mirror of
https://github.com/python/cpython.git
synced 2025-08-28 04:35:02 +00:00
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 ...
This commit is contained in:
parent
7708d697ee
commit
3ec7e2c4be
4 changed files with 96 additions and 32 deletions
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue