class CallFunc(Node):
nodes['call_func'] = 'CallFunc'
- def __init__(self, node, args):
+ def __init__(self, node, args, star_args = None, dstar_args = None):
self.node = node
self.args = args
- self._children = ('call_func', node, args)
+ self.star_args = star_args
+ self.dstar_args = dstar_args
+ self._children = ('call_func', node, args, star_args, dstar_args)
def __repr__(self):
- return "CallFunc(%s,%s)" % self._children[1:]
+ return "CallFunc(%s,%s,*%s, **%s)" % self._children[1:]
class Keyword(Node):
nodes['keyword'] = 'Keyword'
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
else:
self.flags = 0
- self.firstlineno = None
self.consts = []
self.names = []
self.varnames = list(args) or []
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
- if self.firstlineno is None:
- self.firstlineno = oparg
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
return new.code(argcount, nlocals, self.stacksize, self.flags,
self.lnotab.getCode(), self.getConsts(),
tuple(self.names), tuple(self.varnames),
- self.filename, self.name, self.firstlineno,
+ self.filename, self.name, self.lnotab.firstline,
self.lnotab.getTable())
def getConsts(self):
if depth > maxDepth:
maxDepth = depth
# now check patterns
- for pat, delta in self.patterns:
+ for pat, pat_delta in self.patterns:
if opname[:len(pat)] == pat:
+ delta = pat_delta
depth = depth + delta
break
# if we still haven't found a match
if delta == 0:
- meth = getattr(self, opname)
- depth = depth + meth(i[1])
+ meth = getattr(self, opname, None)
+ if meth is not None:
+ depth = depth + meth(i[1])
if depth < 0:
depth = 0
return maxDepth
def CALL_FUNCTION(self, argc):
hi, lo = divmod(argc, 256)
return lo + hi * 2
+ def CALL_FUNCTION_VAR(self, argc):
+ return self.CALL_FUNCTION(argc)+1
+ def CALL_FUNCTION_KW(self, argc):
+ return self.CALL_FUNCTION(argc)+1
+ def CALL_FUNCTION_VAR_KW(self, argc):
+ return self.CALL_FUNCTION(argc)+2
def MAKE_FUNCTION(self, argc):
return -argc
def BUILD_SLICE(self, argc):
from compiler import pyassem, misc
from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, TupleArg
+callfunc_opcode_info = {
+ # (Have *args, Have **args) : opcode
+ (0,0) : "CALL_FUNCTION",
+ (1,0) : "CALL_FUNCTION_VAR",
+ (0,1) : "CALL_FUNCTION_KW",
+ (1,1) : "CALL_FUNCTION_VAR_KW",
+}
+
def compile(filename):
f = open(filename)
buf = f.read()
kw = kw + 1
else:
pos = pos + 1
- self.emit('CALL_FUNCTION', kw << 8 | pos)
+ if node.star_args is not None:
+ self.visit(node.star_args)
+ if node.dstar_args is not None:
+ self.visit(node.dstar_args)
+ have_star = node.star_args is not None
+ have_dstar = node.dstar_args is not None
+ opcode = callfunc_opcode_info[have_star, have_dstar]
+ self.emit(opcode, kw << 8 | pos)
def visitPrint(self, node):
self.emit('SET_LINENO', node.lineno)
return Node('call_func', primaryNode, [ ])
args = [ ]
kw = 0
- for i in range(1, len(nodelist), 2):
- kw, result = self.com_argument(nodelist[i], kw)
+ len_nodelist = len(nodelist)
+ for i in range(1, len_nodelist, 2):
+ node = nodelist[i]
+ if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
+ break
+ kw, result = self.com_argument(node, kw)
args.append(result)
- return Node('call_func', primaryNode, args)
+ else:
+ i = i + 1 # No broken by star arg, so skip the last one we processed.
+ star_node = dstar_node = None
+ while i < len_nodelist:
+ tok = nodelist[i]
+ ch = nodelist[i+1]
+ i = i + 3
+ if tok[0]==token.STAR:
+ if star_node is not None:
+ raise SyntaxError, 'already have the varargs indentifier'
+ star_node = self.com_node(ch)
+ elif tok[0]==token.DOUBLESTAR:
+ if dstar_node is not None:
+ raise SyntaxError, 'already have the kwargs indentifier'
+ dstar_node = self.com_node(ch)
+ else:
+ raise SyntaxError, 'unknown node type: %s' % tok
+
+ return Node('call_func', primaryNode, args, star_node, dstar_node)
def com_argument(self, nodelist, kw):
if len(nodelist) == 2:
class CallFunc(Node):
nodes['call_func'] = 'CallFunc'
- def __init__(self, node, args):
+ def __init__(self, node, args, star_args = None, dstar_args = None):
self.node = node
self.args = args
- self._children = ('call_func', node, args)
+ self.star_args = star_args
+ self.dstar_args = dstar_args
+ self._children = ('call_func', node, args, star_args, dstar_args)
def __repr__(self):
- return "CallFunc(%s,%s)" % self._children[1:]
+ return "CallFunc(%s,%s,*%s, **%s)" % self._children[1:]
class Keyword(Node):
nodes['keyword'] = 'Keyword'
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
else:
self.flags = 0
- self.firstlineno = None
self.consts = []
self.names = []
self.varnames = list(args) or []
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
- if self.firstlineno is None:
- self.firstlineno = oparg
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
return new.code(argcount, nlocals, self.stacksize, self.flags,
self.lnotab.getCode(), self.getConsts(),
tuple(self.names), tuple(self.varnames),
- self.filename, self.name, self.firstlineno,
+ self.filename, self.name, self.lnotab.firstline,
self.lnotab.getTable())
def getConsts(self):
if depth > maxDepth:
maxDepth = depth
# now check patterns
- for pat, delta in self.patterns:
+ for pat, pat_delta in self.patterns:
if opname[:len(pat)] == pat:
+ delta = pat_delta
depth = depth + delta
break
# if we still haven't found a match
if delta == 0:
- meth = getattr(self, opname)
- depth = depth + meth(i[1])
+ meth = getattr(self, opname, None)
+ if meth is not None:
+ depth = depth + meth(i[1])
if depth < 0:
depth = 0
return maxDepth
def CALL_FUNCTION(self, argc):
hi, lo = divmod(argc, 256)
return lo + hi * 2
+ def CALL_FUNCTION_VAR(self, argc):
+ return self.CALL_FUNCTION(argc)+1
+ def CALL_FUNCTION_KW(self, argc):
+ return self.CALL_FUNCTION(argc)+1
+ def CALL_FUNCTION_VAR_KW(self, argc):
+ return self.CALL_FUNCTION(argc)+2
def MAKE_FUNCTION(self, argc):
return -argc
def BUILD_SLICE(self, argc):
from compiler import pyassem, misc
from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, TupleArg
+callfunc_opcode_info = {
+ # (Have *args, Have **args) : opcode
+ (0,0) : "CALL_FUNCTION",
+ (1,0) : "CALL_FUNCTION_VAR",
+ (0,1) : "CALL_FUNCTION_KW",
+ (1,1) : "CALL_FUNCTION_VAR_KW",
+}
+
def compile(filename):
f = open(filename)
buf = f.read()
kw = kw + 1
else:
pos = pos + 1
- self.emit('CALL_FUNCTION', kw << 8 | pos)
+ if node.star_args is not None:
+ self.visit(node.star_args)
+ if node.dstar_args is not None:
+ self.visit(node.dstar_args)
+ have_star = node.star_args is not None
+ have_dstar = node.dstar_args is not None
+ opcode = callfunc_opcode_info[have_star, have_dstar]
+ self.emit(opcode, kw << 8 | pos)
def visitPrint(self, node):
self.emit('SET_LINENO', node.lineno)
return Node('call_func', primaryNode, [ ])
args = [ ]
kw = 0
- for i in range(1, len(nodelist), 2):
- kw, result = self.com_argument(nodelist[i], kw)
+ len_nodelist = len(nodelist)
+ for i in range(1, len_nodelist, 2):
+ node = nodelist[i]
+ if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
+ break
+ kw, result = self.com_argument(node, kw)
args.append(result)
- return Node('call_func', primaryNode, args)
+ else:
+ i = i + 1 # No broken by star arg, so skip the last one we processed.
+ star_node = dstar_node = None
+ while i < len_nodelist:
+ tok = nodelist[i]
+ ch = nodelist[i+1]
+ i = i + 3
+ if tok[0]==token.STAR:
+ if star_node is not None:
+ raise SyntaxError, 'already have the varargs indentifier'
+ star_node = self.com_node(ch)
+ elif tok[0]==token.DOUBLESTAR:
+ if dstar_node is not None:
+ raise SyntaxError, 'already have the kwargs indentifier'
+ dstar_node = self.com_node(ch)
+ else:
+ raise SyntaxError, 'unknown node type: %s' % tok
+
+ return Node('call_func', primaryNode, args, star_node, dstar_node)
def com_argument(self, nodelist, kw):
if len(nodelist) == 2: