# HG changeset patch # User Paul Boddie # Date 1372625192 -7200 # Node ID 46ef6f4f6d03b178dd06c5d70daa44502c2911cb # Parent eaaa3147274e1ca99e288507264dfc8a6eb86640 Added "del" statement handling. Fixed global name access. Added initial list comprehension support. diff -r eaaa3147274e -r 46ef6f4f6d03 micropython/syspython.py --- a/micropython/syspython.py Sun Jun 30 01:52:11 2013 +0200 +++ b/micropython/syspython.py Sun Jun 30 22:46:32 2013 +0200 @@ -582,10 +582,22 @@ def visitAnd(self, node): return compiler.ast.And([self.dispatch(n) for n in node.nodes]) - def visitAssAttr(self, node, expr): + def visitAssAttr(self, node, expr=None): + + # Handle deletion. + + if compiler.ast.is_deletion(node): + return compiler.ast.Stmt([]) + return self._visitAttr(node, expr) - def visitAssList(self, node, expr): + def visitAssList(self, node, expr=None): + + # Handle deletion. + + if compiler.ast.is_deletion(compiler.ast.flatten_assignment(node)): + return compiler.ast.Stmt([]) + return compiler.ast.Stmt([ self.dispatch(n, compiler.ast.CallFunc( module_attribute("operator", "getitem"), @@ -594,7 +606,13 @@ for (i, n) in enumerate(node.nodes) ]) - def visitAssName(self, node, expr): + def visitAssName(self, node, expr=None): + + # Handle deletion. + + if compiler.ast.is_deletion(node): + return compiler.ast.Stmt([]) + unit = self.get_unit() # Generate appropriate name access operation. @@ -674,8 +692,8 @@ return compiler.ast.CallFunc( self.dispatch(node.node), [self.dispatch(arg) for arg in node.args], - node.star_args and [self.dispatch(arg) for arg in node.star_args], - node.dstar_args and [self.dispatch(arg) for arg in node.dstar_args] + node.star_args and self.dispatch(node.star_args), + node.dstar_args and self.dispatch(node.dstar_args) ) def visitCompare(self, node): @@ -709,9 +727,10 @@ return compiler.ast.GenExpr(self.dispatch(node.code)) def visitGenExprFor(self, node): + expr = self.dispatch(node.iter) return compiler.ast.GenExprFor( - self.dispatch(node.assign), # NOTE: Needs to dispatch to AssName/AssTuple/AssList with an expression. - self.dispatch(node.iter), + self.dispatch(node.assign, expr), # NOTE: Needs to dispatch to AssName/AssTuple/AssList with an expression. + expr, [self.dispatch(n) for n in node.ifs] ) @@ -762,22 +781,143 @@ return compiler.ast.List([self.dispatch(n) for n in node.nodes]) def visitListComp(self, node): - return compiler.ast.ListComp( - self.dispatch(node.expr), - [self.dispatch(n) for n in node.quals] + + """ + Convert from... + + [ for in [ for in ]... [ if ]... ] + + ...to... + + _out = [] + ... + """ + + unit = self.get_unit() + temp = quoted_name(unit.temp_usage) + unit.temp_usage += 1 + + return compiler.ast.Stmt([ + # __storetemp__(_out, __loadattr__(__builtins__, list)()) + compiler.ast.CallFunc(special_name("__storetemp__"), [ + temp, + compiler.ast.CallFunc( + compiler.ast.CallFunc(special_name("__loadattr__"), + [special_name("__builtins__"), special_name("list")] + ), + [] + ) + ]), + # ... + self.dispatch(node.quals[0], temp, node.expr, node.quals[1:]) + ]) + + def visitListCompFor(self, node, out_temp, expr, quals): + + """ + Convert from... + + [ for in ...] + + ...to... + + _it = iter() + while True: + try: + = _it.next() + except StopIteration: + break + else: + ... + _out.append() + """ + + unit = self.get_unit() + temp = quoted_name(unit.temp_usage) + unit.temp_usage += 1 + + # Either generate more "for" or "if" constructs. + + if node.ifs or quals: + nodes = node.ifs + quals + body = self.dispatch(nodes[0], out_temp, expr, nodes[1:]) + + # Or generate the append statement. + + else: + body = self._visitListCompExpr(out_temp, expr) + + # Wrap the above body in the loop construct. + + return compiler.ast.Stmt([ + # __storetemp__(_it, __loadattr__(__builtins__, iter)()) + compiler.ast.CallFunc(special_name("__storetemp__"), [ + temp, + compiler.ast.CallFunc( + compiler.ast.CallFunc(special_name("__loadattr__"), + [special_name("__builtins__"), special_name("iter")] + ), + [self.dispatch(node.list)] + ) + ]), + # while True: ... + compiler.ast.While( + special_name("True"), + # try: ... + compiler.ast.TryExcept( + compiler.ast.Stmt([ + # = ... + self.dispatch(node.assign, + # _it.next() + compiler.ast.CallFunc( + compiler.ast.CallFunc(special_name("__loadattr__"), [ + compiler.ast.CallFunc(special_name("__loadtemp__"), [temp]), + special_name("next") + ]), + [] + ) + ) + ]), + # except StopIteration: ... + [(special_name("StopIteration"), None, compiler.ast.Stmt([compiler.ast.Break()]))], + # else: ... + body + ), + None + ) + ]) + + def visitListCompIf(self, node, out_temp, expr, quals): + + # Either generate more "for" or "if" constructs. + + if quals: + body = self.dispatch(quals[0], out_temp, expr, quals[1:]) + + # Or generate the append statement. + + else: + body = self._visitListCompExpr(out_temp, expr) + + return compiler.ast.If( + [(self.dispatch(node.test), body)], + None ) - def visitListCompFor(self, node): - return compiler.ast.ListCompFor( - self.dispatch(node.assign), # NOTE: Needs to dispatch to AssName/AssTuple/AssList with an expression. - self.dispatch(node.list), - [self.dispatch(n) for n in node.ifs] - ) + def _visitListCompExpr(self, out_temp, expr): + + "To the 'out_temp' object, append the result of 'expr'." - def visitListCompIf(self, node): - return compiler.ast.ListCompIf( - self.dispatch(node.test) - ) + return compiler.ast.Stmt([ + # _out.append() + compiler.ast.CallFunc( + compiler.ast.CallFunc(special_name("__loadattr__"), [ + compiler.ast.CallFunc(special_name("__loadtemp__"), [out_temp]), + special_name("append") + ]), + [self.dispatch(expr)] + ) + ]) def visitMod(self, node): return self._visitBinary(node) @@ -805,12 +945,20 @@ # Other attributes should already be resolved. - elif attr is not None: + elif attr is not None and not isinstance(attr, Instance): return compiler.ast.CallFunc( special_name("__loadattr__"), [quoted_ref(attr.parent), special_name(node.name)] ) + # Function globals are referenced via the module. + + elif scope == "global": + return compiler.ast.CallFunc( + special_name("__loadattr__"), + [quoted_ref(self.get_module()), special_name(node.name)] + ) + # NOTE: Unknown attributes may arise because a class attribute has been # NOTE: optimised away. diff -r eaaa3147274e -r 46ef6f4f6d03 tests/listcomp_nested.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/listcomp_nested.py Sun Jun 30 22:46:32 2013 +0200 @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +l = [(x, y) for x in range(0, 6) if x % 2 == 0 for y in range(0, 6) if y % 3 == 0] + +result2 = l[3][0] +result3 = l[3][1] +result5 = l[3][0] + l[3][1] + +# vim: tabstop=4 expandtab shiftwidth=4