# HG changeset patch # User Paul Boddie # Date 1243124193 -7200 # Node ID 09ae448806d1c6361c576d3e179cb9145e9b8190 # Parent d63a8400ce56d5ee6f8cdb4311dd73c069ea8845 Added a StoreAddressContext instruction for class attribute initialisation. Fixed the mechanism behind LoadAttrIndexContextCond and LoadAddressContextCond since it failed to provide the appropriate instance context for instance accesses. Added a LoadFunction instruction in order to distinguish between constants which have no context information and those which do. diff -r d63a8400ce56 -r 09ae448806d1 docs/assignment.txt --- a/docs/assignment.txt Sun May 24 00:21:41 2009 +0200 +++ b/docs/assignment.txt Sun May 24 02:16:33 2009 +0200 @@ -37,8 +37,10 @@ local preserved StoreName global (module) preserved StoreAddress StoreAttrIndex instance preserved StoreAttr StoreAttrIndex + class -> class StoreAddressContext - Class assignments are not permitted + Class assignments are not permitted except during initialisation and hence + employ no unoptimised instruction Access types: @@ -47,7 +49,7 @@ local preserved LoadName global (module) preserved LoadAddress LoadAttrIndex class preserved LoadAddress LoadAttrIndex - class via instance overridden LoadAddressContext(Cond) LoadAttrIndexContext(Cond) + class via instance -> instance LoadAddressContext(Cond) LoadAttrIndexContext(Cond) instance preserved LoadAttr LoadAttrIndex Access to a namespace may not preserve the stored context @@ -56,7 +58,7 @@ Access to stored value with... Effect on context ------------------------------ ----------------- - compatible class as context overridden + compatible class as context -> instance incompatible class as context preserved null context preserved other context (instance) preserved @@ -66,12 +68,12 @@ Class Class attribute Context of attribute Instruction ----- --------------- -------------------- ----------- known constant preserved LoadAddress - known constant overridden LoadAddressContext + known constant -> instance LoadAddressContext known not constant preserved LoadAddress (attribute may always be preserved) - known not constant overridden LoadAddressContext (attribute may always be overridden) + known not constant -> instance LoadAddressContext (attribute may always be overridden) known not constant not known LoadAddressContextCond (perform context check) not known not known preserved LoadAttrIndex (attribute may have preserved context in all classes) - not known not known overridden LoadAttrIndexContext (attribute may have overridden context in all classes) + not known not known -> instance LoadAttrIndexContext (attribute may have overridden context in all classes) not known not known not known LoadAttrIndexContextCond (perform context check for class attribute access) Since the object table encodes sufficient information (an instance must be diff -r d63a8400ce56 -r 09ae448806d1 docs/concepts.txt --- a/docs/concepts.txt Sun May 24 00:21:41 2009 +0200 +++ b/docs/concepts.txt Sun May 24 02:16:33 2009 +0200 @@ -70,15 +70,18 @@ Contexts in Acquired Values --------------------------- -There are two classes of instructions which provide values: +There are three classes of instructions which provide values: Instruction Purpose Context Operations ----------- ------- ------------------ - LoadConst Load class, function, Combine null context with - module, constant loaded object +1) LoadConst Load class, module, Use loaded object with itself + constant as context - LoadAddress* Load attribute from Preserve or override stored +2) LoadFunction Load function Combine null context with + loaded object + +3) LoadAddress* Load attribute from Preserve or override stored LoadAttr* class, module, context (as described in instance assignment.txt) @@ -90,31 +93,34 @@ Contexts in Stored Values ------------------------- -There is only one class of instruction for storing values: +There are two classes of instruction for storing values: - Instruction Purpose Context Operations - ----------- ------- ------------------ + Instruction Purpose Context Operations + ----------- ------- ------------------ - StoreAddress Store attribute in a Preserve context; note that no - known object test for class attribute - assignment should be necessary - since this instruction should only - be generated for module globals +1) StoreAddress Store attribute in a Preserve context; note that no + known object test for class attribute + assignment should be necessary + since this instruction should only + be generated for module globals - StoreAttr Store attribute in an Preserve context; note that no - instance test for class attribute - assignment should be necessary - since this instruction should only - be generated for self accesses + StoreAttr Store attribute in an Preserve context; note that no + instance test for class attribute + assignment should be necessary + since this instruction should only + be generated for self accesses - StoreAttrIndex Store attribute in an Preserve context; since the index - unknown object lookup could yield a class - attribute, a test of the nature of - the nature of the structure is - necessary in order to prevent - assignments to classes + StoreAttrIndex Store attribute in an Preserve context; since the index + unknown object lookup could yield a class + attribute, a test of the nature of + the nature of the structure is + necessary in order to prevent + assignments to classes -Note that contexts are never changed in the stored value: they are preserved. +2) StoreAddressContext Store attribute in a Override context if appropriate; + known object if the value has a null context, + permit the target to take + ownership of the value See assignment.txt for details. diff -r d63a8400ce56 -r 09ae448806d1 micropython/ast.py --- a/micropython/ast.py Sun May 24 00:21:41 2009 +0200 +++ b/micropython/ast.py Sun May 24 02:16:33 2009 +0200 @@ -46,8 +46,8 @@ # Name access instructions, for use with the appropriate handlers. - name_load_instructions = (LoadName, LoadAddress) - name_store_instructions = (StoreName, StoreAddress) + name_load_instructions = (LoadName, LoadAddress, None) + name_store_instructions = (StoreName, StoreAddress, StoreAddressContext) def __init__(self, module, program): @@ -183,7 +183,7 @@ # Invoke the appropriate initialiser. - self.new_op(LoadConst(init_method)) + self.new_op(LoadFunction(init_method)) self.new_op(LoadCallable()) self.new_op(JumpWithFrame()) @@ -587,7 +587,7 @@ # Only store the name when visiting this node from outside. if self.unit is not node.unit: - self.new_op(LoadConst(node.unit)) + self.new_op(LoadFunction(node.unit)) self.record_value() self._visitName(node, self.name_store_instructions) # AssName equivalent @@ -661,7 +661,7 @@ if self.unit is not node.unit: temp = self._generateFunctionDefaults(node.unit) - self.new_op(LoadConst(node.unit)) + self.new_op(LoadFunction(node.unit)) # Populate the new object required for the function. diff -r d63a8400ce56 -r 09ae448806d1 micropython/opt.py --- a/micropython/opt.py Sun May 24 00:21:41 2009 +0200 +++ b/micropython/opt.py Sun May 24 02:16:33 2009 +0200 @@ -158,7 +158,7 @@ # NOTE: Removed StoreName, since this would then demand population of # NOTE: locals/frames. - return isinstance(instruction, StoreAddress) and \ + return isinstance(instruction, (StoreAddress, StoreAddressContext)) and \ instruction.attr.assignments == 1 def is_simple_input(self, instruction): @@ -186,6 +186,7 @@ LoadAttrIndexContextCond, # as the object being referenced StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced StoreFrameIndex, # as the object being referenced + StoreAddressContext, # as the context LoadCallable, TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands CheckException, CheckFrame, MakeObject, diff -r d63a8400ce56 -r 09ae448806d1 micropython/rsvp.py --- a/micropython/rsvp.py Sun May 24 00:21:41 2009 +0200 +++ b/micropython/rsvp.py Sun May 24 02:16:33 2009 +0200 @@ -154,7 +154,8 @@ # Access to stored constant data. -class LoadConst(Address): "Load the constant, class, function, module from the specified location." +class LoadConst(Address): "Load the constant, class, module from the specified location." +class LoadFunction(Address): "Load the function from the specified location." # Access within an invocation frame. @@ -167,9 +168,10 @@ class LoadAddress(Address): "Load the current value from the given fixed attribute address." class StoreAddress(Address): "Store the source value into the given fixed attribute address." -class LoadAddressContext(Address): "Load the current value from the given fixed attribute address, making the current value the context." +class LoadAddressContext(Address): "Load the current value from the given fixed attribute address, using the current value as context." +class StoreAddressContext(Address): "Store the current value into the given fixed attribute address, using the current value as context." class LoadAddressContextCond(Address): - """Load the current value from the given fixed attribute address, only making the current value the + """Load the current value from the given fixed attribute address, only using the current value as context if the attribute is compatible.""" class MakeObject(Immediate): "Make a new object. There isn't a complementary DropObject." diff -r d63a8400ce56 -r 09ae448806d1 micropython/trans.py --- a/micropython/trans.py Sun May 24 00:21:41 2009 +0200 +++ b/micropython/trans.py Sun May 24 02:16:33 2009 +0200 @@ -921,14 +921,18 @@ 'classes', and using the given 'node' as the source of the access. """ - NameInstruction, AddressInstruction = classes + NameInstruction, AddressInstruction, AddressContextInstruction = classes if scope == "local": unit = self.unit if isinstance(unit, Function): self.new_op(NameInstruction(unit.all_locals()[name])) elif isinstance(unit, Class): - self.new_op(AddressInstruction(unit.all_class_attributes()[name])) + if AddressContextInstruction is not None: + self.new_op(LoadConst(unit)) + self.new_op(AddressContextInstruction(unit.all_class_attributes()[name])) + else: + self.new_op(AddressInstruction(unit.all_class_attributes()[name])) elif isinstance(unit, Module): self.new_op(AddressInstruction(unit.module_attributes()[name])) else: diff -r d63a8400ce56 -r 09ae448806d1 rsvp.py --- a/rsvp.py Sun May 24 00:21:41 2009 +0200 +++ b/rsvp.py Sun May 24 02:16:33 2009 +0200 @@ -348,6 +348,9 @@ # Instructions. def LoadConst(self): + self.value = self.operand, self.operand + + def LoadFunction(self): self.value = None, self.operand # context of constant is not interesting def LoadName(self): @@ -376,12 +379,22 @@ def LoadAddressContextCond(self): context, ref = self.load(self.operand) inst_context, inst_ref = self.value - self.value = self._LoadAddressContextCond(context, ref, inst_context, inst_ref) + self.value = self._LoadAddressContextCond(context, ref, inst_ref) def StoreAddress(self): # Preserve context. self.save(self.operand, self.source) + def StoreAddressContext(self): + # Overwrite context if null. + context_context, context_ref = self.value + source_context, source_ref = self.source + if source_context is None: + context = context_ref + else: + context = source_context + self.save(self.operand, (context, source_ref)) + def MakeObject(self): size = self.operand context, ref = self.value @@ -436,7 +449,10 @@ if attr_index == self.operand: if class_attr: loaded_context, loaded_ref = self.load(offset) # offset is address of class attribute - self.value = self._LoadAddressContextCond(loaded_context, loaded_ref, context, ref) + if data.attrcode is None: # absent attrcode == class + self.value = loaded_context, loaded_ref + else: + self.value = self._LoadAddressContextCond(loaded_context, loaded_ref, ref) else: self.value = self.load(ref + offset) else: @@ -687,7 +703,10 @@ data = self.load(ref) target_data = self.load(cls) - # Insist on a class. + # Insist on instance vs. class. + + if data.attrcode is None: # absent attrcode == class + return 0 if target_data.attrcode is not None: # present attrcode == instance return 0 @@ -709,7 +728,7 @@ self.save(addr, data.with_size(size)) return addr - def _LoadAddressContextCond(self, context, ref, inst_context, inst_ref): + def _LoadAddressContextCond(self, context, ref, inst_ref): # Check the instance context against the target's context. diff -r d63a8400ce56 -r 09ae448806d1 tests/attributes_class_copy.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/attributes_class_copy.py Sun May 24 02:16:33 2009 +0200 @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +class C: + clsattr = 123 + clsattr2 = clsattr + +x = 0 # prevent optimisation of assignments +x = C # prevent optimisation of assignments +a = x.clsattr +b = x.clsattr2 + +# vim: tabstop=4 expandtab shiftwidth=4