# HG changeset patch # User Paul Boddie # Date 1203212284 -3600 # Node ID 7adb33e8b1d19969dcc395dbaeacca7352ebb669 # Parent 8a50d440af2fa4c58dfe283add85f7f75ca71b55 Moved deliberately failing tests to a special directory. Added support for generating attribute access instructions. Added further tests of class and instance attributes. Added optimisation of collective predictable attribute accesses. diff -r 8a50d440af2f -r 7adb33e8b1d1 README.txt --- a/README.txt Fri Feb 15 23:50:15 2008 +0100 +++ b/README.txt Sun Feb 17 02:38:04 2008 +0100 @@ -316,6 +316,10 @@ containers" would be used exclusively for this purpose; the StoreAttrIndex instruction would be used exclusively for all other attribute assignments. +To ensure the "sealing" of modules and classes, entries in the attribute +lookup table would encode whether a class or module is being accessed, so +that the StoreAttrIndex instruction could reject such accesses. + Constant Attribute Values ------------------------- diff -r 8a50d440af2f -r 7adb33e8b1d1 micropython/ast.py --- a/micropython/ast.py Fri Feb 15 23:50:15 2008 +0100 +++ b/micropython/ast.py Sun Feb 17 02:38:04 2008 +0100 @@ -123,6 +123,9 @@ def new_op(self, op): self.code.append(op) + def replace_op(self, op): + self.code[-1] = op + def last_op(self): return self.code[-1] @@ -134,6 +137,27 @@ def dispatch(self, node, *args): return ASTVisitor.dispatch(self, node, *args) + def _visitAttr(self, node, classes): + AttrInstruction, AttrIndexInstruction = classes + self.dispatch(node.expr) + + # NOTE: Only simple cases are used for optimisations. + + last = self.last_op() + if isinstance(last, (LoadName, LoadAttr)) and last.attr.assignments == 1: + + # Get the details of the access. + + target = last.attr.value + target_name = target.full_name() + table_entry = self.objtable.table[target_name] + pos = table_entry[node.attrname] + self.replace_op(AttrInstruction(pos)) + + else: + index = self.objtable.get_index(node.attrname) + self.new_op(AttrIndexInstruction(index)) + def _visitName(self, node, classes): name = node.name scope = self.get_scope(name) @@ -182,7 +206,8 @@ for n in node.nodes: self.dispatch(n) - def visitAssAttr(self, node): pass + def visitAssAttr(self, node): + self._visitAttr(node, (StoreAttr, StoreAttrIndex)) def visitAssList(self, node): pass @@ -365,7 +390,8 @@ def visitGenExprInner(self, node): pass - def visitGetattr(self, node): pass + def visitGetattr(self, node): + self._visitAttr(node, (LoadAttr, LoadAttrIndex)) def visitGlobal(self, node): pass diff -r 8a50d440af2f -r 7adb33e8b1d1 micropython/inspect.py --- a/micropython/inspect.py Fri Feb 15 23:50:15 2008 +0100 +++ b/micropython/inspect.py Sun Feb 17 02:38:04 2008 +0100 @@ -161,7 +161,7 @@ if not self.namespace.has_key(name): self.globals.add(name) else: - raise InspectError(self.full_name(), self.node, "Name %r is global and local in %r" % (name, self.full_name())) + raise InspectError(self.full_name(), self.node, "Name %r is both global and local in %r" % (name, self.full_name())) def get_assignments(self, name): if self.assignments.has_key(name): diff -r 8a50d440af2f -r 7adb33e8b1d1 tests/ambiguous_names.py --- a/tests/ambiguous_names.py Fri Feb 15 23:50:15 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -#!/usr/bin/env python - -def g(x): - b = 3 - global b - b = 4 - -# vim: tabstop=4 expandtab shiftwidth=4 diff -r 8a50d440af2f -r 7adb33e8b1d1 tests/classes.py --- a/tests/classes.py Fri Feb 15 23:50:15 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env python - -class A: - pass - -class B: - pass - -for x in A, B: - class C(x): - pass - -# vim: tabstop=4 expandtab shiftwidth=4 diff -r 8a50d440af2f -r 7adb33e8b1d1 tests/failure/ambiguous_names.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/ambiguous_names.py Sun Feb 17 02:38:04 2008 +0100 @@ -0,0 +1,8 @@ +#!/usr/bin/env python + +def g(x): + b = 3 + global b + b = 4 + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 8a50d440af2f -r 7adb33e8b1d1 tests/failure/classes.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/classes.py Sun Feb 17 02:38:04 2008 +0100 @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +class A: + pass + +class B: + pass + +for x in A, B: + class C(x): + pass + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 8a50d440af2f -r 7adb33e8b1d1 tests/names.py --- a/tests/names.py Fri Feb 15 23:50:15 2008 +0100 +++ b/tests/names.py Sun Feb 17 02:38:04 2008 +0100 @@ -16,4 +16,6 @@ for x in range(a, b): subvalue = "world" +C.value + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 8a50d440af2f -r 7adb33e8b1d1 tests/sealing.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sealing.py Sun Feb 17 02:38:04 2008 +0100 @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +class C: + clsattr = 123 + + def __init__(self, value): + self.instattr = value + +# vim: tabstop=4 expandtab shiftwidth=4