mirror of
https://github.com/python/cpython.git
synced 2025-10-17 20:28:43 +00:00
Jiwon Seo's PEP 3102 implementation.
See SF#1549670. The compiler package has not yet been updated.
This commit is contained in:
parent
fc2a0a8e3c
commit
4f72a78684
31 changed files with 739 additions and 227 deletions
|
@ -487,11 +487,12 @@ class From(Node):
|
|||
return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
|
||||
|
||||
class Function(Node):
|
||||
def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
|
||||
def __init__(self, decorators, name, argnames, defaults, kwonlyargs, flags, doc, code, lineno=None):
|
||||
self.decorators = decorators
|
||||
self.name = name
|
||||
self.argnames = argnames
|
||||
self.defaults = defaults
|
||||
self.kwonlyargs = kwonlyargs
|
||||
self.flags = flags
|
||||
self.doc = doc
|
||||
self.code = code
|
||||
|
@ -509,6 +510,7 @@ class Function(Node):
|
|||
children.append(self.name)
|
||||
children.append(self.argnames)
|
||||
children.extend(flatten(self.defaults))
|
||||
children.append(self.kwonlyargs)
|
||||
children.append(self.flags)
|
||||
children.append(self.doc)
|
||||
children.append(self.code)
|
||||
|
@ -523,7 +525,7 @@ class Function(Node):
|
|||
return tuple(nodelist)
|
||||
|
||||
def __repr__(self):
|
||||
return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code))
|
||||
return "Function(%s, %s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.kwonlyargs), repr(self.flags), repr(self.doc), repr(self.code))
|
||||
|
||||
class GenExpr(Node):
|
||||
def __init__(self, code, lineno=None):
|
||||
|
@ -531,6 +533,7 @@ class GenExpr(Node):
|
|||
self.lineno = lineno
|
||||
self.argnames = ['.0']
|
||||
self.varargs = self.kwargs = None
|
||||
self.kwonlyargs = ()
|
||||
|
||||
|
||||
def getChildren(self):
|
||||
|
@ -713,9 +716,10 @@ class Keyword(Node):
|
|||
return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
|
||||
|
||||
class Lambda(Node):
|
||||
def __init__(self, argnames, defaults, flags, code, lineno=None):
|
||||
def __init__(self, argnames, defaults, kwonlyargs, flags, code, lineno=None):
|
||||
self.argnames = argnames
|
||||
self.defaults = defaults
|
||||
self.kwonlyargs = kwonlyargs
|
||||
self.flags = flags
|
||||
self.code = code
|
||||
self.lineno = lineno
|
||||
|
@ -730,6 +734,7 @@ class Lambda(Node):
|
|||
children = []
|
||||
children.append(self.argnames)
|
||||
children.extend(flatten(self.defaults))
|
||||
children.append(self.kwonlyargs)
|
||||
children.append(self.flags)
|
||||
children.append(self.code)
|
||||
return tuple(children)
|
||||
|
@ -741,7 +746,7 @@ class Lambda(Node):
|
|||
return tuple(nodelist)
|
||||
|
||||
def __repr__(self):
|
||||
return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
|
||||
return "Lambda(%s, %s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.kwonlyargs), repr(self.flags), repr(self.code))
|
||||
|
||||
class LeftShift(Node):
|
||||
def __init__(self, (left, right), lineno=None):
|
||||
|
|
|
@ -313,13 +313,15 @@ DONE = "DONE"
|
|||
class PyFlowGraph(FlowGraph):
|
||||
super_init = FlowGraph.__init__
|
||||
|
||||
def __init__(self, name, filename, args=(), optimized=0, klass=None):
|
||||
def __init__(self, name, filename,
|
||||
args=(), kwonlyargs={}, optimized=0, klass=None):
|
||||
self.super_init()
|
||||
self.name = name
|
||||
self.filename = filename
|
||||
self.docstring = None
|
||||
self.args = args # XXX
|
||||
self.argcount = getArgCount(args)
|
||||
self.kwonlyargs = kwonlyargs
|
||||
self.klass = klass
|
||||
if optimized:
|
||||
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
|
||||
|
@ -595,7 +597,9 @@ class PyFlowGraph(FlowGraph):
|
|||
argcount = self.argcount
|
||||
if self.flags & CO_VARKEYWORDS:
|
||||
argcount = argcount - 1
|
||||
return new.code(argcount, nlocals, self.stacksize, self.flags,
|
||||
kwonlyargcount = len(self.kwonlyargs)
|
||||
return new.code(argcount, kwonlyargcount,
|
||||
nlocals, self.stacksize, self.flags,
|
||||
self.lnotab.getCode(), self.getConsts(),
|
||||
tuple(self.names), tuple(self.varnames),
|
||||
self.filename, self.name, self.lnotab.firstline,
|
||||
|
@ -804,7 +808,8 @@ class StackDepthTracker:
|
|||
def CALL_FUNCTION_VAR_KW(self, argc):
|
||||
return self.CALL_FUNCTION(argc)-2
|
||||
def MAKE_FUNCTION(self, argc):
|
||||
return -argc
|
||||
hi, lo = divmod(argc, 256)
|
||||
return -(lo + hi * 2)
|
||||
def MAKE_CLOSURE(self, argc):
|
||||
# XXX need to account for free variables too!
|
||||
return -argc
|
||||
|
|
|
@ -378,6 +378,12 @@ class CodeGenerator:
|
|||
walk(node.code, gen)
|
||||
gen.finish()
|
||||
self.set_lineno(node)
|
||||
for keyword in node.kwonlyargs:
|
||||
default = keyword.expr
|
||||
if isinstance(default, ast.EmptyNode):
|
||||
continue
|
||||
self.emit('LOAD_CONST', keyword.name)
|
||||
self.visit(default)
|
||||
for default in node.defaults:
|
||||
self.visit(default)
|
||||
self._makeClosure(gen, len(node.defaults))
|
||||
|
@ -1320,7 +1326,9 @@ class AbstractFunctionCode:
|
|||
name = func.name
|
||||
|
||||
args, hasTupleArg = generateArgList(func.argnames)
|
||||
kwonlyargs = generateKwonlyArgList(func.kwonlyargs)
|
||||
self.graph = pyassem.PyFlowGraph(name, func.filename, args,
|
||||
kwonlyargs=kwonlyargs,
|
||||
optimized=1)
|
||||
self.isLambda = isLambda
|
||||
self.super_init()
|
||||
|
@ -1456,6 +1464,13 @@ def generateArgList(arglist):
|
|||
raise ValueError, "unexpect argument type:", elt
|
||||
return args + extra, count
|
||||
|
||||
def generateKwonlyArgList(keywordOnlyArgs):
|
||||
kwonlyargs = {}
|
||||
for elt in keywordOnlyArgs:
|
||||
assert isinstance(elt, ast.Keyword)
|
||||
kwonlyargs[elt.name] = elt.expr
|
||||
return kwonlyargs
|
||||
|
||||
def findOp(node):
|
||||
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
|
||||
v = OpFinder()
|
||||
|
|
|
@ -250,9 +250,9 @@ class Transformer:
|
|||
args = nodelist[-3][2]
|
||||
|
||||
if args[0] == symbol.varargslist:
|
||||
names, defaults, flags = self.com_arglist(args[1:])
|
||||
names, defaults, kwonlyargs, flags = self.com_arglist(args[1:])
|
||||
else:
|
||||
names = defaults = ()
|
||||
names = defaults = kwonlyargs = ()
|
||||
flags = 0
|
||||
doc = self.get_docstring(nodelist[-1])
|
||||
|
||||
|
@ -263,21 +263,23 @@ class Transformer:
|
|||
assert isinstance(code, Stmt)
|
||||
assert isinstance(code.nodes[0], Discard)
|
||||
del code.nodes[0]
|
||||
return Function(decorators, name, names, defaults, flags, doc, code,
|
||||
lineno=lineno)
|
||||
return Function(decorators, name, names, defaults,
|
||||
kwonlyargs, flags, doc, code, lineno=lineno)
|
||||
|
||||
def lambdef(self, nodelist):
|
||||
# lambdef: 'lambda' [varargslist] ':' test
|
||||
if nodelist[2][0] == symbol.varargslist:
|
||||
names, defaults, flags = self.com_arglist(nodelist[2][1:])
|
||||
names, defaults, kwonlyargs, flags = \
|
||||
self.com_arglist(nodelist[2][1:])
|
||||
else:
|
||||
names = defaults = ()
|
||||
names = defaults = kwonlyargs = ()
|
||||
flags = 0
|
||||
|
||||
# code for lambda
|
||||
code = self.com_node(nodelist[-1])
|
||||
|
||||
return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
|
||||
return Lambda(names, defaults, kwonlyargs,
|
||||
flags, code, lineno=nodelist[1][2])
|
||||
old_lambdef = lambdef
|
||||
|
||||
def classdef(self, nodelist):
|
||||
|
@ -783,13 +785,37 @@ class Transformer:
|
|||
# ('const', xxxx)) Nodes)
|
||||
return Discard(Const(None))
|
||||
|
||||
def keywordonlyargs(self, nodelist):
|
||||
# (',' NAME ['=' test])*
|
||||
# ^^^
|
||||
# ------+
|
||||
kwonlyargs = []
|
||||
i = 0
|
||||
while i < len(nodelist):
|
||||
default = EmptyNode()
|
||||
node = nodelist[i]
|
||||
#assert node[0] == token.COMMA
|
||||
#node = nodelist[i+1]
|
||||
if i+1 < len(nodelist) and nodelist[i+1][0] == token.EQUAL:
|
||||
assert i+2 < len(nodelist)
|
||||
default = self.com_node(nodelist[i+2])
|
||||
i += 2
|
||||
if node[0] == token.DOUBLESTAR:
|
||||
return kwonlyargs, i
|
||||
elif node[0] == token.NAME:
|
||||
kwonlyargs.append(Keyword(node[1], default, lineno=node[2]))
|
||||
i += 2
|
||||
return kwonlyargs, i
|
||||
|
||||
def com_arglist(self, nodelist):
|
||||
# varargslist:
|
||||
# (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
|
||||
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
# (fpdef ['=' test] ',')*
|
||||
# ('*' [NAME] (',' NAME '=' test)* [',' '**' NAME] | '**' NAME)
|
||||
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
# fpdef: NAME | '(' fplist ')'
|
||||
# fplist: fpdef (',' fpdef)* [',']
|
||||
names = []
|
||||
kwonlyargs = []
|
||||
defaults = []
|
||||
flags = 0
|
||||
|
||||
|
@ -799,10 +825,22 @@ class Transformer:
|
|||
if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
|
||||
if node[0] == token.STAR:
|
||||
node = nodelist[i+1]
|
||||
if node[0] == token.NAME:
|
||||
if node[0] == token.NAME: # vararg
|
||||
names.append(node[1])
|
||||
flags = flags | CO_VARARGS
|
||||
i = i + 3
|
||||
else: # no vararg
|
||||
assert node[0] == token.COMMA
|
||||
i += 1
|
||||
#elif node[0] == token.COMMA:
|
||||
# i += 1
|
||||
# kwonlyargs, skip = self.keywordonlyargs(nodelist[i:])
|
||||
# i += skip
|
||||
if nodelist[i][0] == token.NAME:
|
||||
kwonlyargs, skip = self.keywordonlyargs(nodelist[i:])
|
||||
i += skip
|
||||
|
||||
print "kwonlyargs:", kwonlyargs
|
||||
|
||||
if i < len(nodelist):
|
||||
# should be DOUBLESTAR
|
||||
|
@ -831,7 +869,8 @@ class Transformer:
|
|||
# skip the comma
|
||||
i = i + 1
|
||||
|
||||
return names, defaults, flags
|
||||
print "names:", names, "defaults:", defaults, "kwonlyargs:", kwonlyargs, "flags:", flags
|
||||
return names, defaults, kwonlyargs, flags
|
||||
|
||||
def com_fpdef(self, node):
|
||||
# fpdef: NAME | '(' fplist ')'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue