diff options
-rw-r--r-- | Lib/compiler/pyassem.py | 32 | ||||
-rw-r--r-- | Lib/compiler/pycodegen.py | 32 | ||||
-rw-r--r-- | Tools/compiler/compiler/pyassem.py | 32 | ||||
-rw-r--r-- | Tools/compiler/compiler/pycodegen.py | 32 |
4 files changed, 96 insertions, 32 deletions
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py index 5ae7294..7efc4ab 100644 --- a/Lib/compiler/pyassem.py +++ b/Lib/compiler/pyassem.py @@ -42,6 +42,15 @@ CO_NEWLOCALS = 0x0002 CO_VARARGS = 0x0004 CO_VARKEYWORDS = 0x0008 +class TupleArg: + def __init__(self, count, names): + self.count = count + self.names = names + def __repr__(self): + return "TupleArg(%s, %s)" % (self.count, self.names) + def getName(self): + return ".nested%d" % self.count + class PyAssembler: """Creates Python code objects """ @@ -54,6 +63,7 @@ class PyAssembler: self.insts = [] # used by makeCodeObject self._getArgCount(args) + print name, args, self.argcount self.code = '' self.consts = [docstring] self.filename = filename @@ -61,6 +71,10 @@ class PyAssembler: self.name = name self.names = [] self.varnames = list(args) or [] + for i in range(len(self.varnames)): + var = self.varnames[i] + if isinstance(var, TupleArg): + self.varnames[i] = var.getName() # lnotab support self.firstlineno = 0 self.lastlineno = 0 @@ -68,14 +82,12 @@ class PyAssembler: self.lnotab = '' def _getArgCount(self, args): - if args and args[0][0] == '.': - for i in range(len(args)): - if args[i][0] == '.': - num = i - self.argcount = num + 1 - else: - self.argcount = len(args) - + self.argcount = len(args) + if args: + for arg in args: + if isinstance(arg, TupleArg): + numNames = len(misc.flatten(arg.names)) + self.argcount = self.argcount - numNames def __repr__(self): return "<bytecode: %d instrs>" % len(self.insts) @@ -88,7 +100,9 @@ class PyAssembler: self.flags = self.flags | CO_OPTIMIZED def setVarArgs(self): - self.flags = self.flags | CO_VARARGS + if not self.flags & CO_VARARGS: + self.flags = self.flags | CO_VARARGS + self.argcount = self.argcount - 1 def setKWArgs(self): self.flags = self.flags | CO_VARKEYWORDS diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index e9120cc..4587bf4 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() diff --git a/Tools/compiler/compiler/pyassem.py b/Tools/compiler/compiler/pyassem.py index 5ae7294..7efc4ab 100644 --- a/Tools/compiler/compiler/pyassem.py +++ b/Tools/compiler/compiler/pyassem.py @@ -42,6 +42,15 @@ CO_NEWLOCALS = 0x0002 CO_VARARGS = 0x0004 CO_VARKEYWORDS = 0x0008 +class TupleArg: + def __init__(self, count, names): + self.count = count + self.names = names + def __repr__(self): + return "TupleArg(%s, %s)" % (self.count, self.names) + def getName(self): + return ".nested%d" % self.count + class PyAssembler: """Creates Python code objects """ @@ -54,6 +63,7 @@ class PyAssembler: self.insts = [] # used by makeCodeObject self._getArgCount(args) + print name, args, self.argcount self.code = '' self.consts = [docstring] self.filename = filename @@ -61,6 +71,10 @@ class PyAssembler: self.name = name self.names = [] self.varnames = list(args) or [] + for i in range(len(self.varnames)): + var = self.varnames[i] + if isinstance(var, TupleArg): + self.varnames[i] = var.getName() # lnotab support self.firstlineno = 0 self.lastlineno = 0 @@ -68,14 +82,12 @@ class PyAssembler: self.lnotab = '' def _getArgCount(self, args): - if args and args[0][0] == '.': - for i in range(len(args)): - if args[i][0] == '.': - num = i - self.argcount = num + 1 - else: - self.argcount = len(args) - + self.argcount = len(args) + if args: + for arg in args: + if isinstance(arg, TupleArg): + numNames = len(misc.flatten(arg.names)) + self.argcount = self.argcount - numNames def __repr__(self): return "<bytecode: %d instrs>" % len(self.insts) @@ -88,7 +100,9 @@ class PyAssembler: self.flags = self.flags | CO_OPTIMIZED def setVarArgs(self): - self.flags = self.flags | CO_VARARGS + if not self.flags & CO_VARARGS: + self.flags = self.flags | CO_VARARGS + self.argcount = self.argcount - 1 def setKWArgs(self): self.flags = self.flags | CO_VARKEYWORDS diff --git a/Tools/compiler/compiler/pycodegen.py b/Tools/compiler/compiler/pycodegen.py index e9120cc..4587bf4 100644 --- a/Tools/compiler/compiler/pycodegen.py +++ b/Tools/compiler/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() |