# HG changeset patch # User Paul Boddie # Date 1219016418 -7200 # Node ID b035a74d151bf4b7418c82e5a7f66c6a5f90789b # Parent 42c644df055c403960e86efed73af5976e4a6446 Added a class table which should provide run-time support for class compatibility testing. Improved optimisation activities to remove active value-providing instructions only where appropriate. Added more simple-input-employing instructions. Added notes about context discovery and replacement at run-time. Made the raw code dump include class contexts for class attributes where appropriate. Improved the tests of attribute access and invocation. diff -r 42c644df055c -r b035a74d151b README.txt --- a/README.txt Sun Aug 17 20:46:49 2008 +0200 +++ b/README.txt Mon Aug 18 01:40:18 2008 +0200 @@ -9,6 +9,10 @@ Instance attributes are defined only by assignments to attributes of self within __init__ methods. +(These restrictions apply because such attributes are thus explicitly +declared. Module and class attributes can also be finalised in this way in +order to permit certain optimisations.) + Potential Restrictions ---------------------- diff -r 42c644df055c -r b035a74d151b docs/invocation.txt --- a/docs/invocation.txt Sun Aug 17 20:46:49 2008 +0200 +++ b/docs/invocation.txt Mon Aug 18 01:40:18 2008 +0200 @@ -143,3 +143,13 @@ f(obj, 1, 2) # no restrictions on obj obj.m(1, 2) # f(obj, 1, 2) C.m(obj, 1, 2) # f(obj "assert isinstance(obj, C)", 1, 2) + +Context propagation: + + fn = C.m # has context C + fn(obj, 1, 2) # non-instance context -> explicit context required + # must perform isinstance(obj, C) + fn = c.m # table entry for m on C -> replace context + # gives context c + fn(1, 2) # instance context -> no explicit context required + # context c inserted in call diff -r 42c644df055c -r b035a74d151b docs/structures.txt --- a/docs/structures.txt Sun Aug 17 20:46:49 2008 +0200 +++ b/docs/structures.txt Mon Aug 18 01:40:18 2008 +0200 @@ -13,8 +13,8 @@ object context reference reference -Acquiring Values ----------------- +Values and Contexts +------------------- Values are acquired through name lookups and attribute access, yielding the appropriate object reference together with a context reference as @@ -61,7 +61,10 @@ constant's class hierarchy) LoadAddressContext Override loaded context with a - predetermined object + predetermined object (provided + that the object and context are + compatible, which can be tested at + compile-time) LoadAttr Load attribute from Attributes with null contexts or instance contexts compatible with the @@ -85,14 +88,20 @@ * Since only class-originating attributes may cause context overriding, and since class attributes may only be defined within class definitions, the attributes whose context may be modified should be known at compile-time. + (These will be those attributes whose context agrees with their parent + class.) * By recording a special context value for attributes whose context can be overridden, this value can be tested efficiently at run-time where the - appropriate conditions are satisfied. + appropriate conditions are satisfied. (This special context value or + indicator will be present in the object table record for the attribute.) * It should be possible to move the instance compatibility condition testing to compile-time by testing the compatibility of the origin of an attribute - with the class on which it is stored. + with the class on which it is stored. However, some compatibility testing + will still be required if invoking methods via classes, since the instance + will be specified in the argument list instead of being presented in an + attribute lookup instruction. Storing Values -------------- diff -r 42c644df055c -r b035a74d151b micropython/__init__.py --- a/micropython/__init__.py Sun Aug 17 20:46:49 2008 +0200 +++ b/micropython/__init__.py Mon Aug 18 01:40:18 2008 +0200 @@ -71,6 +71,7 @@ self.objtable = None self.paramtable = None + self.clstable = None # Constant records. @@ -113,6 +114,7 @@ objtable = self.get_object_table() paramtable = self.get_parameter_table() + clstable = self.get_class_table() image = [] @@ -235,6 +237,21 @@ return self.objtable + def get_class_table(self): + + "Return a table with details of class compatibility." + + if self.clstable is None: + t = self.clstable = micropython.table.Table() + for module in self.get_modules(): + for obj in module.all_objects: + if isinstance(obj, micropython.inspect.Class): + compatible = [obj] + obj.descendants + compatible_dict = dict([(cls.full_name(), cls) for cls in compatible]) + t.add(obj.full_name(), compatible_dict) + + return self.clstable + def get_parameter_table(self): "Return a table with details of parameters for functions and methods." diff -r 42c644df055c -r b035a74d151b micropython/ast.py --- a/micropython/ast.py Sun Aug 17 20:46:49 2008 +0200 +++ b/micropython/ast.py Mon Aug 18 01:40:18 2008 +0200 @@ -67,6 +67,7 @@ self.importer = importer self.objtable = self.importer.get_object_table() self.paramtable = self.importer.get_parameter_table() + self.clstable = self.importer.get_class_table() self.builtins = self.importer.modules.get("__builtins__") # Desired optimisations. @@ -280,6 +281,13 @@ op = self.code.pop() self.active = None + def remove_active_value(self): + + "Remove the value-providing active instruction if appropriate." + + if self.active_value is self.active: + self.remove_op() + def replace_op(self, op): "Replace the last added instruction with 'op'." @@ -349,7 +357,9 @@ StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored LoadAddressContext, LoadAttr, LoadAttrIndex, # as the object being referenced StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced - TestIdentity, CheckSelf # as one of the operands + TestIdentity, CheckSelf, # as one of the operands + LoadContext, # as the object providing the result + JumpWithFrame # as the target )) def _is_resultant_no_operation(self, instruction): @@ -554,9 +564,8 @@ if self._should_optimise_temp_storage() and \ self._have_temp_compatible_access(): - last = self.last_op() - self.remove_op() - return last + self.remove_active_value() + return self.active else: return self.get_temp() @@ -570,9 +579,7 @@ self._have_simple_input() and \ self._is_simple_input_user(instruction): - if self.active_value is self.active: - self.remove_op() - + self.remove_active_value() instruction.input = self.active_value def _optimise_away_no_operations(self, instruction): @@ -593,8 +600,8 @@ "Discard results which will not be used." - if self._have_input(): - self.remove_op() + if self._have_simple_input(): + self.remove_active_value() # Visitor methods. diff -r 42c644df055c -r b035a74d151b micropython/rsvp.py --- a/micropython/rsvp.py Sun Aug 17 20:46:49 2008 +0200 +++ b/micropython/rsvp.py Mon Aug 18 01:40:18 2008 +0200 @@ -26,7 +26,7 @@ new_code = [] for item in code: if isinstance(item, Attr): - new_code.append((None, item.value and item.value.location)) # no useful context is provided + new_code.append((item.context and item.context.location, item.value and item.value.location)) # no useful context is provided else: new_code.append(item) return new_code diff -r 42c644df055c -r b035a74d151b test.py --- a/test.py Sun Aug 17 20:46:49 2008 +0200 +++ b/test.py Mon Aug 18 01:40:18 2008 +0200 @@ -68,5 +68,6 @@ i.vacuum() ot = i.get_object_table() pt = i.get_parameter_table() + ct = i.get_class_table() # vim: tabstop=4 expandtab shiftwidth=4 diff -r 42c644df055c -r b035a74d151b tests/attributes2.py --- a/tests/attributes2.py Sun Aug 17 20:46:49 2008 +0200 +++ b/tests/attributes2.py Mon Aug 18 01:40:18 2008 +0200 @@ -11,6 +11,12 @@ def f(self): pass e = e + def test(self): + self.e() + self.f() + self.g() + self.h() + class D: e = C.e f = C.f @@ -20,6 +26,12 @@ self.m = self.f return self.m # not known + def test(self): + self.e(1) + self.f(2) + self.g() + self.h() + class E(C): def g(self): return self.f # C.f with context self @@ -27,6 +39,12 @@ self.m = self.f return self.m # not known + def test(self): + self.e() + self.f() + self.g() + self.h() + C.f D.f E.f diff -r 42c644df055c -r b035a74d151b tests/subclass.py --- a/tests/subclass.py Sun Aug 17 20:46:49 2008 +0200 +++ b/tests/subclass.py Mon Aug 18 01:40:18 2008 +0200 @@ -16,7 +16,7 @@ A.a(self) def b(self): - pass + self.a() def __init__(self, x, y): self.x = x