diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-02-17 22:09:35 +0000 |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-02-17 22:09:35 +0000 |
commit | 3ec7e2c4be9b3127ed1b10de6e3c48e1786c1a10 (patch) | |
tree | ab6383ea0770c6358db907c0cf02cbd99588f9b6 /Lib/compiler/pycodegen.py | |
parent | 7708d697ee38f5d8c61b88737e941a4d1eb49691 (diff) | |
download | cpython-git-3ec7e2c4be9b3127ed1b10de6e3c48e1786c1a10.tar.gz |
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 ...
Diffstat (limited to 'Lib/compiler/pycodegen.py')
-rw-r--r-- | Lib/compiler/pycodegen.py | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index e9120ccd28..4587bf4f31 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -6,7 +6,7 @@ a generic tool and CodeGenerator as a specific tool. """ 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 @@ class CodeGenerator: 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 @@ class CodeGenerator: def visitLambda(self, node): node.name = '<lambda>' - node.varargs = node.kwargs = None self._visitFuncOrLambda(node, 'Lambda') return 1 @@ -633,10 +632,13 @@ class CodeGenerator: 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 @@ class CodeGenerator: 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 @@ class CodeGenerator: else: self.visit(node.globals) self.emit('EXEC_STMT') + return 1 class LocalNameFinder: def __init__(self, names=()): @@ -882,6 +886,20 @@ class LocalNameFinder: 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() |