diff Lib/compiler/pycodegen.py @ 11808:cf8fa92ebf3d legacy-trunk

the previous quick hack to fix def foo((x,y)) failed on some cases (big surprise). new solution is a little less hackish. Code gen adds a TupleArg instance in the argument slot. The tuple arg includes a copy of the names that it is responsble for binding. The PyAssembler uses this information to calculate the correct argcount. all fix this wacky case: del (a, ((b,), c)), d which is the same as: del a, b, c, d (Can't wait for Guido to tell me why.) solution uses findOp which walks a tree to find out whether it contains OP_ASSIGN or OP_DELETE or ...
author Jeremy Hylton <jeremy@alum.mit.edu>
date Thu, 17 Feb 2000 22:09:35 +0000
parents 57167731d124
children 79b6a6a882d9
line wrap: on
line diff
--- a/Lib/compiler/pycodegen.py	Thu Feb 17 22:06:20 2000 +0000
+++ b/Lib/compiler/pycodegen.py	Thu Feb 17 22:09:35 2000 +0000
@@ -6,7 +6,7 @@
 """
 
 from p2c import transformer, ast
-from pyassem import StackRef, PyAssembler
+from pyassem import StackRef, PyAssembler, TupleArg
 import dis
 import misc
 import marshal
@@ -203,7 +203,7 @@
             if type(elt) == types.StringType:
                 args.append(elt)
             elif type(elt) == types.TupleType:
-                args.append(".nested%d" % count)
+                args.append(TupleArg(count, elt))
                 count = count + 1
                 extra.extend(misc.flatten(elt))
             else:
@@ -343,7 +343,6 @@
 
     def visitLambda(self, node):
         node.name = '<lambda>'
-        node.varargs = node.kwargs = None
         self._visitFuncOrLambda(node, 'Lambda')
         return 1
 
@@ -633,10 +632,13 @@
         return 1
 
     def visitAssName(self, node):
-        # XXX handle OP_DELETE
-        if node.flags != 'OP_ASSIGN':
+        if node.flags == 'OP_ASSIGN':
+            self.storeName(node.name)
+        elif node.flags == 'OP_DELETE':
+            self.delName(node.name)
+        else:
             print "oops", node.flags
-        self.storeName(node.name)
+        return 1
 
     def visitAssAttr(self, node):
         self.visit(node.expr)
@@ -650,7 +652,8 @@
         return 1
 
     def visitAssTuple(self, node):
-        self.emit('UNPACK_TUPLE', len(node.nodes))
+        if findOp(node) != 'OP_DELETE':
+            self.emit('UNPACK_TUPLE', len(node.nodes))
         for child in node.nodes:
             self.visit(child)
         return 1
@@ -838,6 +841,7 @@
         else:
             self.visit(node.globals)
         self.emit('EXEC_STMT')
+        return 1
 
 class LocalNameFinder:
     def __init__(self, names=()):
@@ -882,6 +886,20 @@
     def visitAssName(self, node):
         self.names.add(node.name)
 
+class OpFinder:
+    def __init__(self):
+        self.op = None
+    def visitAssName(self, node):
+        if self.op is None:
+            self.op = node.flags
+        elif self.op != node.flags:
+            raise ValueError, "mixed ops in stmt"
+
+def findOp(node):
+    v = OpFinder()
+    walk(node, v)
+    return v.op
+
 class Loop:
     def __init__(self):
         self.startAnchor = StackRef()