summaryrefslogtreecommitdiffstats
path: root/Lib/compiler
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2006-10-27 23:31:49 (GMT)
committerGuido van Rossum <guido@python.org>2006-10-27 23:31:49 (GMT)
commit4f72a78684bbfcdc43ceeabb240ceee54706c4b0 (patch)
tree743c27c5125dcef580cffe77395fe97bedf40d5f /Lib/compiler
parentfc2a0a8e3cb1d40fd965576060c28c8bd2ea1ad5 (diff)
downloadcpython-4f72a78684bbfcdc43ceeabb240ceee54706c4b0.zip
cpython-4f72a78684bbfcdc43ceeabb240ceee54706c4b0.tar.gz
cpython-4f72a78684bbfcdc43ceeabb240ceee54706c4b0.tar.bz2
Jiwon Seo's PEP 3102 implementation.
See SF#1549670. The compiler package has not yet been updated.
Diffstat (limited to 'Lib/compiler')
-rw-r--r--Lib/compiler/ast.py13
-rw-r--r--Lib/compiler/pyassem.py11
-rw-r--r--Lib/compiler/pycodegen.py15
-rw-r--r--Lib/compiler/transformer.py61
4 files changed, 82 insertions, 18 deletions
diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py
index 0be36a4..d21905f 100644
--- a/Lib/compiler/ast.py
+++ b/Lib/compiler/ast.py
@@ -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):
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py
index 5e3eb30..7f44d46 100644
--- a/Lib/compiler/pyassem.py
+++ b/Lib/compiler/pyassem.py
@@ -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
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index 83d0481..b08a307 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -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()
diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py
index 0ffb597..7b1e31c 100644
--- a/Lib/compiler/transformer.py
+++ b/Lib/compiler/transformer.py
@@ -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 ')'