# HG changeset patch # User Paul Boddie # Date 1255136969 -7200 # Node ID f76003d45947d5489161186cce2a2b7f2d47624e # Parent d395dfacb98db11a36333041ab6ab2a193602357 Introduced a DataValue class to replace generic tuples as the run-time value type. diff -r d395dfacb98d -r f76003d45947 micropython/data.py --- a/micropython/data.py Sat Oct 10 01:52:27 2009 +0200 +++ b/micropython/data.py Sat Oct 10 03:09:29 2009 +0200 @@ -44,7 +44,7 @@ where each such object is defined. """ -from micropython.program import DataObject, ReplaceableContext, PlaceholderContext +from micropython.program import DataObject, DataValue, ReplaceableContext, PlaceholderContext def shortrepr(obj): if obj is None: @@ -433,7 +433,7 @@ def as_raw(self, objtable, paramtable): return [ - ( + DataValue( self.get_context() and self.get_context().location, self.get_value() and self.get_value().location ) diff -r d395dfacb98d -r f76003d45947 micropython/program.py --- a/micropython/program.py Sat Oct 10 01:52:27 2009 +0200 +++ b/micropython/program.py Sat Oct 10 03:09:29 2009 +0200 @@ -36,6 +36,19 @@ item.location = location + i return self.code +class DataValue: + + "A representation of a raw program value." + + def __init__(self, context, ref): + self.context = context + self.ref = ref + + def __repr__(self): + return "%r, %r" % ( + self.context, self.ref + ) + class DataObject: "A representation of a raw program data object." diff -r d395dfacb98d -r f76003d45947 rsvp.py --- a/rsvp.py Sat Oct 10 01:52:27 2009 +0200 +++ b/rsvp.py Sat Oct 10 03:09:29 2009 +0200 @@ -52,7 +52,7 @@ current callable """ -from micropython.program import ReplaceableContext, PlaceholderContext, FragmentObject +from micropython.program import DataValue, ReplaceableContext, PlaceholderContext, FragmentObject from rsvplib import Library class IllegalInstruction(Exception): @@ -281,10 +281,10 @@ # NOTE: Assumptions about headers and content made. attr_location = module.location + 1 + attr.position - context, ref = self.load(attr_location) + value = self.load(attr_location) - if ref is not None: - content = self.load(ref + 1) + if value is not None: + content = self.load(value.ref + 1) print label, expected, content success = success and (int(expected) == content) else: @@ -380,13 +380,13 @@ # Instructions. def LoadConst(self): - self.value = self.operand, self.operand + self.value = DataValue(self.operand, self.operand) def LoadClass(self): - self.value = PlaceholderContext, self.operand + self.value = DataValue(PlaceholderContext, self.operand) def LoadFunction(self): - self.value = ReplaceableContext, self.operand + self.value = DataValue(ReplaceableContext, self.operand) def LoadName(self): frame = self.local_sp_stack[-1] @@ -407,14 +407,14 @@ self.value = self.load(self.operand) def LoadAddressContext(self): - context, ref = self.load(self.operand) - inst_context, inst_ref = self.value - self.value = inst_ref, ref + value = self.load(self.operand) + inst_value = self.value + self.value = DataValue(inst_value.ref, value.ref) def LoadAddressContextCond(self): - context, ref = self.load(self.operand) - inst_context, inst_ref = self.value - self.value = self._LoadAddressContextCond(context, ref, inst_ref) + value = self.load(self.operand) + inst_value = self.value + self.value = self._LoadAddressContextCond(value.context, value.ref, inst_value.ref) def StoreAddress(self): # Preserve context. @@ -422,43 +422,43 @@ def StoreAddressContext(self): # Overwrite context if null. - context_context, context_ref = self.value - source_context, source_ref = self.source - if source_context is ReplaceableContext: - context = context_ref + context_value = self.value + source_value = self.source + if source_value.context is ReplaceableContext: + context = context_value.ref else: - context = source_context - self.save(self.operand, (context, source_ref)) + context = source_value.context + self.save(self.operand, DataValue(context, source_value.ref)) def MakeInstance(self): size = self.operand - context, ref = self.value + value = self.value # NOTE: Referencing the instance template. - addr = self._MakeObject(size, ref - 1) + addr = self._MakeObject(size, value.ref - 1) # Introduce object as context for the new object. - self.value = addr, addr + self.value = DataValue(addr, addr) def MakeFragment(self): size = self.operand addr = self._MakeFragment(size) # NOTE: Context is not relevant for fragments. - self.value = None, addr + self.value = DataValue(None, addr) def LoadAttr(self): - context, ref = self.value + value = self.value # Retrieved context should already be appropriate for the instance. # NOTE: Adding 1 to skip any header. - self.value = self.load(ref + self.operand + 1) + self.value = self.load(value.ref + self.operand + 1) def StoreAttr(self): - context, ref = self.value + value = self.value # Target should already be an instance. # NOTE: Adding 1 to skip any header. - self.save(ref + self.operand + 1, self.source) + self.save(value.ref + self.operand + 1, self.source) def LoadAttrIndex(self): - context, ref = self.value - data = self.load(ref) + value = self.value + data = self.load(value.ref) element = self.objlist[data.classcode + self.operand] if element is not None: @@ -467,7 +467,7 @@ if static_attr: self.value = self.load(offset) # offset is address of class/module attribute else: - self.value = self.load(ref + offset) + self.value = self.load(value.ref + offset) return self.exception = self._MakeObject(2, self.attr_error_instance) @@ -476,29 +476,29 @@ # LoadAttrIndexContext not defined. def LoadAttrIndexContextCond(self): - inst_context, inst_ref = self.value - data = self.load(inst_ref) + inst_value = self.value + data = self.load(inst_value.ref) element = self.objlist[data.classcode + self.operand] if element is not None: attr_index, static_attr, offset = element if attr_index == self.operand: if static_attr: - loaded_context, loaded_ref = self.load(offset) # offset is address of class/module attribute + loaded_value = self.load(offset) # offset is address of class/module attribute if data.attrcode is None: # absent attrcode == class/module - self.value = loaded_context, loaded_ref + self.value = loaded_value else: - self.value = self._LoadAddressContextCond(loaded_context, loaded_ref, inst_ref) + self.value = self._LoadAddressContextCond(loaded_value.context, loaded_value.ref, inst_value.ref) else: - self.value = self.load(inst_ref + offset) + self.value = self.load(inst_value.ref + offset) return self.exception = self._MakeObject(2, self.attr_error_instance) return self.RaiseException() def StoreAttrIndex(self): - context, ref = self.value - data = self.load(ref) + value = self.value + data = self.load(value.ref) element = self.objlist[data.classcode + self.operand] if element is not None: @@ -508,7 +508,7 @@ self.exception = self._MakeObject(2, self.type_error_instance) return self.RaiseException() else: - self.save(ref + offset, self.source) + self.save(value.ref + offset, self.source) return self.exception = self._MakeObject(2, self.attr_error_instance) @@ -530,9 +530,9 @@ self.frame_stack[frame + self.operand] = self.value def StoreFrameIndex(self): - context, ref = self.value + value = self.value frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame - data = self.load(ref) + data = self.load(value.ref) element = self.paramlist[data.funccode + self.operand] if element is not None: @@ -546,32 +546,32 @@ return self.RaiseException() def LoadCallable(self): - context, ref = self.value - data = self.load(ref) + value = self.value + data = self.load(value.ref) self.callable = data.codeaddr def StoreCallable(self): - context, ref = self.value + value = self.value # NOTE: Should improve the representation and permit direct saving. - data = self.load(ref) - self.save(ref, data.with_callable(self.callable)) + data = self.load(value.ref) + self.save(value.ref, data.with_callable(self.callable)) def LoadContext(self): - context, ref = self.value + value = self.value # NOTE: Omission of the context of the context would make things like # NOTE: self() inside methods impossible. - self.value = context, context + self.value = DataValue(value.context, value.context) def CheckContext(self): - self.status = self.value[1] is not ReplaceableContext + self.status = self.value.ref is not ReplaceableContext def CheckClass(self): - context, ref = self.value - if ref in (ReplaceableContext, PlaceholderContext): + value = self.value + if value.ref in (ReplaceableContext, PlaceholderContext): self.status = 0 return - data = self.load(ref) + data = self.load(value.ref) # Classes are not themselves usable as the self argument. # NOTE: This may change at some point. @@ -609,7 +609,7 @@ self.frame_stack.extend([None]) # ExtendFrame(1) def FillDefaults(self): - context, ref = self.value + value = self.value (nargs, ndefaults) = self.operand # The frame is actually installed as the locals. @@ -625,7 +625,7 @@ pos = nlocals while pos < nargs: - self.frame_stack[frame + pos] = self.load(ref + default + 1) # skip header + self.frame_stack[frame + pos] = self.load(value.ref + default + 1) # skip header default += 1 pos += 1 @@ -649,15 +649,15 @@ extra += 1 pos += 1 - self.value = ref, ref + self.value = DataValue(ref, ref) def CheckSelf(self): - context, ref = self.value - context_context, context_ref = self.source + value = self.value + context_value = self.source # Check the details of the proposed context and the target's context. - self.status = self._CheckInstance(ref, context_ref) + self.status = self._CheckInstance(value.ref, context_value.ref) def JumpInFrame(self): codeaddr = self.callable @@ -700,10 +700,10 @@ return self.operand def LoadException(self): - self.value = self.exception, self.exception + self.value = DataValue(self.exception, self.exception) def StoreException(self): - self.exception = self.value[1] + self.exception = self.value.ref def ClearException(self): self.exception = None @@ -729,13 +729,13 @@ self.handler_stack.pop() def CheckException(self): - self.status = self.exception is not None and self._CheckInstance(self.exception, self.value[1]) + self.status = self.exception is not None and self._CheckInstance(self.exception, self.value.ref) def TestIdentity(self): - self.status = self.value[1] == self.source[1] + self.status = self.value.ref == self.source.ref def TestIdentityAddress(self): - self.status = self.value[1] == self.operand + self.status = self.value.ref == self.operand # LoadBoolean is implemented in the generated code. # StoreBoolean is implemented by testing against the True value. @@ -787,9 +787,9 @@ # This provides the context overriding for methods. if context is ReplaceableContext or context is not PlaceholderContext and self._CheckInstance(inst_ref, context): # Replace the context with the instance. - return inst_ref, ref + return DataValue(inst_ref, ref) else: - return context, ref + return DataValue(context, ref) # Convenience functions. diff -r d395dfacb98d -r f76003d45947 rsvplib.py --- a/rsvplib.py Sat Oct 10 01:52:27 2009 +0200 +++ b/rsvplib.py Sat Oct 10 03:09:29 2009 +0200 @@ -19,6 +19,7 @@ this program. If not, see . """ +from micropython.program import DataValue import operator class Library: @@ -62,20 +63,22 @@ # Get operands addresses. - left_context, left = self.frame_stack[frame] - right_context, right = self.frame_stack[frame + 1] + left_value = self.frame_stack[frame] + right_value = self.frame_stack[frame + 1] # Test operand suitability. # NOTE: Support other types. - if not (self.machine._CheckInstance(left, self.int_class) and self.machine._CheckInstance(right, self.int_class)): + if not (self.machine._CheckInstance(left_value.ref, self.int_class) and + self.machine._CheckInstance(right_value.ref, self.int_class)): + self.machine.exception = self.machine._MakeObject(2, self.type_error_instance) return self.machine.RaiseException() # NOTE: Assume single location for data. - left_data = left + 1 - right_data = right + 1 + left_data = left_value.ref + 1 + right_data = right_value.ref + 1 # Make a new object. @@ -89,38 +92,40 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.result = addr, addr + self.machine.result = DataValue(addr, addr) def builtins_logical_op(self, operand_class, op, true_if_incompatible): frame = self.local_sp_stack[-1] # Get operands addresses. - left_context, left = self.frame_stack[frame] - right_context, right = self.frame_stack[frame + 1] + left_value = self.frame_stack[frame] + right_value = self.frame_stack[frame + 1] # Test operand suitability. # NOTE: Handle comparisons of incompatible types more appropriately. - if not (self.machine._CheckInstance(left, operand_class) and self.machine._CheckInstance(right, operand_class)): + if not (self.machine._CheckInstance(left_value.ref, operand_class) and + self.machine._CheckInstance(right_value.ref, operand_class)): + if true_if_incompatible: - self.machine.result = self.true_constant, self.true_constant + self.machine.result = DataValue(self.true_constant, self.true_constant) else: - self.machine.result = self.false_constant, self.false_constant + self.machine.result = DataValue(self.false_constant, self.false_constant) return # NOTE: Assume single location for data. - left_data = left + 1 - right_data = right + 1 + left_data = left_value.ref + 1 + right_data = right_value.ref + 1 # Test the data. # NOTE: The data is considered ready to use. if op(self.machine.load(left_data), self.machine.load(right_data)): - self.machine.result = self.true_constant, self.true_constant + self.machine.result = DataValue(self.true_constant, self.true_constant) else: - self.machine.result = self.false_constant, self.false_constant + self.machine.result = DataValue(self.false_constant, self.false_constant) # Operators. # Although this takes a short-cut by using the operator module, testing is @@ -185,42 +190,42 @@ # Get operands addresses. - left_context, left = self.frame_stack[frame] + left_value = self.frame_stack[frame] # Test operand suitability. - if not self.machine._CheckInstance(left, self.int_class): + if not self.machine._CheckInstance(left_value.ref, self.int_class): self.machine.exception = self.machine._MakeObject(2, self.type_error_instance) return self.machine.RaiseException() # NOTE: Assume single location for data. - left_data = left + 1 + left_data = left_value.ref + 1 # Test the data. # NOTE: The data is considered ready to use. if self.machine.load(left_data) != 0: - self.machine.result = self.true_constant, self.true_constant + self.machine.result = DataValue(self.true_constant, self.true_constant) else: - self.machine.result = self.false_constant, self.false_constant + self.machine.result = DataValue(self.false_constant, self.false_constant) def builtins_int_neg(self): frame = self.local_sp_stack[-1] # Get operands addresses. - left_context, left = self.frame_stack[frame] + left_value = self.frame_stack[frame] # Test operand suitability. - if not self.machine._CheckInstance(left, self.int_class): + if not self.machine._CheckInstance(left_value.ref, self.int_class): self.machine.exception = self.machine._MakeObject(2, self.type_error_instance) return self.machine.RaiseException() # NOTE: Assume single location for data. - left_data = left + 1 + left_data = left_value.ref + 1 # Make a new object. @@ -234,7 +239,7 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.result = addr, addr + self.machine.result = DataValue(addr, addr) # Various built-in methods. @@ -243,8 +248,8 @@ # Get operands addresses. - left_context, left = self.frame_stack[frame] - self.machine.result = left, left + left_value = self.frame_stack[frame] + self.machine.result = DataValue(left_value.ref, left_value.ref) def builtins_list_new(self): frame = self.local_sp_stack[-1] @@ -252,16 +257,16 @@ # The first parameter should be empty. # NOTE: Specific copying of tuples/lists. - args_context, args = self.frame_stack[frame + 1] + args_value = self.frame_stack[frame + 1] # Test operand suitability. - if self.machine._CheckInstance(args, self.list_class): - _x, sequence = self.machine.load(args + 1) - header = self.machine.load(sequence) + if self.machine._CheckInstance(args_value.ref, self.list_class): + sequence = self.machine.load(args_value.ref + 1) + header = self.machine.load(sequence.ref) size = header.occupied_size - elif self.machine._CheckInstance(args, self.tuple_class): - sequence = args + elif self.machine._CheckInstance(args_value.ref, self.tuple_class): + sequence = args_value.ref header = self.machine.load(sequence) size = header.size else: @@ -277,34 +282,34 @@ # Make the list instance. addr = self.machine._MakeObject(2, self.list_instance) - self.machine.save(addr + 1, (None, new_fragment)) + self.machine.save(addr + 1, DataValue(None, new_fragment)) - self.machine.result = addr, addr + self.machine.result = DataValue(addr, addr) def builtins_list_getitem(self): frame = self.local_sp_stack[-1] # Get the operand address. - item_context, item = self.frame_stack[frame + 1] + item_value = self.frame_stack[frame + 1] # Get the list address. - obj_context, obj = self.frame_stack[frame] + obj_value = self.frame_stack[frame] # Get the fragment address. # NOTE: Assume single location for header. - _x, fragment = self.machine.load(obj + 1) + fragment = self.machine.load(obj_value.ref + 1) # Get the fragment header. - header = self.machine.load(fragment) + header = self.machine.load(fragment.ref) nelements = header.occupied_size - 1 # NOTE: Assume single location for data and header. - item_pos = self.machine.load(item + 1) + item_pos = self.machine.load(item_value.ref + 1) if item_pos >= 0 and item_pos < nelements: pass @@ -316,23 +321,23 @@ # NOTE: Assume single location for header. - self.machine.result = self.machine.load(fragment + 1 + item_pos) + self.machine.result = self.machine.load(fragment.ref + 1 + item_pos) def builtins_list_len(self): frame = self.local_sp_stack[-1] # Get the list address. - obj_context, obj = self.frame_stack[frame] + obj_value = self.frame_stack[frame] # Get the fragment address. # NOTE: Assume single location for header. - _x, fragment = self.machine.load(obj + 1) + fragment = self.machine.load(obj_value.ref + 1) # Get the fragment header. - header = self.machine.load(fragment) + header = self.machine.load(fragment.ref) nelements = header.occupied_size - 1 # Make a new object. @@ -347,32 +352,32 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.result = addr, addr + self.machine.result = DataValue(addr, addr) def builtins_list_append(self): frame = self.local_sp_stack[-1] # Get operand address. - arg_context, arg = self.frame_stack[frame + 1] + arg_value = self.frame_stack[frame + 1] # Get the list address. - obj_context, obj = self.frame_stack[frame] + obj_value = self.frame_stack[frame] # Get the fragment address. # NOTE: Assume single location for header. - _x, fragment = self.machine.load(obj + 1) + fragment = self.machine.load(obj_value.ref + 1) # Get the fragment header. - header = self.machine.load(fragment) + header = self.machine.load(fragment.ref) # Attempt to add the reference. if header.occupied_size < header.allocated_size: - self.machine.save(fragment + header.occupied_size, (arg_context, arg)) + self.machine.save(fragment.ref + header.occupied_size, arg_value) header.occupied_size += 1 else: @@ -384,26 +389,26 @@ # Copy existing elements. for i in range(1, header.allocated_size): - self.machine.save(new_fragment + i, self.machine.load(fragment + i)) + self.machine.save(new_fragment + i, self.machine.load(fragment.ref + i)) - self.machine.save(new_fragment + header.allocated_size, (arg_context, arg)) + self.machine.save(new_fragment + header.allocated_size, arg_value) # Set the new fragment in the object. # NOTE: The old fragment could be deallocated. - self.machine.save(obj + 1, (None, new_fragment)) + self.machine.save(obj_value.ref + 1, DataValue(None, new_fragment)) def builtins_tuple_len(self): frame = self.local_sp_stack[-1] # Get the tuple address. - obj_context, obj = self.frame_stack[frame] + obj_value = self.frame_stack[frame] # Get the header. # NOTE: Assume single location for header. - header = self.machine.load(obj) + header = self.machine.load(obj_value.ref) nelements = header.size - 1 # Make a new object. @@ -418,28 +423,28 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.result = addr, addr + self.machine.result = DataValue(addr, addr) def builtins_tuple_getitem(self): frame = self.local_sp_stack[-1] # Get the operand address. - item_context, item = self.frame_stack[frame + 1] + item_value = self.frame_stack[frame + 1] # Get the tuple address. - obj_context, obj = self.frame_stack[frame] + obj_value = self.frame_stack[frame] # Get the header. # NOTE: Assume single location for header. - header = self.machine.load(obj) + header = self.machine.load(obj_value.ref) nelements = header.size - 1 # NOTE: Assume single location for data and header. - item_pos = self.machine.load(item + 1) + item_pos = self.machine.load(item_value.ref + 1) if item_pos >= 0 and item_pos < nelements: pass @@ -451,7 +456,7 @@ # NOTE: Assume single location for header. - self.machine.result = self.machine.load(obj + 1 + item_pos) + self.machine.result = self.machine.load(obj_value.ref + 1 + item_pos) def builtins_object_init(self): pass