# HG changeset patch # User paulb@localhost.localdomain # Date 1172190590 -3600 # Node ID c413fccc7e518ddf3fbcae4ae4958cf5569f639e # Parent b86339b061e0004d0cc6d96c76450794446ca864 Fixed/improved the import mechanism so that modules are recorded before annotation. Added a "no annotate" (-na) option to the test program. Added Bitand support. Added Yield support "placeholder". diff -r b86339b061e0 -r c413fccc7e51 annotate.py --- a/annotate.py Fri Feb 23 00:12:44 2007 +0100 +++ b/annotate.py Fri Feb 23 01:29:50 2007 +0100 @@ -892,6 +892,9 @@ try_.finally_ = self.dispatches(try_.finally_) return try_ + def visitYield(self, yield_): + raise NotImplementedError, "The yield statement is not currently supported." + # Utility methods. def get_builtin_instances(self, node, name): @@ -1539,13 +1542,20 @@ package, or None if no such module or package exists. """ + if self.modules.has_key(name): + return Attribute(None, self.modules[name]) + path = name.split(".") m = self.find_in_path(path[0]) if not m: return None # NOTE: Import error. d, filename = m - top = module = self.modules.get(path[0], load(filename, builtins, path[0], self)) - self.modules[path[0]] = module + + if self.modules.has_key(path[0]): + top = module = self.modules[path[0]] + else: + top = module = self.modules[path[0]] = load(filename, builtins, path[0], self, no_annotate=1) + annotate(module, builtins, self) if len(path) > 1: path_so_far = path[:1] @@ -1556,8 +1566,12 @@ return None # NOTE: Import error. d, filename = m module_name = ".".join(path_so_far) - submodule = self.modules.get(module_name, load(filename, builtins, module_name, self)) - self.modules[module_name] = submodule + + if self.modules.has_key(module_name): + submodule = self.modules[module_name] + else: + submodule = self.modules[module_name] = load(filename, builtins, module_name, self, no_annotate=1) + annotate(submodule, builtins, self) # Store the submodule within its parent module. @@ -1670,7 +1684,7 @@ # Convenience functions. -def load(name, builtins=None, module_name=None, importer=None): +def load(name, builtins=None, module_name=None, importer=None, no_annotate=0): """ Load the module with the given 'name' (which may be a full module path), @@ -1680,7 +1694,8 @@ module = simplify.simplify(name, builtins is None, module_name) fixnames.fix(module, builtins) - annotate(module, builtins, importer) + if not no_annotate: + annotate(module, builtins, importer) return module def annotate(module, builtins=None, importer=None): diff -r b86339b061e0 -r c413fccc7e51 lib/builtins.py --- a/lib/builtins.py Fri Feb 23 00:12:44 2007 +0100 +++ b/lib/builtins.py Fri Feb 23 01:29:50 2007 +0100 @@ -373,6 +373,42 @@ else: raise TypeError + def __and__(self, other): + if isinstance(other, int): + return int() + else: + raise TypeError + + def __rand__(self, other): + if isinstance(other, int): + return int() + else: + raise TypeError + + def __or__(self, other): + if isinstance(other, int): + return int() + else: + raise TypeError + + def __ror__(self, other): + if isinstance(other, int): + return int() + else: + raise TypeError + + def __xor__(self, other): + if isinstance(other, int): + return int() + else: + raise TypeError + + def __rxor__(self, other): + if isinstance(other, int): + return int() + else: + raise TypeError + def __lt__(self, other): if isinstance(other, int): return bool() @@ -542,6 +578,54 @@ else: raise TypeError + def __and__(self, other): + if isinstance(other, int): + return long() + elif isinstance(other, long): + return long() + else: + raise TypeError + + def __rand__(self, other): + if isinstance(other, int): + return long() + elif isinstance(other, long): + return long() + else: + raise TypeError + + def __or__(self, other): + if isinstance(other, int): + return long() + elif isinstance(other, long): + return long() + else: + raise TypeError + + def __ror__(self, other): + if isinstance(other, int): + return long() + elif isinstance(other, long): + return long() + else: + raise TypeError + + def __xor__(self, other): + if isinstance(other, int): + return long() + elif isinstance(other, long): + return long() + else: + raise TypeError + + def __rxor__(self, other): + if isinstance(other, int): + return long() + elif isinstance(other, long): + return long() + else: + raise TypeError + def __lt__(self, other): if isinstance(other, int): return bool() diff -r b86339b061e0 -r c413fccc7e51 simplified.py --- a/simplified.py Fri Feb 23 00:12:44 2007 +0100 +++ b/simplified.py Fri Feb 23 01:29:50 2007 +0100 @@ -425,6 +425,13 @@ class ReturnFromBlock(Return): pass +# NOTE: Not actually supported. +# Additionally, yield statements act like return statements for the purposes +# of this system. + +class Yield(ReturnFromFunction): + pass + # Some behaviour is set as the default in conditional nodes but may be # overridden. diff -r b86339b061e0 -r c413fccc7e51 simplify.py --- a/simplify.py Fri Feb 23 00:12:44 2007 +0100 +++ b/simplify.py Fri Feb 23 01:29:50 2007 +0100 @@ -48,15 +48,16 @@ A simplifying visitor for AST nodes. Covered: Add, And, Assert, AssAttr, AssList, AssName, AssTuple, Assign, - AugAssign, Break, CallFunc, Class, Compare, Const, Continue, Dict, - Discard, Div, FloorDiv, For, From, Function, Getattr, Global, If, - Import, Invert, Keyword, Lambda, List, ListComp, ListCompFor, - ListCompIf, Mod, Module, Mul, Name, Not, Or, Pass, Power, Print, - Printnl, Raise, Return, Slice, Sliceobj, Stmt, Sub, Subscript, - TryExcept, TryFinally, Tuple, While, UnaryAdd, UnarySub. + AugAssign, Bitand, Break, CallFunc, Class, Compare, Const, + Continue, Dict, Discard, Div, FloorDiv, For, From, Function, + Getattr, Global, If, Import, Invert, Keyword, Lambda, List, + ListComp, ListCompFor, ListCompIf, Mod, Module, Mul, Name, Not, Or, + Pass, Power, Print, Printnl, Raise, Return, Slice, Sliceobj, Stmt, + Sub, Subscript, TryExcept, TryFinally, Tuple, While, UnaryAdd, + UnarySub. - Missing: Backquote, Bitand, Bitor, Bitxor, Decorators, Ellipsis, - Exec, LeftShift, RightShift, Yield. + Missing: Backquote, Bitor, Bitxor, Decorators, Ellipsis, Exec, LeftShift, + RightShift, Yield. """ def __init__(self, builtins=0): @@ -457,6 +458,95 @@ return result + def visitBitand(self, bitand): + + """ + Make a subprogram for the 'bitand' node and record its contents inside the + subprogram. Convert... + + Bitand (node) + (node) + ... + + ...to: + + Subprogram -> Conditional (test) -> ReturnFromBlock ... + (else) -> Conditional (test) -> ReturnFromBlock ... + (else) -> ... + """ + + subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None) + self.current_subprograms.append(subprogram) + + # In the subprogram, make instructions which store each operand, test + # for each operand's truth status, and if appropriate return from the + # subprogram with the value of the operand. + + last = bitand.nodes[-1] + results = nodes = [] + + # Start by storing the first operand. + + nodes += [ + StoreTemp(expr=self.dispatch(bitand.nodes[0])) + ] + + # For viewing purposes, record invocations on the AST node. + + bitand._ops = [] + + for node in bitand.nodes[1:]: + + # Make a new AST-style node to wrap the operation program nodes. + + new_op = Op("&", node) + bitand._ops.append(new_op) + + # Generate the operation involving the previous result and the + # current operand. + + expr = self._visitBinaryOp(new_op, LoadTemp(), self.dispatch(node), "__and__", "__rand__") + + # Return from the subprogram where the test is not satisfied. + + if node is not last: + nodes += [ + StoreTemp(expr=expr), + Conditional( + test=self._visitNot(LoadTemp()), + body=[ + ReturnFromBlock( + expr=LoadTemp() + ) + ], + else_=[ + # Subsequent operations go here! + ] + ) + ] + + # Put subsequent operations in the else section of this conditional. + + nodes = nodes[-1].else_ + + # For the last operation, return the result. + + else: + nodes.append(ReturnFromBlock(expr=expr)) + + # Finish the subprogram definition. + + subprogram.code = results + + self.current_subprograms.pop() + self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram + + # Make an invocation of the subprogram. + + result = InvokeBlock(bitand, 1, produces_result=1) + result.expr = LoadRef(ref=subprogram) + return result + def visitBreak(self, break_): result = ReturnFromBlock(break_, 1) return result @@ -567,6 +657,8 @@ # Make a new AST-style node to wrap the operation program nodes. new_op = Op(op_name, node) + compare._ops.append(new_op) + expr = self.dispatch(node) # Identify the operation and produce the appropriate method call. @@ -624,7 +716,6 @@ raise NotImplementedError, op_name nodes.append(StoreTemp(expr=invocation)) - compare._ops.append(new_op) # Return from the subprogram where the test is not satisfied. @@ -1594,6 +1685,15 @@ return result + # NOTE: Not actually supported. + # NOTE: Virtually the same as visitReturn... + + def visitYield(self, yield_): + result = Yield(yield_, 1, + expr=self.dispatch(yield_.value) + ) + return result + # Convenience methods. def _visitBinary(self, binary, left_name, right_name): diff -r b86339b061e0 -r c413fccc7e51 test.py --- a/test.py Fri Feb 23 00:12:44 2007 +0100 +++ b/test.py Fri Feb 23 01:29:50 2007 +0100 @@ -19,7 +19,7 @@ importer = Importer(sys.path) try: builtins = load(os.path.join("lib", "builtins.py")) - module = load(sys.argv[1], builtins, None, importer) + module = load(sys.argv[1], builtins, None, importer, "-na" in sys.argv) except simplified.SimplifiedError, exc: raise else: diff -r b86339b061e0 -r c413fccc7e51 tests/bitand.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/bitand.py Fri Feb 23 01:29:50 2007 +0100 @@ -0,0 +1,4 @@ +a = 0x100 +b = 0x110 +c = 0x101 +d = a & b & c diff -r b86339b061e0 -r c413fccc7e51 viewer.py --- a/viewer.py Fri Feb 23 00:12:44 2007 +0100 +++ b/viewer.py Fri Feb 23 01:29:50 2007 +0100 @@ -127,14 +127,14 @@ A browsing visitor for AST nodes. Covered: Add, And, Assert, AssAttr, AssList, AssName, AssTuple, Assign, - AugAssign, Break, CallFunc, Class, Compare, Const, Continue, Dict, - Discard, Div, FloorDiv, For, From, Function, Getattr, Global, If, - Import, Keyword, Lambda, List, ListComp, ListCompFor, ListCompIf, - Mod, Module, Mul, Name, Not, Or, Pass, Power, Print, Printnl, - Raise, Return, Slice, Sliceobj, Stmt, Sub, Subscript, TryExcept, - TryFinally, Tuple, UnaryAdd, UnarySub, While. + AugAssign, Bitand, Break, CallFunc, Class, Compare, Const, + Continue, Dict, Discard, Div, FloorDiv, For, From, Function, + Getattr, Global, If, Import, Keyword, Lambda, List, ListComp, + ListCompFor, ListCompIf, Mod, Module, Mul, Name, Not, Or, Pass, + Power, Print, Printnl, Raise, Return, Slice, Sliceobj, Stmt, Sub, + Subscript, TryExcept, TryFinally, Tuple, UnaryAdd, UnarySub, While. - Missing: Backquote, Bitand, Bitor, Bitxor, Decorators, Ellipsis, + Missing: Backquote, Bitor, Bitxor, Decorators, Ellipsis, Exec, Invert, LeftShift, RightShift, Yield. """ @@ -610,6 +610,19 @@ self.stream.write(")\n") self.stream.write("\n") + def visitBitand(self, node): + self.stream.write("\n") + self.dispatch(node.nodes[0]) + for op in node._ops: + self.stream.write("\n") + self.stream.write(op.name) + self._popup( + self._op(op) + ) + self.stream.write("\n") + self.dispatch(op.expr) + self.stream.write("") + def visitCallFunc(self, node): target = node._node targets = target.active()