1.1 --- a/rsvp.py Sun Jun 12 00:57:03 2011 +0200
1.2 +++ b/rsvp.py Sun Jun 12 22:14:36 2011 +0200
1.3 @@ -44,11 +44,11 @@
1.4
1.5 * Exception handler PC stack refers to the state of the PC stack
1.6
1.7 - * Registers: current value,
1.8 + * Registers: current context/value,
1.9 + source context/value,
1.10 + current result context/value,
1.11 + current exception value,
1.12 boolean status value,
1.13 - source value,
1.14 - current result,
1.15 - current exception,
1.16 current callable
1.17 """
1.18
1.19 @@ -121,14 +121,21 @@
1.20
1.21 # Registers.
1.22
1.23 + self.value = None
1.24 + self.context = None
1.25 +
1.26 + self.source_value = None
1.27 + self.source_context = None
1.28 +
1.29 + self.result_value = None
1.30 + self.result_context = None
1.31 +
1.32 + self.exception = None
1.33 +
1.34 self.instruction = None
1.35 self.operand = None
1.36 - self.value = None
1.37 self.status = None
1.38 - self.source = None
1.39 self.callable = None
1.40 - self.result = None
1.41 - self.exception = None
1.42
1.43 # Constants.
1.44
1.45 @@ -173,14 +180,21 @@
1.46 print "Handler frame stack", self.handler_local_sp_stack
1.47 print "Handler PC stack", self.handler_pc_stack
1.48 print
1.49 + print "Value", self.value
1.50 + print "Context", self.context
1.51 + print
1.52 + print "Source value", self.source_value
1.53 + print "Source context", self.source_context
1.54 + print
1.55 + print "Result value", self.result_value
1.56 + print "Result context", self.result_context
1.57 + print
1.58 + print "Exception", self.exception
1.59 + print
1.60 print "Instruction", self.instruction
1.61 print "Operand", self.operand
1.62 - print "Value", self.value
1.63 print "Status", self.status
1.64 - print "Source", self.source
1.65 print "Callable", self.callable
1.66 - print "Result", self.result
1.67 - print "Exception", self.exception
1.68
1.69 def show(self, start=None, end=None):
1.70 self.show_memory(self.memory[start:end], self.coverage[start:end], start or 0)
1.71 @@ -387,11 +401,11 @@
1.72 instructions would otherwise have.
1.73 """
1.74
1.75 - value = self.value
1.76 + value, context = self.value, self.context
1.77 if self.instruction.source is not None:
1.78 self.perform(self.instruction.source, 1)
1.79 - self.source = self.value
1.80 - self.value = value
1.81 + self.source_value, self.source_context = self.value, self.context
1.82 + self.value, self.context = value, context
1.83 if self.instruction.input is not None:
1.84 self.perform(self.instruction.input, 1)
1.85
1.86 @@ -416,94 +430,111 @@
1.87 self.push_pc(self.pc + 1)
1.88 return addr
1.89
1.90 + # Low-level instructions.
1.91 +
1.92 + def LoadValue(self, operand):
1.93 + self.value = operand
1.94 +
1.95 + def LoadContext(self, operand):
1.96 + self.context = operand
1.97 +
1.98 # Instructions.
1.99
1.100 def LoadConst(self):
1.101 - self.value = DataValue(self.operand, self.operand)
1.102 + self.LoadContext(self.operand)
1.103 + self.LoadValue(self.operand)
1.104
1.105 def LoadClass(self):
1.106 - self.value = DataValue(PlaceholderContext, self.operand)
1.107 + self.LoadContext(PlaceholderContext)
1.108 + self.LoadValue(self.operand)
1.109
1.110 def LoadFunction(self):
1.111 - self.value = DataValue(ReplaceableContext, self.operand)
1.112 + self.LoadContext(ReplaceableContext)
1.113 + self.LoadValue(self.operand)
1.114
1.115 def LoadName(self):
1.116 frame = self.local_sp_stack[-1]
1.117 - self.value = self.frame_stack[frame + self.operand]
1.118 + data = self.frame_stack[frame + self.operand]
1.119 + self.LoadContext(data.context)
1.120 + self.LoadValue(data.ref)
1.121
1.122 def StoreName(self):
1.123 frame = self.local_sp_stack[-1]
1.124 - self.frame_stack[frame + self.operand] = self.source # uses the source value
1.125 + self.frame_stack[frame + self.operand] = DataValue(self.source_context, self.source_value)
1.126
1.127 LoadTemp = LoadName
1.128
1.129 def StoreTemp(self):
1.130 frame = self.local_sp_stack[-1]
1.131 - self.frame_stack[frame + self.operand] = self.value
1.132 + self.frame_stack[frame + self.operand] = DataValue(self.context, self.value)
1.133
1.134 def LoadAddress(self):
1.135 # Preserve context (potentially null).
1.136 - self.value = self.load(self.operand)
1.137 + data = self.load(self.operand)
1.138 + self.LoadContext(data.context)
1.139 + self.LoadValue(data.ref)
1.140
1.141 def LoadAddressContext(self):
1.142 - value = self.load(self.operand)
1.143 - inst_value = self.value
1.144 - self.value = DataValue(inst_value.ref, value.ref)
1.145 + # Value becomes context.
1.146 + data = self.load(self.operand)
1.147 + self.LoadContext(self.value)
1.148 + self.LoadValue(data.ref)
1.149
1.150 def LoadAddressContextCond(self):
1.151 - value = self.load(self.operand)
1.152 - inst_value = self.value
1.153 - self.value = self._LoadAddressContextCond(value.context, value.ref, inst_value.ref)
1.154 + data = self.load(self.operand)
1.155 + data = self._LoadAddressContextCond(data.context, data.ref, self.value)
1.156 + self.LoadContext(data.context)
1.157 + self.LoadValue(data.ref)
1.158
1.159 def StoreAddress(self):
1.160 # Preserve context.
1.161 - self.save(self.operand, self.source)
1.162 + self.save(self.operand, DataValue(self.source_context, self.source_value))
1.163
1.164 def StoreAddressContext(self):
1.165 # Overwrite context if null.
1.166 - context_value = self.value
1.167 - source_value = self.source
1.168 - self._StoreAddressContext(self.operand, context_value, source_value)
1.169 + self._StoreAddressContext(self.operand, self.context, self.value, self.source_context, self.source_value)
1.170
1.171 def MakeInstance(self):
1.172 size = self.operand
1.173 - value = self.value
1.174 # NOTE: Referencing the instance template.
1.175 - addr = self._MakeObject(size, value.ref - Library.instance_template_size)
1.176 + addr = self._MakeObject(size, self.value - Library.instance_template_size)
1.177 # Introduce object as context for the new object.
1.178 - self.value = DataValue(addr, addr)
1.179 + self.LoadContext(addr)
1.180 + self.LoadValue(addr)
1.181
1.182 def MakeFragment(self):
1.183 size = self.operand
1.184 # Reserve twice the amount of space.
1.185 addr = self._MakeFragment(size, size * 2)
1.186 # NOTE: Context is not relevant for fragments.
1.187 - self.value = DataValue(None, addr)
1.188 + self.LoadContext(None)
1.189 + self.LoadValue(addr)
1.190
1.191 def LoadAttr(self):
1.192 - value = self.value
1.193 # Retrieved context should already be appropriate for the instance.
1.194 # NOTE: Adding 1 to skip any header.
1.195 - self.value = self.load(value.ref + self.operand + 1)
1.196 + data = self.load(self.value + self.operand + 1)
1.197 + self.LoadContext(data.context)
1.198 + self.LoadValue(data.ref)
1.199
1.200 def StoreAttr(self):
1.201 - value = self.value
1.202 # Target should already be an instance.
1.203 # NOTE: Adding 1 to skip any header.
1.204 - self.save(value.ref + self.operand + 1, self.source)
1.205 + self.save(self.value + self.operand + 1, DataValue(self.source_context, self.source_value))
1.206
1.207 def LoadAttrIndex(self):
1.208 - value = self.value
1.209 - data = self.load(value.ref)
1.210 + data = self.load(self.value)
1.211 element = self.objlist[data.classcode + self.operand]
1.212
1.213 if element is not None:
1.214 attr_index, static_attr, offset = element
1.215 if attr_index == self.operand:
1.216 if static_attr:
1.217 - self.value = self.load(offset) # offset is address of class/module attribute
1.218 + data = self.load(offset) # offset is address of class/module attribute
1.219 else:
1.220 - self.value = self.load(value.ref + offset)
1.221 + data = self.load(self.value + offset)
1.222 + self.LoadContext(data.context)
1.223 + self.LoadValue(data.ref)
1.224 return
1.225
1.226 self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance)
1.227 @@ -512,39 +543,38 @@
1.228 # LoadAttrIndexContext not defined.
1.229
1.230 def LoadAttrIndexContextCond(self):
1.231 - inst_value = self.value
1.232 - data = self.load(inst_value.ref)
1.233 + data = self.load(self.value)
1.234 element = self.objlist[data.classcode + self.operand]
1.235
1.236 if element is not None:
1.237 attr_index, static_attr, offset = element
1.238 if attr_index == self.operand:
1.239 if static_attr:
1.240 - loaded_value = self.load(offset) # offset is address of class/module attribute
1.241 - if data.attrcode is None: # absent attrcode == class/module
1.242 - self.value = loaded_value
1.243 - else:
1.244 - self.value = self._LoadAddressContextCond(loaded_value.context, loaded_value.ref, inst_value.ref)
1.245 + loaded_data = self.load(offset) # offset is address of class/module attribute
1.246 + # Absent attrcode == class/module.
1.247 + if data.attrcode is not None:
1.248 + loaded_data = self._LoadAddressContextCond(loaded_data.context, loaded_data.ref, self.value)
1.249 else:
1.250 - self.value = self.load(inst_value.ref + offset)
1.251 + loaded_data = self.load(self.value + offset)
1.252 + self.LoadContext(loaded_data.context)
1.253 + self.LoadValue(loaded_data.ref)
1.254 return
1.255
1.256 self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance)
1.257 return self.RaiseException()
1.258
1.259 def StoreAttrIndex(self):
1.260 - value = self.value
1.261 - data = self.load(value.ref)
1.262 + data = self.load(self.value)
1.263 element = self.objlist[data.classcode + self.operand]
1.264
1.265 if element is not None:
1.266 attr_index, static_attr, offset = element
1.267 if attr_index == self.operand:
1.268 if static_attr:
1.269 - self._StoreAddressContext(offset, value, self.source)
1.270 + self._StoreAddressContext(offset, self.context, self.value, self.source_context, self.source_value)
1.271 return
1.272 else:
1.273 - self.save(value.ref + offset, self.source)
1.274 + self.save(self.value + offset, DataValue(self.source_context, self.source_value))
1.275 return
1.276
1.277 self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance)
1.278 @@ -563,51 +593,46 @@
1.279
1.280 def StoreFrame(self):
1.281 frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
1.282 - self.frame_stack[frame + self.operand] = self.value
1.283 + self.frame_stack[frame + self.operand] = DataValue(self.context, self.value)
1.284
1.285 def StoreFrameIndex(self):
1.286 - value = self.value
1.287 frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
1.288 - data = self.load(value.ref)
1.289 + data = self.load(self.value)
1.290 element = self.paramlist[data.funccode + self.operand]
1.291
1.292 if element is not None:
1.293 # NOTE: Need to ensure correct positioning where a context has been generated.
1.294 param_index, offset = element
1.295 if param_index == self.operand:
1.296 - self.frame_stack[frame + offset] = self.source
1.297 + self.frame_stack[frame + offset] = DataValue(self.source_context, self.source_value)
1.298 return
1.299
1.300 self.exception = self._MakeObject(Library.instance_size, self.type_error_instance)
1.301 return self.RaiseException()
1.302
1.303 def LoadCallable(self):
1.304 - value = self.value
1.305 - data = self.load(value.ref)
1.306 + data = self.load(self.value)
1.307 self.callable = data.codeaddr
1.308
1.309 def StoreCallable(self):
1.310 - value = self.value
1.311 # NOTE: Should improve the representation and permit direct saving.
1.312 - data = self.load(value.ref)
1.313 - self.save(value.ref, data.with_callable(self.callable))
1.314 + data = self.load(self.value)
1.315 + self.save(self.value, data.with_callable(self.callable))
1.316
1.317 - def LoadContext(self):
1.318 - value = self.value
1.319 + def LoadContextIntoValue(self):
1.320 # NOTE: Omission of the context of the context would make things like
1.321 # NOTE: self() inside methods impossible.
1.322 - self.value = DataValue(value.context, value.context)
1.323 + self.LoadValue(self.context)
1.324
1.325 def CheckContext(self):
1.326 - self.status = self.value.ref is not ReplaceableContext
1.327 + self.status = self.value is not ReplaceableContext
1.328
1.329 def CheckClass(self):
1.330 - value = self.value
1.331 - if value.ref in (ReplaceableContext, PlaceholderContext):
1.332 + if self.value in (ReplaceableContext, PlaceholderContext):
1.333 self.status = 0
1.334 return
1.335
1.336 - data = self.load(value.ref)
1.337 + data = self.load(self.value)
1.338
1.339 # Classes are not themselves usable as the self argument.
1.340 # NOTE: This may change at some point.
1.341 @@ -645,7 +670,6 @@
1.342 self.frame_stack.extend([None]) # ExtendFrame(1)
1.343
1.344 def FillDefaults(self):
1.345 - value = self.value
1.346 (nargs, ndefaults) = self.operand
1.347
1.348 # The frame is actually installed as the locals.
1.349 @@ -661,7 +685,7 @@
1.350 pos = nlocals
1.351
1.352 while pos < nargs:
1.353 - self.frame_stack[frame + pos] = self.load(value.ref + default + 1) # skip header
1.354 + self.frame_stack[frame + pos] = self.load(self.value + default + 1) # skip header
1.355 default += 1
1.356 pos += 1
1.357
1.358 @@ -685,21 +709,13 @@
1.359 extra += 1
1.360 pos += 1
1.361
1.362 - self.value = DataValue(ref, ref)
1.363 + self.LoadContext(ref)
1.364 + self.LoadValue(ref)
1.365
1.366 def CheckInstance(self):
1.367 - value = self.value
1.368 - target_value = self.source
1.369 -
1.370 # For the 'self' parameter in an invoked function, the proposed context
1.371 # ('self') is checked against the target's context.
1.372 -
1.373 - self.status = self._CheckInstance(value.ref, target_value.ref)
1.374 -
1.375 - def CheckType(self):
1.376 - value = self.value
1.377 - target_value = self.operand
1.378 - self.status = self._CheckType(value.ref, target_value.ref)
1.379 + self.status = self._CheckInstance(self.value, self.source_value)
1.380
1.381 def JumpInFrame(self):
1.382 codeaddr = self.callable
1.383 @@ -725,10 +741,12 @@
1.384 return self.pull_pc()
1.385
1.386 def LoadResult(self):
1.387 - self.value = self.result
1.388 + self.LoadContext(self.result_context)
1.389 + self.LoadValue(self.result_value)
1.390
1.391 def StoreResult(self):
1.392 - self.result = self.value
1.393 + self.result_context = self.context
1.394 + self.result_value = self.value
1.395
1.396 def Jump(self):
1.397 return self.operand
1.398 @@ -742,10 +760,11 @@
1.399 return self.operand
1.400
1.401 def LoadException(self):
1.402 - self.value = DataValue(self.exception, self.exception)
1.403 + self.LoadContext(self.exception)
1.404 + self.LoadValue(self.exception)
1.405
1.406 def StoreException(self):
1.407 - self.exception = self.value.ref
1.408 + self.exception = self.value
1.409
1.410 def ClearException(self):
1.411 self.exception = None
1.412 @@ -783,13 +802,13 @@
1.413 del self.handler_stack[-nframes:]
1.414
1.415 def CheckException(self):
1.416 - self.status = self.exception is not None and self._CheckInstance(self.exception, self.value.ref)
1.417 + self.status = self.exception is not None and self._CheckInstance(self.exception, self.value)
1.418
1.419 def TestIdentity(self):
1.420 - self.status = self.value.ref == self.source.ref
1.421 + self.status = self.value == self.source_value
1.422
1.423 def TestIdentityAddress(self):
1.424 - self.status = self.value.ref == self.operand
1.425 + self.status = self.value == self.operand
1.426
1.427 # LoadBoolean is implemented in the generated code.
1.428 # StoreBoolean is implemented by testing against the True value.
1.429 @@ -821,22 +840,6 @@
1.430 else:
1.431 return 0
1.432
1.433 - def _CheckType(self, ref, cls):
1.434 - data = self.load(ref)
1.435 - target_data = self.load(cls)
1.436 -
1.437 - # Insist on instance vs. class.
1.438 -
1.439 - if data.attrcode is None: # absent attrcode == class/module
1.440 - return 0
1.441 -
1.442 - if target_data.attrcode is not None: # present attrcode == instance
1.443 - return 0
1.444 -
1.445 - # Return whether the types match.
1.446 -
1.447 - return data.classcode == target_data.classcode
1.448 -
1.449 def _MakeObject(self, size, ref):
1.450 # Load the template.
1.451 data = self.load(ref)
1.452 @@ -851,21 +854,21 @@
1.453 self.save(addr, FragmentObject(occupied, size))
1.454 return addr
1.455
1.456 - def _LoadAddressContextCond(self, context, ref, inst_ref):
1.457 + def _LoadAddressContextCond(self, context, value, inst_value):
1.458 # Check the instance context against the target's context.
1.459 # This provides the context overriding for methods.
1.460 - if context is ReplaceableContext or context is not PlaceholderContext and self._CheckInstance(inst_ref, context):
1.461 + if context is ReplaceableContext or context is not PlaceholderContext and self._CheckInstance(inst_value, context):
1.462 # Replace the context with the instance.
1.463 - return DataValue(inst_ref, ref)
1.464 + return DataValue(inst_value, value)
1.465 else:
1.466 - return DataValue(context, ref)
1.467 + return DataValue(context, value)
1.468
1.469 - def _StoreAddressContext(self, location, context_value, source_value):
1.470 - if source_value.context is ReplaceableContext:
1.471 - context = context_value.ref
1.472 + def _StoreAddressContext(self, location, context, value, source_context, source_value):
1.473 + if source_context is ReplaceableContext:
1.474 + context = value
1.475 else:
1.476 - context = source_value.context
1.477 - self.save(location, DataValue(context, source_value.ref))
1.478 + context = source_context
1.479 + self.save(location, DataValue(context, source_value))
1.480
1.481 # Convenience functions.
1.482