[pypy-svn] r66837 - pypy/branch/parser-compiler/pypy/interpreter/astcompiler

benjamin at codespeak.net benjamin at codespeak.net
Fri Aug 14 19:08:17 CEST 2009


Author: benjamin
Date: Fri Aug 14 19:08:16 2009
New Revision: 66837

Modified:
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/astbuilder.py
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/asthelpers.py
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/misc.py
Log:
make set_context() a method of ast.expr

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/astbuilder.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/astbuilder.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/astbuilder.py	Fri Aug 14 19:08:16 2009
@@ -1,4 +1,5 @@
 from pypy.interpreter.astcompiler import ast, misc
+from pypy.interpreter.astcompiler import asthelpers # Side effects
 from pypy.interpreter import error
 from pypy.interpreter.pyparser.pygram import syms, tokens
 from pypy.interpreter.pyparser.error import SyntaxError
@@ -107,72 +108,24 @@
         raise SyntaxError(msg, n.lineno, n.column,
                           filename=self.compile_info.filename)
 
+    def error_ast(self, msg, ast_node):
+        raise SyntaxError(msg, ast_node.lineno, ast_node.col_offset,
+                          filename=self.compile_info.filename)
+
     def check_forbidden_name(self, name, node):
-        """Raise an error if the name cannot be assigned to."""
-        if name == "None":
-            self.error("assignment to None", node)
-        if name == "__debug__":
-            self.error("assignment to __debug__", node)
-        # XXX Warn about using True and False
+        try:
+            misc.check_forbidden_name(name)
+        except misc.ForbiddenNameAssignment, e:
+            self.error("assignment to %s" % (e.name,), node)
 
-    def set_context(self, expr, ctx, node):
+    def set_context(self, expr, ctx):
         """Set the context of an expression to Store or Del if possible."""
-        error = None
-        sequence = None
-        if isinstance(expr, ast.Attribute):
-            if ctx == ast.Store:
-                self.check_forbidden_name(expr.attr, node)
-            expr.ctx = ctx
-        elif isinstance(expr, ast.Subscript):
-            expr.ctx = ctx
-        elif isinstance(expr, ast.Name):
-            if ctx == ast.Store:
-                self.check_forbidden_name(expr.id, node)
-            expr.ctx = ctx
-        elif isinstance(expr, ast.List):
-            expr.ctx = ctx
-            sequence = expr.elts
-        elif isinstance(expr, ast.Tuple):
-            if expr.elts:
-                expr.ctx = ctx
-                sequence = expr.elts
-            else:
-                error = "()"
-        elif isinstance(expr, ast.Lambda):
-            error = "lambda"
-        elif isinstance(expr, ast.Call):
-            error = "function call"
-        elif isinstance(expr, ast.BoolOp) or \
-                isinstance(expr, ast.BinOp) or \
-                isinstance(expr, ast.UnaryOp):
-            error = "operator"
-        elif isinstance(expr, ast.GeneratorExp):
-            error = "generator expression"
-        elif isinstance(expr, ast.Yield):
-            error = "yield expression"
-        elif isinstance(expr, ast.ListComp):
-            error = "list comprehension"
-        elif isinstance(expr, ast.Dict) or \
-                isinstance(expr, ast.Num) or \
-                isinstance(expr, ast.Str):
-            error = "literal"
-        elif isinstance(expr, ast.Compare):
-            error = "comparison"
-        elif isinstance(expr, ast.IfExp):
-            error = "conditional expression"
-        elif isinstance(expr, ast.Repr):
-            error = "repr"
-        else:
-            raise AssertionError("unknown expression in set_context()")
-        if error is not None:
-            if ctx == ast.Store:
-                action = "assign to"
-            else:
-                action = "delete"
-            self.error("can't %s %s" % (action, error), node)
-        if sequence:
-            for item in sequence:
-                self.set_context(item, ctx, node)
+        try:
+            expr.set_context(ctx)
+        except ast.UnacceptableExpressionContext, e:
+            self.error_ast(e.msg, e.node)
+        except misc.ForbiddenNameAssignment, e:
+            self.error_ast("assignment to %s" % (e.name,), e.node)
 
     def handle_print_stmt(self, print_node):
         dest = None
@@ -452,7 +405,7 @@
         if child_count == 4:
             target_child = exc.children[3]
             target = self.handle_expr(target_child)
-            self.set_context(target, ast.Store, target_child)
+            self.set_context(target, ast.Store)
         return ast.excepthandler(test, target, suite, exc.lineno, exc.column)
 
     def handle_try_stmt(self, try_node):
@@ -494,7 +447,7 @@
         if len(with_node.children) == 5:
             target_node = with_node.children[2]
             target = self.handle_with_var(target_node)
-            self.set_context(target, ast.Store, target_node)
+            self.set_context(target, ast.Store)
         else:
             target = None
         return ast.With(test, target, body, with_node.lineno, with_node.column)
@@ -644,7 +597,7 @@
                     args.append(self.handle_arg_unpacking(child))
                 break
         tup = ast.Tuple(args, ast.Store, fplist_node.lineno, fplist_node.column)
-        self.set_context(tup, ast.Store, fplist_node)
+        self.set_context(tup, ast.Store)
         return tup
 
     def handle_stmt(self, stmt):
@@ -708,7 +661,7 @@
             # Augmented assignment.
             target_child = stmt.children[0]
             target_expr = self.handle_testlist(target_child)
-            self.set_context(target_expr, ast.Store, target_child)
+            self.set_context(target_expr, ast.Store)
             value_child = stmt.children[2]
             if value_child.type == syms.testlist:
                 value_expr = self.handle_testlist(value_child)
@@ -726,7 +679,7 @@
                 if target_node.type == syms.yield_expr:
                     self.error("can't assign to yield expression", target_node)
                 target_expr = self.handle_testlist(target_node)
-                self.set_context(target_expr, ast.Store, target_node)
+                self.set_context(target_expr, ast.Store)
                 targets.append(target_expr)
             value_child = stmt.children[-1]
             if value_child.type == syms.testlist:
@@ -1249,6 +1202,6 @@
         for i in range(0, len(exprlist.children), 2):
             child = exprlist.children[i]
             expr = self.handle_expr(child)
-            self.set_context(expr, context, child)
+            self.set_context(expr, context)
             exprs.append(expr)
         return exprs

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/asthelpers.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/asthelpers.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/asthelpers.py	Fri Aug 14 19:08:16 2009
@@ -1,7 +1,15 @@
-from pypy.interpreter.astcompiler import ast
+from pypy.interpreter.astcompiler import ast, misc
 from pypy.interpreter.error import OperationError
 
 
+class UnacceptableExpressionContext(Exception):
+
+    def __init__(self, node, msg):
+        self.node = node
+        self.msg = msg
+setattr(ast, "UnacceptableExpressionContext", UnacceptableExpressionContext)
+
+
 class __extend__(ast.expr):
 
     constant = False
@@ -9,18 +17,112 @@
     def as_node_list(self, space):
         return None
 
+    def set_context(self, ctx):
+        if ctx == ast.Del:
+            msg = "can't delete %s" % (self._description,)
+        else:
+            msg = "can't assign to %s" % (self._description,)
+        raise UnacceptableExpressionContext(self, msg)
+
 
 class __extend__(ast.List):
 
     def as_node_list(self, space):
         return self.elts
 
+    def set_context(self, ctx):
+        for elt in self.elts:
+            elt.set_context(ctx)
+        self.ctx = ctx
+
+
+class __extend__(ast.Attribute):
+
+    def set_context(self, ctx):
+        if ctx == ast.Store:
+            misc.check_forbidden_name(self.attr, self)
+        self.ctx = ctx
+
+
+class __extend__(ast.Subscript):
+
+    def set_context(self, ctx):
+        self.ctx = ctx
+
+
+class __extend__(ast.Name):
+
+    def set_context(self, ctx):
+        if ctx == ast.Store:
+            misc.check_forbidden_name(self.id, self)
+        self.ctx = ctx
+
 
 class __extend__(ast.Tuple):
 
+    _description = "()"
+
     def as_node_list(self, space):
         return self.elts
 
+    def set_context(self, ctx):
+        if self.elts:
+            for elt in self.elts:
+                elt.set_context(ctx)
+            self.ctx = ctx
+        else:
+            # Assignment to () raises an error.
+            ast.expr.set_context(self, ctx)
+
+class __extend__(ast.Lambda):
+
+    _description = "lambda"
+
+
+class __extend__(ast.Call):
+
+    _description = "function call"
+
+
+class __extend__(ast.BoolOp, ast.BinOp, ast.UnaryOp):
+
+    _description = "operator"
+
+
+class __extend__(ast.GeneratorExp):
+
+    _description = "generator expression"
+
+
+class __extend__(ast.Yield):
+
+    _description = "yield expression"
+
+
+class __extend__(ast.ListComp):
+
+    _description = "list comprehension"
+
+
+class __extend__(ast.Dict, ast.Str, ast.Num, ast.Const):
+
+    _description = "literal"
+
+
+class __extend__(ast.Compare):
+
+    _description = "comparison"
+
+
+class __extend__(ast.IfExp):
+
+    _description = "conditional expression"
+
+
+class __extend__(ast.Repr):
+
+    _description = "repr"
+
 
 class __extend__(ast.Const):
 

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/codegen.py	Fri Aug 14 19:08:16 2009
@@ -8,7 +8,7 @@
 # please.
 
 from pypy.interpreter.astcompiler import ast, assemble, symtable, consts, misc
-from pypy.interpreter.astcompiler import optimize, asthelpers # For side effects
+from pypy.interpreter.astcompiler import optimize # For side effects
 from pypy.interpreter.pyparser.error import SyntaxError
 from pypy.tool import stdlib_opcode as ops
 from pypy.interpreter.pyparser import future

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/misc.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/misc.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/misc.py	Fri Aug 14 19:08:16 2009
@@ -27,6 +27,20 @@
     _emit_syntax_warning(space, w_msg, w_filename, w_lineno, w_offset)
 
 
+class ForbiddenNameAssignment(Exception):
+
+    def __init__(self, name, node):
+        self.name = name
+        self.node = node
+
+
+def check_forbidden_name(name, node=None):
+    """Raise an error if the name cannot be assigned to."""
+    if name in ("None", "__debug__"):
+        raise ForbiddenNameAssignment(name, node)
+    # XXX Warn about using True and False
+
+
 def dict_to_switch(d):
     """Convert of dictionary with integer keys to a switch statement."""
     def lookup(query):



More information about the Pypy-commit mailing list