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
|
@ -24,7 +24,7 @@ decorators: decorator+
|
||||||
funcdef: [decorators] 'def' NAME parameters ':' suite
|
funcdef: [decorators] 'def' NAME parameters ':' suite
|
||||||
parameters: '(' [varargslist] ')'
|
parameters: '(' [varargslist] ')'
|
||||||
varargslist: ((fpdef ['=' test] ',')*
|
varargslist: ((fpdef ['=' test] ',')*
|
||||||
('*' NAME [',' '**' NAME] | '**' NAME) |
|
('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME) |
|
||||||
fpdef ['=' test] (',' fpdef ['=' test])* [','])
|
fpdef ['=' test] (',' fpdef ['=' test])* [','])
|
||||||
fpdef: NAME | '(' fplist ')'
|
fpdef: NAME | '(' fplist ')'
|
||||||
fplist: fpdef (',' fpdef)* [',']
|
fplist: fpdef (',' fpdef)* [',']
|
||||||
|
|
|
@ -328,8 +328,10 @@ struct _excepthandler {
|
||||||
struct _arguments {
|
struct _arguments {
|
||||||
asdl_seq *args;
|
asdl_seq *args;
|
||||||
identifier vararg;
|
identifier vararg;
|
||||||
|
asdl_seq *kwonlyargs;
|
||||||
identifier kwarg;
|
identifier kwarg;
|
||||||
asdl_seq *defaults;
|
asdl_seq *defaults;
|
||||||
|
asdl_seq *kw_defaults;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _keyword {
|
struct _keyword {
|
||||||
|
@ -427,8 +429,9 @@ comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs,
|
||||||
PyArena *arena);
|
PyArena *arena);
|
||||||
excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int
|
excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int
|
||||||
lineno, int col_offset, PyArena *arena);
|
lineno, int col_offset, PyArena *arena);
|
||||||
arguments_ty arguments(asdl_seq * args, identifier vararg, identifier kwarg,
|
arguments_ty arguments(asdl_seq * args, identifier vararg, asdl_seq *
|
||||||
asdl_seq * defaults, PyArena *arena);
|
kwonlyargs, identifier kwarg, asdl_seq * defaults,
|
||||||
|
asdl_seq * kw_defaults, PyArena *arena);
|
||||||
keyword_ty keyword(identifier arg, expr_ty value, PyArena *arena);
|
keyword_ty keyword(identifier arg, expr_ty value, PyArena *arena);
|
||||||
alias_ty alias(identifier name, identifier asname, PyArena *arena);
|
alias_ty alias(identifier name, identifier asname, PyArena *arena);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
int co_argcount; /* #arguments, except *args */
|
int co_argcount; /* #arguments, except *args */
|
||||||
|
int co_kwonlyargcount; /* #keyword only arguments */
|
||||||
int co_nlocals; /* #local variables */
|
int co_nlocals; /* #local variables */
|
||||||
int co_stacksize; /* #entries needed for evaluation stack */
|
int co_stacksize; /* #entries needed for evaluation stack */
|
||||||
int co_flags; /* CO_..., see below */
|
int co_flags; /* CO_..., see below */
|
||||||
|
@ -63,8 +64,9 @@ PyAPI_DATA(PyTypeObject) PyCode_Type;
|
||||||
|
|
||||||
/* Public interface */
|
/* Public interface */
|
||||||
PyAPI_FUNC(PyCodeObject *) PyCode_New(
|
PyAPI_FUNC(PyCodeObject *) PyCode_New(
|
||||||
int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *,
|
int, int, int, int, int, PyObject *, PyObject *,
|
||||||
PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *);
|
PyObject *, PyObject *, PyObject *, PyObject *,
|
||||||
|
PyObject *, PyObject *, int, PyObject *);
|
||||||
/* same as struct above */
|
/* same as struct above */
|
||||||
PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
|
PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyCodeObject *co,
|
||||||
PyObject **args, int argc,
|
PyObject **args, int argc,
|
||||||
PyObject **kwds, int kwdc,
|
PyObject **kwds, int kwdc,
|
||||||
PyObject **defs, int defc,
|
PyObject **defs, int defc,
|
||||||
PyObject *closure);
|
PyObject *kwdefs, PyObject *closure);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) _PyEval_CallTracing(PyObject *func, PyObject *args);
|
PyAPI_FUNC(PyObject *) _PyEval_CallTracing(PyObject *func, PyObject *args);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef struct {
|
||||||
PyObject *func_code; /* A code object */
|
PyObject *func_code; /* A code object */
|
||||||
PyObject *func_globals; /* A dictionary (other mappings won't do) */
|
PyObject *func_globals; /* A dictionary (other mappings won't do) */
|
||||||
PyObject *func_defaults; /* NULL or a tuple */
|
PyObject *func_defaults; /* NULL or a tuple */
|
||||||
|
PyObject *func_kwdefaults; /* NULL or a dict */
|
||||||
PyObject *func_closure; /* NULL or a tuple of cell objects */
|
PyObject *func_closure; /* NULL or a tuple of cell objects */
|
||||||
PyObject *func_doc; /* The __doc__ attribute, can be anything */
|
PyObject *func_doc; /* The __doc__ attribute, can be anything */
|
||||||
PyObject *func_name; /* The __name__ attribute, a string object */
|
PyObject *func_name; /* The __name__ attribute, a string object */
|
||||||
|
@ -47,6 +48,8 @@ PyAPI_FUNC(PyObject *) PyFunction_GetGlobals(PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_GetDefaults(PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_GetDefaults(PyObject *);
|
||||||
PyAPI_FUNC(int) PyFunction_SetDefaults(PyObject *, PyObject *);
|
PyAPI_FUNC(int) PyFunction_SetDefaults(PyObject *, PyObject *);
|
||||||
|
PyAPI_FUNC(PyObject *) PyFunction_GetKwDefaults(PyObject *);
|
||||||
|
PyAPI_FUNC(int) PyFunction_SetKwDefaults(PyObject *, PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) PyFunction_GetClosure(PyObject *);
|
PyAPI_FUNC(PyObject *) PyFunction_GetClosure(PyObject *);
|
||||||
PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
||||||
|
|
||||||
|
@ -60,6 +63,8 @@ PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
||||||
(((PyFunctionObject *)func) -> func_module)
|
(((PyFunctionObject *)func) -> func_module)
|
||||||
#define PyFunction_GET_DEFAULTS(func) \
|
#define PyFunction_GET_DEFAULTS(func) \
|
||||||
(((PyFunctionObject *)func) -> func_defaults)
|
(((PyFunctionObject *)func) -> func_defaults)
|
||||||
|
#define PyFunction_GET_KW_DEFAULTS(func) \
|
||||||
|
(((PyFunctionObject *)func) -> func_kwdefaults)
|
||||||
#define PyFunction_GET_CLOSURE(func) \
|
#define PyFunction_GET_CLOSURE(func) \
|
||||||
(((PyFunctionObject *)func) -> func_closure)
|
(((PyFunctionObject *)func) -> func_closure)
|
||||||
|
|
||||||
|
|
|
@ -487,11 +487,12 @@ class From(Node):
|
||||||
return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
|
return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
|
||||||
|
|
||||||
class Function(Node):
|
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.decorators = decorators
|
||||||
self.name = name
|
self.name = name
|
||||||
self.argnames = argnames
|
self.argnames = argnames
|
||||||
self.defaults = defaults
|
self.defaults = defaults
|
||||||
|
self.kwonlyargs = kwonlyargs
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.code = code
|
self.code = code
|
||||||
|
@ -509,6 +510,7 @@ class Function(Node):
|
||||||
children.append(self.name)
|
children.append(self.name)
|
||||||
children.append(self.argnames)
|
children.append(self.argnames)
|
||||||
children.extend(flatten(self.defaults))
|
children.extend(flatten(self.defaults))
|
||||||
|
children.append(self.kwonlyargs)
|
||||||
children.append(self.flags)
|
children.append(self.flags)
|
||||||
children.append(self.doc)
|
children.append(self.doc)
|
||||||
children.append(self.code)
|
children.append(self.code)
|
||||||
|
@ -523,7 +525,7 @@ class Function(Node):
|
||||||
return tuple(nodelist)
|
return tuple(nodelist)
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
class GenExpr(Node):
|
||||||
def __init__(self, code, lineno=None):
|
def __init__(self, code, lineno=None):
|
||||||
|
@ -531,6 +533,7 @@ class GenExpr(Node):
|
||||||
self.lineno = lineno
|
self.lineno = lineno
|
||||||
self.argnames = ['.0']
|
self.argnames = ['.0']
|
||||||
self.varargs = self.kwargs = None
|
self.varargs = self.kwargs = None
|
||||||
|
self.kwonlyargs = ()
|
||||||
|
|
||||||
|
|
||||||
def getChildren(self):
|
def getChildren(self):
|
||||||
|
@ -713,9 +716,10 @@ class Keyword(Node):
|
||||||
return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
|
return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
|
||||||
|
|
||||||
class Lambda(Node):
|
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.argnames = argnames
|
||||||
self.defaults = defaults
|
self.defaults = defaults
|
||||||
|
self.kwonlyargs = kwonlyargs
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.code = code
|
self.code = code
|
||||||
self.lineno = lineno
|
self.lineno = lineno
|
||||||
|
@ -730,6 +734,7 @@ class Lambda(Node):
|
||||||
children = []
|
children = []
|
||||||
children.append(self.argnames)
|
children.append(self.argnames)
|
||||||
children.extend(flatten(self.defaults))
|
children.extend(flatten(self.defaults))
|
||||||
|
children.append(self.kwonlyargs)
|
||||||
children.append(self.flags)
|
children.append(self.flags)
|
||||||
children.append(self.code)
|
children.append(self.code)
|
||||||
return tuple(children)
|
return tuple(children)
|
||||||
|
@ -741,7 +746,7 @@ class Lambda(Node):
|
||||||
return tuple(nodelist)
|
return tuple(nodelist)
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
class LeftShift(Node):
|
||||||
def __init__(self, (left, right), lineno=None):
|
def __init__(self, (left, right), lineno=None):
|
||||||
|
|
|
@ -313,13 +313,15 @@ DONE = "DONE"
|
||||||
class PyFlowGraph(FlowGraph):
|
class PyFlowGraph(FlowGraph):
|
||||||
super_init = FlowGraph.__init__
|
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.super_init()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.docstring = None
|
self.docstring = None
|
||||||
self.args = args # XXX
|
self.args = args # XXX
|
||||||
self.argcount = getArgCount(args)
|
self.argcount = getArgCount(args)
|
||||||
|
self.kwonlyargs = kwonlyargs
|
||||||
self.klass = klass
|
self.klass = klass
|
||||||
if optimized:
|
if optimized:
|
||||||
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
|
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
|
||||||
|
@ -595,7 +597,9 @@ class PyFlowGraph(FlowGraph):
|
||||||
argcount = self.argcount
|
argcount = self.argcount
|
||||||
if self.flags & CO_VARKEYWORDS:
|
if self.flags & CO_VARKEYWORDS:
|
||||||
argcount = argcount - 1
|
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(),
|
self.lnotab.getCode(), self.getConsts(),
|
||||||
tuple(self.names), tuple(self.varnames),
|
tuple(self.names), tuple(self.varnames),
|
||||||
self.filename, self.name, self.lnotab.firstline,
|
self.filename, self.name, self.lnotab.firstline,
|
||||||
|
@ -804,7 +808,8 @@ class StackDepthTracker:
|
||||||
def CALL_FUNCTION_VAR_KW(self, argc):
|
def CALL_FUNCTION_VAR_KW(self, argc):
|
||||||
return self.CALL_FUNCTION(argc)-2
|
return self.CALL_FUNCTION(argc)-2
|
||||||
def MAKE_FUNCTION(self, argc):
|
def MAKE_FUNCTION(self, argc):
|
||||||
return -argc
|
hi, lo = divmod(argc, 256)
|
||||||
|
return -(lo + hi * 2)
|
||||||
def MAKE_CLOSURE(self, argc):
|
def MAKE_CLOSURE(self, argc):
|
||||||
# XXX need to account for free variables too!
|
# XXX need to account for free variables too!
|
||||||
return -argc
|
return -argc
|
||||||
|
|
|
@ -378,6 +378,12 @@ class CodeGenerator:
|
||||||
walk(node.code, gen)
|
walk(node.code, gen)
|
||||||
gen.finish()
|
gen.finish()
|
||||||
self.set_lineno(node)
|
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:
|
for default in node.defaults:
|
||||||
self.visit(default)
|
self.visit(default)
|
||||||
self._makeClosure(gen, len(node.defaults))
|
self._makeClosure(gen, len(node.defaults))
|
||||||
|
@ -1320,7 +1326,9 @@ class AbstractFunctionCode:
|
||||||
name = func.name
|
name = func.name
|
||||||
|
|
||||||
args, hasTupleArg = generateArgList(func.argnames)
|
args, hasTupleArg = generateArgList(func.argnames)
|
||||||
|
kwonlyargs = generateKwonlyArgList(func.kwonlyargs)
|
||||||
self.graph = pyassem.PyFlowGraph(name, func.filename, args,
|
self.graph = pyassem.PyFlowGraph(name, func.filename, args,
|
||||||
|
kwonlyargs=kwonlyargs,
|
||||||
optimized=1)
|
optimized=1)
|
||||||
self.isLambda = isLambda
|
self.isLambda = isLambda
|
||||||
self.super_init()
|
self.super_init()
|
||||||
|
@ -1456,6 +1464,13 @@ def generateArgList(arglist):
|
||||||
raise ValueError, "unexpect argument type:", elt
|
raise ValueError, "unexpect argument type:", elt
|
||||||
return args + extra, count
|
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):
|
def findOp(node):
|
||||||
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
|
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
|
||||||
v = OpFinder()
|
v = OpFinder()
|
||||||
|
|
|
@ -250,9 +250,9 @@ class Transformer:
|
||||||
args = nodelist[-3][2]
|
args = nodelist[-3][2]
|
||||||
|
|
||||||
if args[0] == symbol.varargslist:
|
if args[0] == symbol.varargslist:
|
||||||
names, defaults, flags = self.com_arglist(args[1:])
|
names, defaults, kwonlyargs, flags = self.com_arglist(args[1:])
|
||||||
else:
|
else:
|
||||||
names = defaults = ()
|
names = defaults = kwonlyargs = ()
|
||||||
flags = 0
|
flags = 0
|
||||||
doc = self.get_docstring(nodelist[-1])
|
doc = self.get_docstring(nodelist[-1])
|
||||||
|
|
||||||
|
@ -263,21 +263,23 @@ class Transformer:
|
||||||
assert isinstance(code, Stmt)
|
assert isinstance(code, Stmt)
|
||||||
assert isinstance(code.nodes[0], Discard)
|
assert isinstance(code.nodes[0], Discard)
|
||||||
del code.nodes[0]
|
del code.nodes[0]
|
||||||
return Function(decorators, name, names, defaults, flags, doc, code,
|
return Function(decorators, name, names, defaults,
|
||||||
lineno=lineno)
|
kwonlyargs, flags, doc, code, lineno=lineno)
|
||||||
|
|
||||||
def lambdef(self, nodelist):
|
def lambdef(self, nodelist):
|
||||||
# lambdef: 'lambda' [varargslist] ':' test
|
# lambdef: 'lambda' [varargslist] ':' test
|
||||||
if nodelist[2][0] == symbol.varargslist:
|
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:
|
else:
|
||||||
names = defaults = ()
|
names = defaults = kwonlyargs = ()
|
||||||
flags = 0
|
flags = 0
|
||||||
|
|
||||||
# code for lambda
|
# code for lambda
|
||||||
code = self.com_node(nodelist[-1])
|
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
|
old_lambdef = lambdef
|
||||||
|
|
||||||
def classdef(self, nodelist):
|
def classdef(self, nodelist):
|
||||||
|
@ -783,13 +785,37 @@ class Transformer:
|
||||||
# ('const', xxxx)) Nodes)
|
# ('const', xxxx)) Nodes)
|
||||||
return Discard(Const(None))
|
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):
|
def com_arglist(self, nodelist):
|
||||||
# varargslist:
|
# varargslist:
|
||||||
# (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
|
# (fpdef ['=' test] ',')*
|
||||||
|
# ('*' [NAME] (',' NAME '=' test)* [',' '**' NAME] | '**' NAME)
|
||||||
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||||
# fpdef: NAME | '(' fplist ')'
|
# fpdef: NAME | '(' fplist ')'
|
||||||
# fplist: fpdef (',' fpdef)* [',']
|
# fplist: fpdef (',' fpdef)* [',']
|
||||||
names = []
|
names = []
|
||||||
|
kwonlyargs = []
|
||||||
defaults = []
|
defaults = []
|
||||||
flags = 0
|
flags = 0
|
||||||
|
|
||||||
|
@ -799,10 +825,22 @@ class Transformer:
|
||||||
if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
|
if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
|
||||||
if node[0] == token.STAR:
|
if node[0] == token.STAR:
|
||||||
node = nodelist[i+1]
|
node = nodelist[i+1]
|
||||||
if node[0] == token.NAME:
|
if node[0] == token.NAME: # vararg
|
||||||
names.append(node[1])
|
names.append(node[1])
|
||||||
flags = flags | CO_VARARGS
|
flags = flags | CO_VARARGS
|
||||||
i = i + 3
|
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):
|
if i < len(nodelist):
|
||||||
# should be DOUBLESTAR
|
# should be DOUBLESTAR
|
||||||
|
@ -831,7 +869,8 @@ class Transformer:
|
||||||
# skip the comma
|
# skip the comma
|
||||||
i = i + 1
|
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):
|
def com_fpdef(self, node):
|
||||||
# fpdef: NAME | '(' fplist ')'
|
# fpdef: NAME | '(' fplist ')'
|
||||||
|
|
|
@ -9,9 +9,9 @@ test_extcall
|
||||||
(1, 2, 3) {'a': 4, 'b': 5}
|
(1, 2, 3) {'a': 4, 'b': 5}
|
||||||
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
|
||||||
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
|
||||||
TypeError: g() takes at least 1 argument (0 given)
|
TypeError: g() takes at least 1 positional argument (0 given)
|
||||||
TypeError: g() takes at least 1 argument (0 given)
|
TypeError: g() takes at least 1 positional argument (0 given)
|
||||||
TypeError: g() takes at least 1 argument (0 given)
|
TypeError: g() takes at least 1 positional argument (0 given)
|
||||||
1 () {}
|
1 () {}
|
||||||
1 (2,) {}
|
1 (2,) {}
|
||||||
1 (2, 3) {}
|
1 (2, 3) {}
|
||||||
|
@ -35,24 +35,24 @@ dir() got multiple values for keyword argument 'b'
|
||||||
3 512 True
|
3 512 True
|
||||||
3
|
3
|
||||||
3
|
3
|
||||||
za () {} -> za() takes exactly 1 argument (0 given)
|
za () {} -> za() takes exactly 1 positional argument (0 given)
|
||||||
za () {'a': 'aa'} -> ok za aa B D E V a
|
za () {'a': 'aa'} -> ok za aa B D E V a
|
||||||
za () {'d': 'dd'} -> za() got an unexpected keyword argument 'd'
|
za () {'d': 'dd'} -> za() got an unexpected keyword argument 'd'
|
||||||
za () {'a': 'aa', 'd': 'dd'} -> za() got an unexpected keyword argument 'd'
|
za () {'a': 'aa', 'd': 'dd'} -> za() got an unexpected keyword argument 'd'
|
||||||
za () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() got an unexpected keyword argument 'b'
|
za () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() got an unexpected keyword argument 'b'
|
||||||
za (1, 2) {} -> za() takes exactly 1 argument (2 given)
|
za (1, 2) {} -> za() takes exactly 1 positional argument (2 given)
|
||||||
za (1, 2) {'a': 'aa'} -> za() takes exactly 1 non-keyword argument (2 given)
|
za (1, 2) {'a': 'aa'} -> za() takes exactly 1 non-keyword positional argument (2 given)
|
||||||
za (1, 2) {'d': 'dd'} -> za() takes exactly 1 non-keyword argument (2 given)
|
za (1, 2) {'d': 'dd'} -> za() takes exactly 1 non-keyword positional argument (2 given)
|
||||||
za (1, 2) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword argument (2 given)
|
za (1, 2) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword positional argument (2 given)
|
||||||
za (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword argument (2 given)
|
za (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword positional argument (2 given)
|
||||||
za (1, 2, 3, 4, 5) {} -> za() takes exactly 1 argument (5 given)
|
za (1, 2, 3, 4, 5) {} -> za() takes exactly 1 positional argument (5 given)
|
||||||
za (1, 2, 3, 4, 5) {'a': 'aa'} -> za() takes exactly 1 non-keyword argument (5 given)
|
za (1, 2, 3, 4, 5) {'a': 'aa'} -> za() takes exactly 1 non-keyword positional argument (5 given)
|
||||||
za (1, 2, 3, 4, 5) {'d': 'dd'} -> za() takes exactly 1 non-keyword argument (5 given)
|
za (1, 2, 3, 4, 5) {'d': 'dd'} -> za() takes exactly 1 non-keyword positional argument (5 given)
|
||||||
za (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword argument (5 given)
|
za (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword positional argument (5 given)
|
||||||
za (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword argument (5 given)
|
za (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword positional argument (5 given)
|
||||||
zade () {} -> zade() takes at least 1 argument (0 given)
|
zade () {} -> zade() takes at least 1 positional argument (0 given)
|
||||||
zade () {'a': 'aa'} -> ok zade aa B d e V a
|
zade () {'a': 'aa'} -> ok zade aa B d e V a
|
||||||
zade () {'d': 'dd'} -> zade() takes at least 1 non-keyword argument (0 given)
|
zade () {'d': 'dd'} -> zade() takes at least 1 non-keyword positional argument (0 given)
|
||||||
zade () {'a': 'aa', 'd': 'dd'} -> ok zade aa B dd e V d
|
zade () {'a': 'aa', 'd': 'dd'} -> ok zade aa B dd e V d
|
||||||
zade () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got an unexpected keyword argument 'b'
|
zade () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got an unexpected keyword argument 'b'
|
||||||
zade (1, 2) {} -> ok zade 1 B 2 e V e
|
zade (1, 2) {} -> ok zade 1 B 2 e V e
|
||||||
|
@ -60,30 +60,30 @@ zade (1, 2) {'a': 'aa'} -> zade() got multiple values for keyword argument 'a'
|
||||||
zade (1, 2) {'d': 'dd'} -> zade() got multiple values for keyword argument 'd'
|
zade (1, 2) {'d': 'dd'} -> zade() got multiple values for keyword argument 'd'
|
||||||
zade (1, 2) {'a': 'aa', 'd': 'dd'} -> zade() got multiple values for keyword argument 'a'
|
zade (1, 2) {'a': 'aa', 'd': 'dd'} -> zade() got multiple values for keyword argument 'a'
|
||||||
zade (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got multiple values for keyword argument 'a'
|
zade (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got multiple values for keyword argument 'a'
|
||||||
zade (1, 2, 3, 4, 5) {} -> zade() takes at most 3 arguments (5 given)
|
zade (1, 2, 3, 4, 5) {} -> zade() takes at most 3 positional arguments (5 given)
|
||||||
zade (1, 2, 3, 4, 5) {'a': 'aa'} -> zade() takes at most 3 non-keyword arguments (5 given)
|
zade (1, 2, 3, 4, 5) {'a': 'aa'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
|
||||||
zade (1, 2, 3, 4, 5) {'d': 'dd'} -> zade() takes at most 3 non-keyword arguments (5 given)
|
zade (1, 2, 3, 4, 5) {'d': 'dd'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
|
||||||
zade (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zade() takes at most 3 non-keyword arguments (5 given)
|
zade (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
|
||||||
zade (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() takes at most 3 non-keyword arguments (5 given)
|
zade (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
|
||||||
zabk () {} -> zabk() takes exactly 2 arguments (0 given)
|
zabk () {} -> zabk() takes exactly 2 positional arguments (0 given)
|
||||||
zabk () {'a': 'aa'} -> zabk() takes exactly 2 non-keyword arguments (1 given)
|
zabk () {'a': 'aa'} -> zabk() takes exactly 2 non-keyword positional arguments (1 given)
|
||||||
zabk () {'d': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (0 given)
|
zabk () {'d': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (0 given)
|
||||||
zabk () {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (1 given)
|
zabk () {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (1 given)
|
||||||
zabk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabk aa bb D E V {'d': 'dd', 'e': 'ee'}
|
zabk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabk aa bb D E V {'d': 'dd', 'e': 'ee'}
|
||||||
zabk (1, 2) {} -> ok zabk 1 2 D E V {}
|
zabk (1, 2) {} -> ok zabk 1 2 D E V {}
|
||||||
zabk (1, 2) {'a': 'aa'} -> zabk() got multiple values for keyword argument 'a'
|
zabk (1, 2) {'a': 'aa'} -> zabk() got multiple values for keyword argument 'a'
|
||||||
zabk (1, 2) {'d': 'dd'} -> ok zabk 1 2 D E V {'d': 'dd'}
|
zabk (1, 2) {'d': 'dd'} -> ok zabk 1 2 D E V {'d': 'dd'}
|
||||||
zabk (1, 2) {'a': 'aa', 'd': 'dd'} -> zabk() got multiple values for keyword argument 'a'
|
zabk (1, 2) {'a': 'aa', 'd': 'dd'} -> zabk() got multiple values for keyword argument 'a'
|
||||||
zabk (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() got multiple values for keyword argument 'a'
|
zabk (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() got multiple values for keyword argument 'a'
|
||||||
zabk (1, 2, 3, 4, 5) {} -> zabk() takes exactly 2 arguments (5 given)
|
zabk (1, 2, 3, 4, 5) {} -> zabk() takes exactly 2 positional arguments (5 given)
|
||||||
zabk (1, 2, 3, 4, 5) {'a': 'aa'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
|
zabk (1, 2, 3, 4, 5) {'a': 'aa'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
|
||||||
zabk (1, 2, 3, 4, 5) {'d': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
|
zabk (1, 2, 3, 4, 5) {'d': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
|
||||||
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
|
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
|
||||||
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
|
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
|
||||||
zabdv () {} -> zabdv() takes at least 2 arguments (0 given)
|
zabdv () {} -> zabdv() takes at least 2 positional arguments (0 given)
|
||||||
zabdv () {'a': 'aa'} -> zabdv() takes at least 2 non-keyword arguments (1 given)
|
zabdv () {'a': 'aa'} -> zabdv() takes at least 2 non-keyword positional arguments (1 given)
|
||||||
zabdv () {'d': 'dd'} -> zabdv() takes at least 2 non-keyword arguments (0 given)
|
zabdv () {'d': 'dd'} -> zabdv() takes at least 2 non-keyword positional arguments (0 given)
|
||||||
zabdv () {'a': 'aa', 'd': 'dd'} -> zabdv() takes at least 2 non-keyword arguments (1 given)
|
zabdv () {'a': 'aa', 'd': 'dd'} -> zabdv() takes at least 2 non-keyword positional arguments (1 given)
|
||||||
zabdv () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got an unexpected keyword argument 'e'
|
zabdv () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got an unexpected keyword argument 'e'
|
||||||
zabdv (1, 2) {} -> ok zabdv 1 2 d E () e
|
zabdv (1, 2) {} -> ok zabdv 1 2 d E () e
|
||||||
zabdv (1, 2) {'a': 'aa'} -> zabdv() got multiple values for keyword argument 'a'
|
zabdv (1, 2) {'a': 'aa'} -> zabdv() got multiple values for keyword argument 'a'
|
||||||
|
@ -95,10 +95,10 @@ zabdv (1, 2, 3, 4, 5) {'a': 'aa'} -> zabdv() got multiple values for keyword arg
|
||||||
zabdv (1, 2, 3, 4, 5) {'d': 'dd'} -> zabdv() got multiple values for keyword argument 'd'
|
zabdv (1, 2, 3, 4, 5) {'d': 'dd'} -> zabdv() got multiple values for keyword argument 'd'
|
||||||
zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabdv() got multiple values for keyword argument 'a'
|
zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabdv() got multiple values for keyword argument 'a'
|
||||||
zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got multiple values for keyword argument 'a'
|
zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got multiple values for keyword argument 'a'
|
||||||
zabdevk () {} -> zabdevk() takes at least 2 arguments (0 given)
|
zabdevk () {} -> zabdevk() takes at least 2 positional arguments (0 given)
|
||||||
zabdevk () {'a': 'aa'} -> zabdevk() takes at least 2 non-keyword arguments (1 given)
|
zabdevk () {'a': 'aa'} -> zabdevk() takes at least 2 non-keyword positional arguments (1 given)
|
||||||
zabdevk () {'d': 'dd'} -> zabdevk() takes at least 2 non-keyword arguments (0 given)
|
zabdevk () {'d': 'dd'} -> zabdevk() takes at least 2 non-keyword positional arguments (0 given)
|
||||||
zabdevk () {'a': 'aa', 'd': 'dd'} -> zabdevk() takes at least 2 non-keyword arguments (1 given)
|
zabdevk () {'a': 'aa', 'd': 'dd'} -> zabdevk() takes at least 2 non-keyword positional arguments (1 given)
|
||||||
zabdevk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabdevk aa bb dd ee () {}
|
zabdevk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabdevk aa bb dd ee () {}
|
||||||
zabdevk (1, 2) {} -> ok zabdevk 1 2 d e () {}
|
zabdevk (1, 2) {} -> ok zabdevk 1 2 d e () {}
|
||||||
zabdevk (1, 2) {'a': 'aa'} -> zabdevk() got multiple values for keyword argument 'a'
|
zabdevk (1, 2) {'a': 'aa'} -> zabdevk() got multiple values for keyword argument 'a'
|
||||||
|
|
|
@ -151,9 +151,9 @@ def run_tests():
|
||||||
|
|
||||||
#### EVERYTHING BELOW IS GENERATED #####
|
#### EVERYTHING BELOW IS GENERATED #####
|
||||||
exec_results = [
|
exec_results = [
|
||||||
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Pass', (1, 9))], [])]),
|
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], None, [], []), [('Pass', (1, 9))], [])]),
|
||||||
('Module', [('ClassDef', (1, 0), 'C', [], [('Pass', (1, 8))])]),
|
('Module', [('ClassDef', (1, 0), 'C', [], [('Pass', (1, 8))])]),
|
||||||
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [])]),
|
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], None, [], []), [('Return', (1, 8), ('Num', (1, 15), 1))], [])]),
|
||||||
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]),
|
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]),
|
||||||
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]),
|
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]),
|
||||||
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]),
|
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]),
|
||||||
|
@ -180,7 +180,7 @@ eval_results = [
|
||||||
('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])),
|
('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])),
|
||||||
('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))),
|
('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))),
|
||||||
('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))),
|
('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))),
|
||||||
('Expression', ('Lambda', (1, 0), ('arguments', [], None, None, []), ('Name', (1, 7), 'None', ('Load',)))),
|
('Expression', ('Lambda', (1, 0), ('arguments', [], None, [], None, [], []), ('Name', (1, 7), 'None', ('Load',)))),
|
||||||
('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])),
|
('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])),
|
||||||
('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
|
('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
|
||||||
('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
|
('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
>>> dump(f.func_code)
|
>>> dump(f.func_code)
|
||||||
name: f
|
name: f
|
||||||
argcount: 1
|
argcount: 1
|
||||||
|
kwonlyargcount: 0
|
||||||
names: ()
|
names: ()
|
||||||
varnames: ('x', 'g')
|
varnames: ('x', 'g')
|
||||||
cellvars: ('x',)
|
cellvars: ('x',)
|
||||||
|
@ -20,6 +21,7 @@ consts: ('None', '<code object g>')
|
||||||
>>> dump(f(4).func_code)
|
>>> dump(f(4).func_code)
|
||||||
name: g
|
name: g
|
||||||
argcount: 1
|
argcount: 1
|
||||||
|
kwonlyargcount: 0
|
||||||
names: ()
|
names: ()
|
||||||
varnames: ('y',)
|
varnames: ('y',)
|
||||||
cellvars: ()
|
cellvars: ()
|
||||||
|
@ -34,9 +36,11 @@ consts: ('None',)
|
||||||
... c = a * b
|
... c = a * b
|
||||||
... return c
|
... return c
|
||||||
...
|
...
|
||||||
|
|
||||||
>>> dump(h.func_code)
|
>>> dump(h.func_code)
|
||||||
name: h
|
name: h
|
||||||
argcount: 2
|
argcount: 2
|
||||||
|
kwonlyargcount: 0
|
||||||
names: ()
|
names: ()
|
||||||
varnames: ('x', 'y', 'a', 'b', 'c')
|
varnames: ('x', 'y', 'a', 'b', 'c')
|
||||||
cellvars: ()
|
cellvars: ()
|
||||||
|
@ -53,6 +57,7 @@ consts: ('None',)
|
||||||
>>> dump(attrs.func_code)
|
>>> dump(attrs.func_code)
|
||||||
name: attrs
|
name: attrs
|
||||||
argcount: 1
|
argcount: 1
|
||||||
|
kwonlyargcount: 0
|
||||||
names: ('attr1', 'attr2', 'attr3')
|
names: ('attr1', 'attr2', 'attr3')
|
||||||
varnames: ('obj',)
|
varnames: ('obj',)
|
||||||
cellvars: ()
|
cellvars: ()
|
||||||
|
@ -70,6 +75,7 @@ consts: ('None',)
|
||||||
>>> dump(optimize_away.func_code)
|
>>> dump(optimize_away.func_code)
|
||||||
name: optimize_away
|
name: optimize_away
|
||||||
argcount: 0
|
argcount: 0
|
||||||
|
kwonlyargcount: 0
|
||||||
names: ()
|
names: ()
|
||||||
varnames: ()
|
varnames: ()
|
||||||
cellvars: ()
|
cellvars: ()
|
||||||
|
@ -78,6 +84,22 @@ nlocals: 0
|
||||||
flags: 67
|
flags: 67
|
||||||
consts: ("'doc string'", 'None')
|
consts: ("'doc string'", 'None')
|
||||||
|
|
||||||
|
>>> def keywordonly_args(a,b,*,k1):
|
||||||
|
... return a,b,k1
|
||||||
|
...
|
||||||
|
|
||||||
|
>>> dump(keywordonly_args.func_code)
|
||||||
|
name: keywordonly_args
|
||||||
|
argcount: 2
|
||||||
|
kwonlyargcount: 1
|
||||||
|
names: ()
|
||||||
|
varnames: ('a', 'b', 'k1')
|
||||||
|
cellvars: ()
|
||||||
|
freevars: ()
|
||||||
|
nlocals: 3
|
||||||
|
flags: 67
|
||||||
|
consts: ('None',)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def consts(t):
|
def consts(t):
|
||||||
|
@ -91,8 +113,8 @@ def consts(t):
|
||||||
|
|
||||||
def dump(co):
|
def dump(co):
|
||||||
"""Print out a text representation of a code object."""
|
"""Print out a text representation of a code object."""
|
||||||
for attr in ["name", "argcount", "names", "varnames", "cellvars",
|
for attr in ["name", "argcount", "kwonlyargcount", "names", "varnames",
|
||||||
"freevars", "nlocals", "flags"]:
|
"cellvars", "freevars", "nlocals", "flags"]:
|
||||||
print "%s: %s" % (attr, getattr(co, "co_" + attr))
|
print "%s: %s" % (attr, getattr(co, "co_" + attr))
|
||||||
print "consts:", tuple(consts(co.co_consts))
|
print "consts:", tuple(consts(co.co_consts))
|
||||||
|
|
||||||
|
|
|
@ -19,36 +19,51 @@ class CompilerTest(unittest.TestCase):
|
||||||
libdir = os.path.dirname(unittest.__file__)
|
libdir = os.path.dirname(unittest.__file__)
|
||||||
testdir = os.path.dirname(test.test_support.__file__)
|
testdir = os.path.dirname(test.test_support.__file__)
|
||||||
|
|
||||||
for dir in [libdir, testdir]:
|
## for dir in [libdir, testdir]:
|
||||||
for basename in os.listdir(dir):
|
## for basename in os.listdir(dir):
|
||||||
# Print still working message since this test can be really slow
|
## # Print still working message since this test can be really slow
|
||||||
if next_time <= time.time():
|
## if next_time <= time.time():
|
||||||
next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL
|
## next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL
|
||||||
print >>sys.__stdout__, \
|
## print >>sys.__stdout__, \
|
||||||
' testCompileLibrary still working, be patient...'
|
## ' testCompileLibrary still working, be patient...'
|
||||||
sys.__stdout__.flush()
|
## sys.__stdout__.flush()
|
||||||
|
##
|
||||||
|
## if not basename.endswith(".py"):
|
||||||
|
## continue
|
||||||
|
## if not TEST_ALL and random() < 0.98:
|
||||||
|
## continue
|
||||||
|
## path = os.path.join(dir, basename)
|
||||||
|
## if test.test_support.verbose:
|
||||||
|
## print "compiling", path
|
||||||
|
## f = open(path, "U")
|
||||||
|
## buf = f.read()
|
||||||
|
## f.close()
|
||||||
|
## if "badsyntax" in basename or "bad_coding" in basename:
|
||||||
|
## self.assertRaises(SyntaxError, compiler.compile,
|
||||||
|
## buf, basename, "exec")
|
||||||
|
## else:
|
||||||
|
## try:
|
||||||
|
## compiler.compile(buf, basename, "exec")
|
||||||
|
## except Exception, e:
|
||||||
|
## args = list(e.args)
|
||||||
|
## args[0] += "[in file %s]" % basename
|
||||||
|
## e.args = tuple(args)
|
||||||
|
## raise
|
||||||
|
|
||||||
if not basename.endswith(".py"):
|
path = "/home/jiwon/p3yk/Lib/test/test_keywordonlyarg.py"
|
||||||
continue
|
|
||||||
if not TEST_ALL and random() < 0.98:
|
|
||||||
continue
|
|
||||||
path = os.path.join(dir, basename)
|
|
||||||
if test.test_support.verbose:
|
if test.test_support.verbose:
|
||||||
print "compiling", path
|
print "compiling", path
|
||||||
f = open(path, "U")
|
f = open(path, "U")
|
||||||
buf = f.read()
|
buf = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
if "badsyntax" in basename or "bad_coding" in basename:
|
#try:
|
||||||
self.assertRaises(SyntaxError, compiler.compile,
|
compiler.compile(buf, "test_keywordonlyarg.py", "exec")
|
||||||
buf, basename, "exec")
|
#except Exception, e:
|
||||||
else:
|
# args = list(e.args)
|
||||||
try:
|
# args[0] += "[in file %s]" % path
|
||||||
compiler.compile(buf, basename, "exec")
|
# e.args = tuple(args)
|
||||||
except Exception, e:
|
# raise
|
||||||
args = list(e.args)
|
|
||||||
args[0] += "[in file %s]" % basename
|
|
||||||
e.args = tuple(args)
|
|
||||||
raise
|
|
||||||
|
|
||||||
def testNewClassSyntax(self):
|
def testNewClassSyntax(self):
|
||||||
compiler.compile("class foo():pass\n\n","<string>","exec")
|
compiler.compile("class foo():pass\n\n","<string>","exec")
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
# Test the frozen module defined in frozen.c.
|
# Test the frozen module defined in frozen.c.
|
||||||
|
# Currently test_frozen fails:
|
||||||
|
# Implementing pep3102(keyword only argument) needs changes in
|
||||||
|
# code object, which needs modification to marshal.
|
||||||
|
# However, to regenerate hard-coded marshal data in frozen.c,
|
||||||
|
# we need to run Tools/freeze/freeze.py, which currently doesn't work
|
||||||
|
# because Lib/modulefinder.py cannot handle relative module import
|
||||||
|
# This test will keep failing until Lib/modulefinder.py is fixed
|
||||||
|
|
||||||
from test.test_support import TestFailed
|
from test.test_support import TestFailed
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
|
@ -148,7 +148,8 @@ x = eval('1, 0 or 1')
|
||||||
print 'funcdef'
|
print 'funcdef'
|
||||||
### 'def' NAME parameters ':' suite
|
### 'def' NAME parameters ':' suite
|
||||||
### parameters: '(' [varargslist] ')'
|
### parameters: '(' [varargslist] ')'
|
||||||
### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME]
|
### varargslist: (fpdef ['=' test] ',')*
|
||||||
|
### ('*' (NAME|',' fpdef ['=' test]) [',' ('**'|'*' '*') NAME]
|
||||||
### | ('**'|'*' '*') NAME)
|
### | ('**'|'*' '*') NAME)
|
||||||
### | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
### | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||||
### fpdef: NAME | '(' fplist ')'
|
### fpdef: NAME | '(' fplist ')'
|
||||||
|
@ -265,6 +266,16 @@ def d31v((x)): pass
|
||||||
d31v(1)
|
d31v(1)
|
||||||
def d32v((x,)): pass
|
def d32v((x,)): pass
|
||||||
d32v((1,))
|
d32v((1,))
|
||||||
|
#keyword only argument tests
|
||||||
|
def pos0key1(*, key): return key
|
||||||
|
pos0key1(key=100)
|
||||||
|
def pos2key2(p1, p2, *, k1, k2=100): return p1,p2,k1,k2
|
||||||
|
pos2key2(1, 2, k1=100)
|
||||||
|
pos2key2(1, 2, k1=100, k2=200)
|
||||||
|
pos2key2(1, 2, k2=100, k1=200)
|
||||||
|
def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): return p1,p2,k1,k2,kwarg
|
||||||
|
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
|
||||||
|
pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
|
||||||
|
|
||||||
### lambdef: 'lambda' [varargslist] ':' test
|
### lambdef: 'lambda' [varargslist] ':' test
|
||||||
print 'lambdef'
|
print 'lambdef'
|
||||||
|
@ -279,6 +290,9 @@ l5 = lambda x, y, z=2: x + y + z
|
||||||
verify(l5(1, 2) == 5)
|
verify(l5(1, 2) == 5)
|
||||||
verify(l5(1, 2, 3) == 6)
|
verify(l5(1, 2, 3) == 6)
|
||||||
check_syntax("lambda x: x = 2")
|
check_syntax("lambda x: x = 2")
|
||||||
|
l6 = lambda x, y, *, k=20: x+y+k
|
||||||
|
verify(l6(1,2) == 1+2+20)
|
||||||
|
verify(l6(1,2,k=10) == 1+2+10)
|
||||||
|
|
||||||
### stmt: simple_stmt | compound_stmt
|
### stmt: simple_stmt | compound_stmt
|
||||||
# Tested below
|
# Tested below
|
||||||
|
|
|
@ -103,6 +103,7 @@ if hasattr(new, 'code'):
|
||||||
|
|
||||||
c = f.func_code
|
c = f.func_code
|
||||||
argcount = c.co_argcount
|
argcount = c.co_argcount
|
||||||
|
kwonlyargcount = c.co_kwonlyargcount
|
||||||
nlocals = c.co_nlocals
|
nlocals = c.co_nlocals
|
||||||
stacksize = c.co_stacksize
|
stacksize = c.co_stacksize
|
||||||
flags = c.co_flags
|
flags = c.co_flags
|
||||||
|
@ -117,17 +118,20 @@ if hasattr(new, 'code'):
|
||||||
freevars = c.co_freevars
|
freevars = c.co_freevars
|
||||||
cellvars = c.co_cellvars
|
cellvars = c.co_cellvars
|
||||||
|
|
||||||
d = new.code(argcount, nlocals, stacksize, flags, codestring,
|
d = new.code(argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags, codestring,
|
||||||
constants, names, varnames, filename, name,
|
constants, names, varnames, filename, name,
|
||||||
firstlineno, lnotab, freevars, cellvars)
|
firstlineno, lnotab, freevars, cellvars)
|
||||||
|
|
||||||
# test backwards-compatibility version with no freevars or cellvars
|
# test backwards-compatibility version with no freevars or cellvars
|
||||||
d = new.code(argcount, nlocals, stacksize, flags, codestring,
|
d = new.code(argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags, codestring,
|
||||||
constants, names, varnames, filename, name,
|
constants, names, varnames, filename, name,
|
||||||
firstlineno, lnotab)
|
firstlineno, lnotab)
|
||||||
|
|
||||||
try: # this used to trigger a SystemError
|
try: # this used to trigger a SystemError
|
||||||
d = new.code(-argcount, nlocals, stacksize, flags, codestring,
|
d = new.code(-argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags, codestring,
|
||||||
constants, names, varnames, filename, name,
|
constants, names, varnames, filename, name,
|
||||||
firstlineno, lnotab)
|
firstlineno, lnotab)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -136,7 +140,8 @@ if hasattr(new, 'code'):
|
||||||
raise TestFailed, "negative co_argcount didn't trigger an exception"
|
raise TestFailed, "negative co_argcount didn't trigger an exception"
|
||||||
|
|
||||||
try: # this used to trigger a SystemError
|
try: # this used to trigger a SystemError
|
||||||
d = new.code(argcount, -nlocals, stacksize, flags, codestring,
|
d = new.code(argcount, kwonlyargcount,
|
||||||
|
-nlocals, stacksize, flags, codestring,
|
||||||
constants, names, varnames, filename, name,
|
constants, names, varnames, filename, name,
|
||||||
firstlineno, lnotab)
|
firstlineno, lnotab)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -145,7 +150,8 @@ if hasattr(new, 'code'):
|
||||||
raise TestFailed, "negative co_nlocals didn't trigger an exception"
|
raise TestFailed, "negative co_nlocals didn't trigger an exception"
|
||||||
|
|
||||||
try: # this used to trigger a Py_FatalError!
|
try: # this used to trigger a Py_FatalError!
|
||||||
d = new.code(argcount, nlocals, stacksize, flags, codestring,
|
d = new.code(argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags, codestring,
|
||||||
constants, (5,), varnames, filename, name,
|
constants, (5,), varnames, filename, name,
|
||||||
firstlineno, lnotab)
|
firstlineno, lnotab)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -156,7 +162,8 @@ if hasattr(new, 'code'):
|
||||||
# new.code used to be a way to mutate a tuple...
|
# new.code used to be a way to mutate a tuple...
|
||||||
class S(str): pass
|
class S(str): pass
|
||||||
t = (S("ab"),)
|
t = (S("ab"),)
|
||||||
d = new.code(argcount, nlocals, stacksize, flags, codestring,
|
d = new.code(argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags, codestring,
|
||||||
constants, t, varnames, filename, name,
|
constants, t, varnames, filename, name,
|
||||||
firstlineno, lnotab)
|
firstlineno, lnotab)
|
||||||
verify(type(t[0]) is S, "eek, tuple changed under us!")
|
verify(type(t[0]) is S, "eek, tuple changed under us!")
|
||||||
|
|
|
@ -51,6 +51,7 @@ void _AddTraceback(char *funcname, char *filename, int lineno)
|
||||||
if (!empty_string) goto bad;
|
if (!empty_string) goto bad;
|
||||||
py_code = PyCode_New(
|
py_code = PyCode_New(
|
||||||
0, /*int argcount,*/
|
0, /*int argcount,*/
|
||||||
|
0, /*int kwonlyargcount,*/
|
||||||
0, /*int nlocals,*/
|
0, /*int nlocals,*/
|
||||||
0, /*int stacksize,*/
|
0, /*int stacksize,*/
|
||||||
0, /*int flags,*/
|
0, /*int flags,*/
|
||||||
|
|
|
@ -1105,13 +1105,13 @@ validate_testlist_safe(node *tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* '*' NAME [',' '**' NAME] | '**' NAME
|
/* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
validate_varargslist_trailer(node *tree, int start)
|
validate_varargslist_trailer(node *tree, int start)
|
||||||
{
|
{
|
||||||
int nch = NCH(tree);
|
int nch = NCH(tree);
|
||||||
int res = 0;
|
int res = 0, i;
|
||||||
int sym;
|
int sym;
|
||||||
|
|
||||||
if (nch <= start) {
|
if (nch <= start) {
|
||||||
|
@ -1121,15 +1121,40 @@ validate_varargslist_trailer(node *tree, int start)
|
||||||
sym = TYPE(CHILD(tree, start));
|
sym = TYPE(CHILD(tree, start));
|
||||||
if (sym == STAR) {
|
if (sym == STAR) {
|
||||||
/*
|
/*
|
||||||
* ('*' NAME [',' '**' NAME]
|
* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||||
*/
|
*/
|
||||||
if (nch-start == 2)
|
if (nch-start == 2)
|
||||||
res = validate_name(CHILD(tree, start+1), NULL);
|
res = validate_name(CHILD(tree, start+1), NULL);
|
||||||
else if (nch-start == 5)
|
else if (nch-start == 5 && TYPE(CHILD(tree, start+2)) == COMMA)
|
||||||
res = (validate_name(CHILD(tree, start+1), NULL)
|
res = (validate_name(CHILD(tree, start+1), NULL)
|
||||||
&& validate_comma(CHILD(tree, start+2))
|
&& validate_comma(CHILD(tree, start+2))
|
||||||
&& validate_doublestar(CHILD(tree, start+3))
|
&& validate_doublestar(CHILD(tree, start+3))
|
||||||
&& validate_name(CHILD(tree, start+4), NULL));
|
&& validate_name(CHILD(tree, start+4), NULL));
|
||||||
|
else {
|
||||||
|
/* skip over [NAME] (',' NAME ['=' test])* */
|
||||||
|
i = start + 1;
|
||||||
|
if (TYPE(CHILD(tree, i)) == NAME) { /* skip over [NAME] */
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
while (res && i+1 < nch) { /* validate (',' NAME ['=' test])* */
|
||||||
|
res = validate_comma(CHILD(tree, i));
|
||||||
|
if (TYPE(CHILD(tree, i+1)) == DOUBLESTAR)
|
||||||
|
break;
|
||||||
|
res = res && validate_name(CHILD(tree, i+1), NULL);
|
||||||
|
if (res && i+2 < nch && TYPE(CHILD(tree, i+2)) == EQUAL) {
|
||||||
|
res = res && (i+3 < nch)
|
||||||
|
&& validate_test(CHILD(tree, i+3));
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* [',' '**' NAME] */
|
||||||
|
if (res && i+1 < nch && TYPE(CHILD(tree, i+1)) == DOUBLESTAR) {
|
||||||
|
res = validate_name(CHILD(tree, i+2), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (sym == DOUBLESTAR) {
|
else if (sym == DOUBLESTAR) {
|
||||||
/*
|
/*
|
||||||
|
@ -1148,8 +1173,7 @@ validate_varargslist_trailer(node *tree, int start)
|
||||||
*
|
*
|
||||||
* varargslist:
|
* varargslist:
|
||||||
* (fpdef ['=' test] ',')*
|
* (fpdef ['=' test] ',')*
|
||||||
* ('*' NAME [',' '**' NAME]
|
* ('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||||
* | '**' NAME)
|
|
||||||
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -1169,7 +1193,7 @@ validate_varargslist(node *tree)
|
||||||
sym = TYPE(CHILD(tree, 0));
|
sym = TYPE(CHILD(tree, 0));
|
||||||
if (sym == STAR || sym == DOUBLESTAR)
|
if (sym == STAR || sym == DOUBLESTAR)
|
||||||
/* whole thing matches:
|
/* whole thing matches:
|
||||||
* '*' NAME [',' '**' NAME] | '**' NAME
|
* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||||
*/
|
*/
|
||||||
res = validate_varargslist_trailer(tree, 0);
|
res = validate_varargslist_trailer(tree, 0);
|
||||||
else if (sym == fpdef) {
|
else if (sym == fpdef) {
|
||||||
|
@ -1201,7 +1225,7 @@ validate_varargslist(node *tree)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ... '*' NAME [',' '**' NAME] | '**' NAME
|
/* .. ('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||||
* i --^^^
|
* i --^^^
|
||||||
*/
|
*/
|
||||||
if (res)
|
if (res)
|
||||||
|
|
|
@ -279,6 +279,7 @@ getcode(enum HandlerTypes slot, char* func_name, int lineno)
|
||||||
filename = PyString_FromString(__FILE__);
|
filename = PyString_FromString(__FILE__);
|
||||||
handler_info[slot].tb_code =
|
handler_info[slot].tb_code =
|
||||||
PyCode_New(0, /* argcount */
|
PyCode_New(0, /* argcount */
|
||||||
|
0, /* kwonlyargcount */
|
||||||
0, /* nlocals */
|
0, /* nlocals */
|
||||||
0, /* stacksize */
|
0, /* stacksize */
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
|
|
|
@ -41,7 +41,8 @@ intern_strings(PyObject *tuple)
|
||||||
|
|
||||||
|
|
||||||
PyCodeObject *
|
PyCodeObject *
|
||||||
PyCode_New(int argcount, int nlocals, int stacksize, int flags,
|
PyCode_New(int argcount, int kwonlyargcount,
|
||||||
|
int nlocals, int stacksize, int flags,
|
||||||
PyObject *code, PyObject *consts, PyObject *names,
|
PyObject *code, PyObject *consts, PyObject *names,
|
||||||
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
|
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
|
||||||
PyObject *filename, PyObject *name, int firstlineno,
|
PyObject *filename, PyObject *name, int firstlineno,
|
||||||
|
@ -80,6 +81,7 @@ PyCode_New(int argcount, int nlocals, int stacksize, int flags,
|
||||||
co = PyObject_NEW(PyCodeObject, &PyCode_Type);
|
co = PyObject_NEW(PyCodeObject, &PyCode_Type);
|
||||||
if (co != NULL) {
|
if (co != NULL) {
|
||||||
co->co_argcount = argcount;
|
co->co_argcount = argcount;
|
||||||
|
co->co_kwonlyargcount = kwonlyargcount;
|
||||||
co->co_nlocals = nlocals;
|
co->co_nlocals = nlocals;
|
||||||
co->co_stacksize = stacksize;
|
co->co_stacksize = stacksize;
|
||||||
co->co_flags = flags;
|
co->co_flags = flags;
|
||||||
|
@ -112,6 +114,7 @@ PyCode_New(int argcount, int nlocals, int stacksize, int flags,
|
||||||
|
|
||||||
static PyMemberDef code_memberlist[] = {
|
static PyMemberDef code_memberlist[] = {
|
||||||
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
||||||
|
{"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY},
|
||||||
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
||||||
{"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
|
{"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
|
||||||
{"co_flags", T_INT, OFF(co_flags), READONLY},
|
{"co_flags", T_INT, OFF(co_flags), READONLY},
|
||||||
|
@ -182,6 +185,7 @@ static PyObject *
|
||||||
code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||||
{
|
{
|
||||||
int argcount;
|
int argcount;
|
||||||
|
int kwonlyargcount;
|
||||||
int nlocals;
|
int nlocals;
|
||||||
int stacksize;
|
int stacksize;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -197,8 +201,9 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||||
int firstlineno;
|
int firstlineno;
|
||||||
PyObject *lnotab;
|
PyObject *lnotab;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
|
if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!SSiS|O!O!:code",
|
||||||
&argcount, &nlocals, &stacksize, &flags,
|
&argcount, &kwonlyargcount,
|
||||||
|
&nlocals, &stacksize, &flags,
|
||||||
&code,
|
&code,
|
||||||
&PyTuple_Type, &consts,
|
&PyTuple_Type, &consts,
|
||||||
&PyTuple_Type, &names,
|
&PyTuple_Type, &names,
|
||||||
|
@ -216,6 +221,12 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kwonlyargcount < 0) {
|
||||||
|
PyErr_SetString(
|
||||||
|
PyExc_ValueError,
|
||||||
|
"code: kwonlyargcount must not be negative");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
if (nlocals < 0) {
|
if (nlocals < 0) {
|
||||||
PyErr_SetString(
|
PyErr_SetString(
|
||||||
PyExc_ValueError,
|
PyExc_ValueError,
|
||||||
|
@ -242,7 +253,8 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||||
if (ourcellvars == NULL)
|
if (ourcellvars == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
|
co = (PyObject *)PyCode_New(argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags,
|
||||||
code, consts, ournames, ourvarnames,
|
code, consts, ournames, ourvarnames,
|
||||||
ourfreevars, ourcellvars, filename,
|
ourfreevars, ourcellvars, filename,
|
||||||
name, firstlineno, lnotab);
|
name, firstlineno, lnotab);
|
||||||
|
@ -312,6 +324,8 @@ code_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
if (eq <= 0) goto unequal;
|
if (eq <= 0) goto unequal;
|
||||||
eq = co->co_argcount == cp->co_argcount;
|
eq = co->co_argcount == cp->co_argcount;
|
||||||
if (!eq) goto unequal;
|
if (!eq) goto unequal;
|
||||||
|
eq = co->co_kwonlyargcount == cp->co_kwonlyargcount;
|
||||||
|
if (!eq) goto unequal;
|
||||||
eq = co->co_nlocals == cp->co_nlocals;
|
eq = co->co_nlocals == cp->co_nlocals;
|
||||||
if (!eq) goto unequal;
|
if (!eq) goto unequal;
|
||||||
eq = co->co_flags == cp->co_flags;
|
eq = co->co_flags == cp->co_flags;
|
||||||
|
@ -369,7 +383,8 @@ code_hash(PyCodeObject *co)
|
||||||
h6 = PyObject_Hash(co->co_cellvars);
|
h6 = PyObject_Hash(co->co_cellvars);
|
||||||
if (h6 == -1) return -1;
|
if (h6 == -1) return -1;
|
||||||
h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
|
h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
|
||||||
co->co_argcount ^ co->co_nlocals ^ co->co_flags;
|
co->co_argcount ^ co->co_kwonlyargcount ^
|
||||||
|
co->co_nlocals ^ co->co_flags;
|
||||||
if (h == -1) h = -2;
|
if (h == -1) h = -2;
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ PyFunction_New(PyObject *code, PyObject *globals)
|
||||||
op->func_name = ((PyCodeObject *)code)->co_name;
|
op->func_name = ((PyCodeObject *)code)->co_name;
|
||||||
Py_INCREF(op->func_name);
|
Py_INCREF(op->func_name);
|
||||||
op->func_defaults = NULL; /* No default arguments */
|
op->func_defaults = NULL; /* No default arguments */
|
||||||
|
op->func_kwdefaults = NULL; /* No keyword only defaults */
|
||||||
op->func_closure = NULL;
|
op->func_closure = NULL;
|
||||||
consts = ((PyCodeObject *)code)->co_consts;
|
consts = ((PyCodeObject *)code)->co_consts;
|
||||||
if (PyTuple_Size(consts) >= 1) {
|
if (PyTuple_Size(consts) >= 1) {
|
||||||
|
@ -121,6 +122,38 @@ PyFunction_SetDefaults(PyObject *op, PyObject *defaults)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyFunction_GetKwDefaults(PyObject *op)
|
||||||
|
{
|
||||||
|
if (!PyFunction_Check(op)) {
|
||||||
|
PyErr_BadInternalCall();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ((PyFunctionObject *) op) -> func_kwdefaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyFunction_SetKwDefaults(PyObject *op, PyObject *defaults)
|
||||||
|
{
|
||||||
|
if (!PyFunction_Check(op)) {
|
||||||
|
PyErr_BadInternalCall();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (defaults == Py_None)
|
||||||
|
defaults = NULL;
|
||||||
|
else if (defaults && PyDict_Check(defaults)) {
|
||||||
|
Py_INCREF(defaults);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
"non-dict keyword only default args");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_XDECREF(((PyFunctionObject *)op) -> func_kwdefaults);
|
||||||
|
((PyFunctionObject *) op) -> func_kwdefaults = defaults;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyFunction_GetClosure(PyObject *op)
|
PyFunction_GetClosure(PyObject *op)
|
||||||
{
|
{
|
||||||
|
@ -325,10 +358,49 @@ func_set_defaults(PyFunctionObject *op, PyObject *value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
func_get_kwdefaults(PyFunctionObject *op)
|
||||||
|
{
|
||||||
|
if (restricted())
|
||||||
|
return NULL;
|
||||||
|
if (op->func_kwdefaults == NULL) {
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
Py_INCREF(op->func_kwdefaults);
|
||||||
|
return op->func_kwdefaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
|
||||||
|
{
|
||||||
|
PyObject *tmp;
|
||||||
|
|
||||||
|
if (restricted())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (value == Py_None)
|
||||||
|
value = NULL;
|
||||||
|
/* Legal to del f.func_defaults.
|
||||||
|
* Can only set func_kwdefaults to NULL or a dict. */
|
||||||
|
if (value != NULL && !PyDict_Check(value)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"func_kwdefaults must be set to a dict object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmp = op->func_kwdefaults;
|
||||||
|
Py_XINCREF(value);
|
||||||
|
op->func_kwdefaults = value;
|
||||||
|
Py_XDECREF(tmp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyGetSetDef func_getsetlist[] = {
|
static PyGetSetDef func_getsetlist[] = {
|
||||||
{"func_code", (getter)func_get_code, (setter)func_set_code},
|
{"func_code", (getter)func_get_code, (setter)func_set_code},
|
||||||
{"func_defaults", (getter)func_get_defaults,
|
{"func_defaults", (getter)func_get_defaults,
|
||||||
(setter)func_set_defaults},
|
(setter)func_set_defaults},
|
||||||
|
{"func_kwdefaults", (getter)func_get_kwdefaults,
|
||||||
|
(setter)func_set_kwdefaults},
|
||||||
{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
|
{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
|
||||||
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
|
{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
|
||||||
{"func_name", (getter)func_get_name, (setter)func_set_name},
|
{"func_name", (getter)func_get_name, (setter)func_set_name},
|
||||||
|
@ -519,6 +591,7 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw)
|
||||||
PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
|
PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
|
||||||
&PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg),
|
&PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg),
|
||||||
k, nk, d, nd,
|
k, nk, d, nd,
|
||||||
|
PyFunction_GET_KW_DEFAULTS(func),
|
||||||
PyFunction_GET_CLOSURE(func));
|
PyFunction_GET_CLOSURE(func));
|
||||||
|
|
||||||
if (k != NULL)
|
if (k != NULL)
|
||||||
|
|
|
@ -100,8 +100,8 @@ module Python version "$Revision$"
|
||||||
excepthandler = (expr? type, expr? name, stmt* body, int lineno,
|
excepthandler = (expr? type, expr? name, stmt* body, int lineno,
|
||||||
int col_offset)
|
int col_offset)
|
||||||
|
|
||||||
arguments = (expr* args, identifier? vararg,
|
arguments = (expr* args, identifier? vararg, expr* kwonlyargs,
|
||||||
identifier? kwarg, expr* defaults)
|
identifier? kwarg, expr* defaults, expr* kw_defaults)
|
||||||
|
|
||||||
-- keyword arguments supplied to call
|
-- keyword arguments supplied to call
|
||||||
keyword = (identifier arg, expr value)
|
keyword = (identifier arg, expr value)
|
||||||
|
|
|
@ -333,8 +333,10 @@ static PyObject* ast2obj_arguments(void*);
|
||||||
static char *arguments_fields[]={
|
static char *arguments_fields[]={
|
||||||
"args",
|
"args",
|
||||||
"vararg",
|
"vararg",
|
||||||
|
"kwonlyargs",
|
||||||
"kwarg",
|
"kwarg",
|
||||||
"defaults",
|
"defaults",
|
||||||
|
"kw_defaults",
|
||||||
};
|
};
|
||||||
static PyTypeObject *keyword_type;
|
static PyTypeObject *keyword_type;
|
||||||
static PyObject* ast2obj_keyword(void*);
|
static PyObject* ast2obj_keyword(void*);
|
||||||
|
@ -708,7 +710,7 @@ static int init_types(void)
|
||||||
excepthandler_type = make_type("excepthandler", AST_type,
|
excepthandler_type = make_type("excepthandler", AST_type,
|
||||||
excepthandler_fields, 5);
|
excepthandler_fields, 5);
|
||||||
if (!excepthandler_type) return 0;
|
if (!excepthandler_type) return 0;
|
||||||
arguments_type = make_type("arguments", AST_type, arguments_fields, 4);
|
arguments_type = make_type("arguments", AST_type, arguments_fields, 6);
|
||||||
if (!arguments_type) return 0;
|
if (!arguments_type) return 0;
|
||||||
keyword_type = make_type("keyword", AST_type, keyword_fields, 2);
|
keyword_type = make_type("keyword", AST_type, keyword_fields, 2);
|
||||||
if (!keyword_type) return 0;
|
if (!keyword_type) return 0;
|
||||||
|
@ -1828,8 +1830,8 @@ excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments_ty
|
arguments_ty
|
||||||
arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq *
|
arguments(asdl_seq * args, identifier vararg, asdl_seq * kwonlyargs, identifier
|
||||||
defaults, PyArena *arena)
|
kwarg, asdl_seq * defaults, asdl_seq * kw_defaults, PyArena *arena)
|
||||||
{
|
{
|
||||||
arguments_ty p;
|
arguments_ty p;
|
||||||
p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p));
|
p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||||
|
@ -1839,8 +1841,10 @@ arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq *
|
||||||
}
|
}
|
||||||
p->args = args;
|
p->args = args;
|
||||||
p->vararg = vararg;
|
p->vararg = vararg;
|
||||||
|
p->kwonlyargs = kwonlyargs;
|
||||||
p->kwarg = kwarg;
|
p->kwarg = kwarg;
|
||||||
p->defaults = defaults;
|
p->defaults = defaults;
|
||||||
|
p->kw_defaults = kw_defaults;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2907,6 +2911,11 @@ ast2obj_arguments(void* _o)
|
||||||
if (PyObject_SetAttrString(result, "vararg", value) == -1)
|
if (PyObject_SetAttrString(result, "vararg", value) == -1)
|
||||||
goto failed;
|
goto failed;
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
|
value = ast2obj_list(o->kwonlyargs, ast2obj_expr);
|
||||||
|
if (!value) goto failed;
|
||||||
|
if (PyObject_SetAttrString(result, "kwonlyargs", value) == -1)
|
||||||
|
goto failed;
|
||||||
|
Py_DECREF(value);
|
||||||
value = ast2obj_identifier(o->kwarg);
|
value = ast2obj_identifier(o->kwarg);
|
||||||
if (!value) goto failed;
|
if (!value) goto failed;
|
||||||
if (PyObject_SetAttrString(result, "kwarg", value) == -1)
|
if (PyObject_SetAttrString(result, "kwarg", value) == -1)
|
||||||
|
@ -2917,6 +2926,11 @@ ast2obj_arguments(void* _o)
|
||||||
if (PyObject_SetAttrString(result, "defaults", value) == -1)
|
if (PyObject_SetAttrString(result, "defaults", value) == -1)
|
||||||
goto failed;
|
goto failed;
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
|
value = ast2obj_list(o->kw_defaults, ast2obj_expr);
|
||||||
|
if (!value) goto failed;
|
||||||
|
if (PyObject_SetAttrString(result, "kw_defaults", value) == -1)
|
||||||
|
goto failed;
|
||||||
|
Py_DECREF(value);
|
||||||
return result;
|
return result;
|
||||||
failed:
|
failed:
|
||||||
Py_XDECREF(value);
|
Py_XDECREF(value);
|
||||||
|
@ -2994,7 +3008,7 @@ init_ast(void)
|
||||||
if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return;
|
if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return;
|
||||||
if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)
|
if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)
|
||||||
return;
|
return;
|
||||||
if (PyModule_AddStringConstant(m, "__version__", "51631") < 0)
|
if (PyModule_AddStringConstant(m, "__version__", "51773") < 0)
|
||||||
return;
|
return;
|
||||||
if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return;
|
if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return;
|
||||||
if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0)
|
if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0)
|
||||||
|
|
159
Python/ast.c
159
Python/ast.c
|
@ -591,6 +591,63 @@ compiler_complex_args(struct compiling *c, const node *n)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns -1 if failed to handle keyword only arguments
|
||||||
|
returns new position to keep processing if successful
|
||||||
|
(',' NAME ['=' test])*
|
||||||
|
^^^
|
||||||
|
start pointing here
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
handle_keywordonly_args(struct compiling *c, const node *n, int start,
|
||||||
|
asdl_seq *kwonlyargs, asdl_seq *kwdefaults)
|
||||||
|
{
|
||||||
|
node *ch;
|
||||||
|
expr_ty name;
|
||||||
|
int i = start;
|
||||||
|
int j = 0; /* index for kwdefaults and kwonlyargs */
|
||||||
|
assert(kwonlyargs != NULL);
|
||||||
|
assert(kwdefaults != NULL);
|
||||||
|
while (i < NCH(n)) {
|
||||||
|
ch = CHILD(n, i);
|
||||||
|
switch (TYPE(ch)) {
|
||||||
|
case NAME:
|
||||||
|
if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
|
||||||
|
expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));
|
||||||
|
if (!expression) {
|
||||||
|
ast_error(ch, "assignment to None");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
asdl_seq_SET(kwdefaults, j, expression);
|
||||||
|
i += 2; /* '=' and test */
|
||||||
|
}
|
||||||
|
else { /* setting NULL if no default value exists */
|
||||||
|
asdl_seq_SET(kwdefaults, j, NULL);
|
||||||
|
}
|
||||||
|
if (!strcmp(STR(ch), "None")) {
|
||||||
|
ast_error(ch, "assignment to None");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
name = Name(NEW_IDENTIFIER(ch),
|
||||||
|
Param, LINENO(ch), ch->n_col_offset,
|
||||||
|
c->c_arena);
|
||||||
|
if (!name) {
|
||||||
|
ast_error(ch, "expecting name");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
asdl_seq_SET(kwonlyargs, j++, name);
|
||||||
|
i += 2; /* the name and the comma */
|
||||||
|
break;
|
||||||
|
case DOUBLESTAR:
|
||||||
|
return i;
|
||||||
|
default:
|
||||||
|
ast_error(ch, "unexpected node");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create AST for argument list. */
|
/* Create AST for argument list. */
|
||||||
|
|
||||||
|
@ -598,35 +655,71 @@ static arguments_ty
|
||||||
ast_for_arguments(struct compiling *c, const node *n)
|
ast_for_arguments(struct compiling *c, const node *n)
|
||||||
{
|
{
|
||||||
/* parameters: '(' [varargslist] ')'
|
/* parameters: '(' [varargslist] ')'
|
||||||
varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME]
|
varargslist: (fpdef ['=' test] ',')*
|
||||||
| '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
('*' [NAME] (',' fpdef ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||||
|
| fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||||
*/
|
*/
|
||||||
int i, j, k, n_args = 0, n_defaults = 0, found_default = 0;
|
int i, j, k, nposargs = 0, nkwonlyargs = 0;
|
||||||
asdl_seq *args, *defaults;
|
int nposdefaults = 0, found_default = 0;
|
||||||
|
asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults;
|
||||||
identifier vararg = NULL, kwarg = NULL;
|
identifier vararg = NULL, kwarg = NULL;
|
||||||
node *ch;
|
node *ch;
|
||||||
|
|
||||||
if (TYPE(n) == parameters) {
|
if (TYPE(n) == parameters) {
|
||||||
if (NCH(n) == 2) /* () as argument list */
|
if (NCH(n) == 2) /* () as argument list */
|
||||||
return arguments(NULL, NULL, NULL, NULL, c->c_arena);
|
return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||||
n = CHILD(n, 1);
|
n = CHILD(n, 1);
|
||||||
}
|
}
|
||||||
REQ(n, varargslist);
|
REQ(n, varargslist);
|
||||||
|
|
||||||
/* first count the number of normal args & defaults */
|
/* first count the number of positional args & defaults */
|
||||||
for (i = 0; i < NCH(n); i++) {
|
for (i = 0; i < NCH(n); i++) {
|
||||||
ch = CHILD(n, i);
|
ch = CHILD(n, i);
|
||||||
if (TYPE(ch) == fpdef)
|
if (TYPE(ch) == STAR) {
|
||||||
n_args++;
|
if (TYPE(CHILD(n, i+1)) == NAME) {
|
||||||
if (TYPE(ch) == EQUAL)
|
/* skip NAME of vararg */
|
||||||
n_defaults++;
|
/* so that following can count only keyword only args */
|
||||||
|
i += 2;
|
||||||
}
|
}
|
||||||
args = (n_args ? asdl_seq_new(n_args, c->c_arena) : NULL);
|
else {
|
||||||
if (!args && n_args)
|
i++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (TYPE(ch) == fpdef) nposargs++;
|
||||||
|
if (TYPE(ch) == EQUAL) nposdefaults++;
|
||||||
|
}
|
||||||
|
/* count the number of keyword only args &
|
||||||
|
defaults for keyword only args */
|
||||||
|
for ( ; i < NCH(n); ++i) {
|
||||||
|
ch = CHILD(n, i);
|
||||||
|
if (TYPE(ch) == DOUBLESTAR) break;
|
||||||
|
if (TYPE(ch) == NAME) nkwonlyargs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
posargs = (nposargs ? asdl_seq_new(nposargs, c->c_arena) : NULL);
|
||||||
|
if (!posargs && nposargs)
|
||||||
return NULL; /* Don't need to goto error; no objects allocated */
|
return NULL; /* Don't need to goto error; no objects allocated */
|
||||||
defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL);
|
kwonlyargs = (nkwonlyargs ?
|
||||||
if (!defaults && n_defaults)
|
asdl_seq_new(nkwonlyargs, c->c_arena) : NULL);
|
||||||
|
if (!kwonlyargs && nkwonlyargs)
|
||||||
return NULL; /* Don't need to goto error; no objects allocated */
|
return NULL; /* Don't need to goto error; no objects allocated */
|
||||||
|
posdefaults = (nposdefaults ?
|
||||||
|
asdl_seq_new(nposdefaults, c->c_arena) : NULL);
|
||||||
|
if (!posdefaults && nposdefaults)
|
||||||
|
return NULL; /* Don't need to goto error; no objects allocated */
|
||||||
|
/* The length of kwonlyargs and kwdefaults are same
|
||||||
|
since we set NULL as default for keyword only argument w/o default
|
||||||
|
- we have sequence data structure, but no dictionary */
|
||||||
|
kwdefaults = (nkwonlyargs ?
|
||||||
|
asdl_seq_new(nkwonlyargs, c->c_arena) : NULL);
|
||||||
|
if (!kwdefaults && nkwonlyargs)
|
||||||
|
return NULL; /* Don't need to goto error; no objects allocated */
|
||||||
|
|
||||||
|
if (nposargs + nkwonlyargs > 255) {
|
||||||
|
ast_error(n, "more than 255 arguments");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* fpdef: NAME | '(' fplist ')'
|
/* fpdef: NAME | '(' fplist ')'
|
||||||
fplist: fpdef (',' fpdef)* [',']
|
fplist: fpdef (',' fpdef)* [',']
|
||||||
|
@ -645,8 +738,9 @@ ast_for_arguments(struct compiling *c, const node *n)
|
||||||
expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));
|
expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));
|
||||||
if (!expression)
|
if (!expression)
|
||||||
goto error;
|
goto error;
|
||||||
assert(defaults != NULL);
|
assert(posdefaults != NULL);
|
||||||
asdl_seq_SET(defaults, j++, expression);
|
asdl_seq_SET(posdefaults, j++, expression);
|
||||||
|
|
||||||
i += 2;
|
i += 2;
|
||||||
found_default = 1;
|
found_default = 1;
|
||||||
}
|
}
|
||||||
|
@ -660,7 +754,8 @@ ast_for_arguments(struct compiling *c, const node *n)
|
||||||
/* def foo((x)): is not complex, special case. */
|
/* def foo((x)): is not complex, special case. */
|
||||||
if (NCH(ch) != 1) {
|
if (NCH(ch) != 1) {
|
||||||
/* We have complex arguments, setup for unpacking. */
|
/* We have complex arguments, setup for unpacking. */
|
||||||
asdl_seq_SET(args, k++, compiler_complex_args(c, ch));
|
asdl_seq_SET(posargs, k++,
|
||||||
|
compiler_complex_args(c, ch));
|
||||||
} else {
|
} else {
|
||||||
/* def foo((x)): setup for checking NAME below. */
|
/* def foo((x)): setup for checking NAME below. */
|
||||||
ch = CHILD(ch, 0);
|
ch = CHILD(ch, 0);
|
||||||
|
@ -677,18 +772,39 @@ ast_for_arguments(struct compiling *c, const node *n)
|
||||||
c->c_arena);
|
c->c_arena);
|
||||||
if (!name)
|
if (!name)
|
||||||
goto error;
|
goto error;
|
||||||
asdl_seq_SET(args, k++, name);
|
asdl_seq_SET(posargs, k++, name);
|
||||||
|
|
||||||
}
|
}
|
||||||
i += 2; /* the name and the comma */
|
i += 2; /* the name and the comma */
|
||||||
break;
|
break;
|
||||||
case STAR:
|
case STAR:
|
||||||
|
if (i+1 >= NCH(n)) {
|
||||||
|
ast_error(CHILD(n, i), "no name for vararg");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (!strcmp(STR(CHILD(n, i+1)), "None")) {
|
if (!strcmp(STR(CHILD(n, i+1)), "None")) {
|
||||||
ast_error(CHILD(n, i+1), "assignment to None");
|
ast_error(CHILD(n, i+1), "assignment to None");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (TYPE(CHILD(n, i+1)) == COMMA) {
|
||||||
|
int res = 0;
|
||||||
|
i += 2; /* now follows keyword only arguments */
|
||||||
|
res = handle_keywordonly_args(c, n, i,
|
||||||
|
kwonlyargs, kwdefaults);
|
||||||
|
if (res == -1) goto error;
|
||||||
|
i = res; /* res has new position to process */
|
||||||
|
}
|
||||||
|
else {
|
||||||
vararg = NEW_IDENTIFIER(CHILD(n, i+1));
|
vararg = NEW_IDENTIFIER(CHILD(n, i+1));
|
||||||
i += 3;
|
i += 3;
|
||||||
|
if (i < NCH(n) && TYPE(CHILD(n, i)) == NAME) {
|
||||||
|
int res = 0;
|
||||||
|
res = handle_keywordonly_args(c, n, i,
|
||||||
|
kwonlyargs, kwdefaults);
|
||||||
|
if (res == -1) goto error;
|
||||||
|
i = res; /* res has new position to process */
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DOUBLESTAR:
|
case DOUBLESTAR:
|
||||||
if (!strcmp(STR(CHILD(n, i+1)), "None")) {
|
if (!strcmp(STR(CHILD(n, i+1)), "None")) {
|
||||||
|
@ -705,9 +821,8 @@ ast_for_arguments(struct compiling *c, const node *n)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return arguments(posargs, vararg, kwonlyargs, kwarg,
|
||||||
return arguments(args, vararg, kwarg, defaults, c->c_arena);
|
posdefaults, kwdefaults, c->c_arena);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Py_XDECREF(vararg);
|
Py_XDECREF(vararg);
|
||||||
Py_XDECREF(kwarg);
|
Py_XDECREF(kwarg);
|
||||||
|
@ -851,7 +966,7 @@ ast_for_lambdef(struct compiling *c, const node *n)
|
||||||
expr_ty expression;
|
expr_ty expression;
|
||||||
|
|
||||||
if (NCH(n) == 3) {
|
if (NCH(n) == 3) {
|
||||||
args = arguments(NULL, NULL, NULL, NULL, c->c_arena);
|
args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||||
if (!args)
|
if (!args)
|
||||||
return NULL;
|
return NULL;
|
||||||
expression = ast_for_expr(c, CHILD(n, 2));
|
expression = ast_for_expr(c, CHILD(n, 2));
|
||||||
|
|
|
@ -494,7 +494,7 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
|
||||||
(PyObject **)NULL, 0,
|
(PyObject **)NULL, 0,
|
||||||
(PyObject **)NULL, 0,
|
(PyObject **)NULL, 0,
|
||||||
(PyObject **)NULL, 0,
|
(PyObject **)NULL, 0,
|
||||||
NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2290,26 +2290,46 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
}
|
}
|
||||||
|
|
||||||
case MAKE_FUNCTION:
|
case MAKE_FUNCTION:
|
||||||
|
{
|
||||||
|
int posdefaults = oparg & 0xff;
|
||||||
|
int kwdefaults = (oparg>>8) & 0xff;
|
||||||
|
|
||||||
v = POP(); /* code object */
|
v = POP(); /* code object */
|
||||||
x = PyFunction_New(v, f->f_globals);
|
x = PyFunction_New(v, f->f_globals);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
/* XXX Maybe this should be a separate opcode? */
|
/* XXX Maybe this should be a separate opcode? */
|
||||||
if (x != NULL && oparg > 0) {
|
if (x != NULL && posdefaults > 0) {
|
||||||
v = PyTuple_New(oparg);
|
v = PyTuple_New(posdefaults);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
Py_DECREF(x);
|
Py_DECREF(x);
|
||||||
x = NULL;
|
x = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (--oparg >= 0) {
|
while (--posdefaults >= 0) {
|
||||||
w = POP();
|
w = POP();
|
||||||
PyTuple_SET_ITEM(v, oparg, w);
|
PyTuple_SET_ITEM(v, posdefaults, w);
|
||||||
}
|
}
|
||||||
err = PyFunction_SetDefaults(x, v);
|
err = PyFunction_SetDefaults(x, v);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
}
|
}
|
||||||
|
if (x != NULL && kwdefaults > 0) {
|
||||||
|
v = PyDict_New();
|
||||||
|
if (v == NULL) {
|
||||||
|
Py_DECREF(x);
|
||||||
|
x = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (--kwdefaults >= 0) {
|
||||||
|
w = POP(); /* default value */
|
||||||
|
u = POP(); /* kw only arg name */
|
||||||
|
PyDict_SetItem(v, u, w);
|
||||||
|
}
|
||||||
|
err = PyFunction_SetKwDefaults(x, v);
|
||||||
|
Py_DECREF(v);
|
||||||
|
}
|
||||||
PUSH(x);
|
PUSH(x);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MAKE_CLOSURE:
|
case MAKE_CLOSURE:
|
||||||
{
|
{
|
||||||
|
@ -2577,7 +2597,7 @@ fast_yield:
|
||||||
PyObject *
|
PyObject *
|
||||||
PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
PyObject **args, int argcount, PyObject **kws, int kwcount,
|
PyObject **args, int argcount, PyObject **kws, int kwcount,
|
||||||
PyObject **defs, int defcount, PyObject *closure)
|
PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
|
||||||
{
|
{
|
||||||
register PyFrameObject *f;
|
register PyFrameObject *f;
|
||||||
register PyObject *retval = NULL;
|
register PyObject *retval = NULL;
|
||||||
|
@ -2601,6 +2621,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
freevars = f->f_localsplus + co->co_nlocals;
|
freevars = f->f_localsplus + co->co_nlocals;
|
||||||
|
|
||||||
if (co->co_argcount > 0 ||
|
if (co->co_argcount > 0 ||
|
||||||
|
co->co_kwonlyargcount > 0 ||
|
||||||
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
|
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
|
||||||
int i;
|
int i;
|
||||||
int n = argcount;
|
int n = argcount;
|
||||||
|
@ -2609,7 +2630,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
kwdict = PyDict_New();
|
kwdict = PyDict_New();
|
||||||
if (kwdict == NULL)
|
if (kwdict == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
i = co->co_argcount;
|
i = co->co_argcount + co->co_kwonlyargcount;
|
||||||
if (co->co_flags & CO_VARARGS)
|
if (co->co_flags & CO_VARARGS)
|
||||||
i++;
|
i++;
|
||||||
SETLOCAL(i, kwdict);
|
SETLOCAL(i, kwdict);
|
||||||
|
@ -2618,7 +2639,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
if (!(co->co_flags & CO_VARARGS)) {
|
if (!(co->co_flags & CO_VARARGS)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.200s() takes %s %d "
|
"%.200s() takes %s %d "
|
||||||
"%sargument%s (%d given)",
|
"%spositional argument%s (%d given)",
|
||||||
PyString_AsString(co->co_name),
|
PyString_AsString(co->co_name),
|
||||||
defcount ? "at most" : "exactly",
|
defcount ? "at most" : "exactly",
|
||||||
co->co_argcount,
|
co->co_argcount,
|
||||||
|
@ -2638,7 +2659,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
u = PyTuple_New(argcount - n);
|
u = PyTuple_New(argcount - n);
|
||||||
if (u == NULL)
|
if (u == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
SETLOCAL(co->co_argcount, u);
|
SETLOCAL(co->co_argcount + co->co_kwonlyargcount, u);
|
||||||
for (i = n; i < argcount; i++) {
|
for (i = n; i < argcount; i++) {
|
||||||
x = args[i];
|
x = args[i];
|
||||||
Py_INCREF(x);
|
Py_INCREF(x);
|
||||||
|
@ -2656,7 +2677,9 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* XXX slow -- speed up using dictionary? */
|
/* XXX slow -- speed up using dictionary? */
|
||||||
for (j = 0; j < co->co_argcount; j++) {
|
for (j = 0;
|
||||||
|
j < co->co_argcount + co->co_kwonlyargcount;
|
||||||
|
j++) {
|
||||||
PyObject *nm = PyTuple_GET_ITEM(
|
PyObject *nm = PyTuple_GET_ITEM(
|
||||||
co->co_varnames, j);
|
co->co_varnames, j);
|
||||||
int cmp = PyObject_RichCompareBool(
|
int cmp = PyObject_RichCompareBool(
|
||||||
|
@ -2669,7 +2692,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
/* Check errors from Compare */
|
/* Check errors from Compare */
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
goto fail;
|
goto fail;
|
||||||
if (j >= co->co_argcount) {
|
if (j >= co->co_argcount + co->co_kwonlyargcount) {
|
||||||
if (kwdict == NULL) {
|
if (kwdict == NULL) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.200s() got an unexpected "
|
"%.200s() got an unexpected "
|
||||||
|
@ -2694,13 +2717,38 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
SETLOCAL(j, value);
|
SETLOCAL(j, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (co->co_kwonlyargcount > 0) {
|
||||||
|
for (i = co->co_argcount;
|
||||||
|
i < co->co_argcount + co->co_kwonlyargcount;
|
||||||
|
i++) {
|
||||||
|
if (GETLOCAL(i) != NULL)
|
||||||
|
continue;
|
||||||
|
PyObject *name =
|
||||||
|
PyTuple_GET_ITEM(co->co_varnames, i);
|
||||||
|
PyObject *def = NULL;
|
||||||
|
if (kwdefs != NULL)
|
||||||
|
def = PyDict_GetItem(kwdefs, name);
|
||||||
|
if (def != NULL) {
|
||||||
|
Py_INCREF(def);
|
||||||
|
SETLOCAL(i, def);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%.200s() needs "
|
||||||
|
"keyword only argument %s",
|
||||||
|
PyString_AsString(co->co_name),
|
||||||
|
PyString_AsString(name));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (argcount < co->co_argcount) {
|
if (argcount < co->co_argcount) {
|
||||||
int m = co->co_argcount - defcount;
|
int m = co->co_argcount - defcount;
|
||||||
for (i = argcount; i < m; i++) {
|
for (i = argcount; i < m; i++) {
|
||||||
if (GETLOCAL(i) == NULL) {
|
if (GETLOCAL(i) == NULL) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.200s() takes %s %d "
|
"%.200s() takes %s %d "
|
||||||
"%sargument%s (%d given)",
|
"%spositional argument%s "
|
||||||
|
"(%d given)",
|
||||||
PyString_AsString(co->co_name),
|
PyString_AsString(co->co_name),
|
||||||
((co->co_flags & CO_VARARGS) ||
|
((co->co_flags & CO_VARARGS) ||
|
||||||
defcount) ? "at least"
|
defcount) ? "at least"
|
||||||
|
@ -3565,12 +3613,14 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
|
||||||
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
|
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
|
||||||
PyObject *globals = PyFunction_GET_GLOBALS(func);
|
PyObject *globals = PyFunction_GET_GLOBALS(func);
|
||||||
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
|
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
|
||||||
|
PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
|
||||||
PyObject **d = NULL;
|
PyObject **d = NULL;
|
||||||
int nd = 0;
|
int nd = 0;
|
||||||
|
|
||||||
PCALL(PCALL_FUNCTION);
|
PCALL(PCALL_FUNCTION);
|
||||||
PCALL(PCALL_FAST_FUNCTION);
|
PCALL(PCALL_FAST_FUNCTION);
|
||||||
if (argdefs == NULL && co->co_argcount == n && nk==0 &&
|
if (argdefs == NULL && co->co_argcount == n &&
|
||||||
|
co->co_kwonlyargcount == 0 && nk==0 &&
|
||||||
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
|
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
|
||||||
PyFrameObject *f;
|
PyFrameObject *f;
|
||||||
PyObject *retval = NULL;
|
PyObject *retval = NULL;
|
||||||
|
@ -3608,7 +3658,7 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
|
||||||
}
|
}
|
||||||
return PyEval_EvalCodeEx(co, globals,
|
return PyEval_EvalCodeEx(co, globals,
|
||||||
(PyObject *)NULL, (*pp_stack)-n, na,
|
(PyObject *)NULL, (*pp_stack)-n, na,
|
||||||
(*pp_stack)-2*nk, nk, d, nd,
|
(*pp_stack)-2*nk, nk, d, nd, kwdefs,
|
||||||
PyFunction_GET_CLOSURE(func));
|
PyFunction_GET_CLOSURE(func));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ struct compiler_unit {
|
||||||
PyObject *u_private; /* for private name mangling */
|
PyObject *u_private; /* for private name mangling */
|
||||||
|
|
||||||
int u_argcount; /* number of arguments for block */
|
int u_argcount; /* number of arguments for block */
|
||||||
|
int u_kwonlyargcount; /* number of keyword only arguments for block */
|
||||||
/* Pointer to the most recently allocated block. By following b_list
|
/* Pointer to the most recently allocated block. By following b_list
|
||||||
members, you can reach all early allocated blocks. */
|
members, you can reach all early allocated blocks. */
|
||||||
basicblock *u_blocks;
|
basicblock *u_blocks;
|
||||||
|
@ -494,6 +495,7 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key,
|
||||||
}
|
}
|
||||||
memset(u, 0, sizeof(struct compiler_unit));
|
memset(u, 0, sizeof(struct compiler_unit));
|
||||||
u->u_argcount = 0;
|
u->u_argcount = 0;
|
||||||
|
u->u_kwonlyargcount = 0;
|
||||||
u->u_ste = PySymtable_Lookup(c->c_st, key);
|
u->u_ste = PySymtable_Lookup(c->c_st, key);
|
||||||
if (!u->u_ste) {
|
if (!u->u_ste) {
|
||||||
compiler_unit_free(u);
|
compiler_unit_free(u);
|
||||||
|
@ -896,9 +898,9 @@ opcode_stack_effect(int opcode, int oparg)
|
||||||
return -NARGS(oparg)-1;
|
return -NARGS(oparg)-1;
|
||||||
case CALL_FUNCTION_VAR_KW:
|
case CALL_FUNCTION_VAR_KW:
|
||||||
return -NARGS(oparg)-2;
|
return -NARGS(oparg)-2;
|
||||||
#undef NARGS
|
|
||||||
case MAKE_FUNCTION:
|
case MAKE_FUNCTION:
|
||||||
return -oparg;
|
return -NARGS(oparg);
|
||||||
|
#undef NARGS
|
||||||
case BUILD_SLICE:
|
case BUILD_SLICE:
|
||||||
if (oparg == 3)
|
if (oparg == 3)
|
||||||
return -2;
|
return -2;
|
||||||
|
@ -1346,6 +1348,25 @@ compiler_arguments(struct compiler *c, arguments_ty args)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs,
|
||||||
|
asdl_seq *kw_defaults)
|
||||||
|
{
|
||||||
|
int i, default_count = 0;
|
||||||
|
for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
|
||||||
|
expr_ty arg = asdl_seq_GET(kwonlyargs, i);
|
||||||
|
expr_ty default_ = asdl_seq_GET(kw_defaults, i);
|
||||||
|
if (default_) {
|
||||||
|
ADDOP_O(c, LOAD_CONST, arg->v.Name.id, consts);
|
||||||
|
if (!compiler_visit_expr(c, default_)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
default_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default_count;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_function(struct compiler *c, stmt_ty s)
|
compiler_function(struct compiler *c, stmt_ty s)
|
||||||
{
|
{
|
||||||
|
@ -1354,14 +1375,22 @@ compiler_function(struct compiler *c, stmt_ty s)
|
||||||
arguments_ty args = s->v.FunctionDef.args;
|
arguments_ty args = s->v.FunctionDef.args;
|
||||||
asdl_seq* decos = s->v.FunctionDef.decorators;
|
asdl_seq* decos = s->v.FunctionDef.decorators;
|
||||||
stmt_ty st;
|
stmt_ty st;
|
||||||
int i, n, docstring;
|
int i, n, docstring, kw_default_count = 0, arglength;
|
||||||
|
|
||||||
assert(s->kind == FunctionDef_kind);
|
assert(s->kind == FunctionDef_kind);
|
||||||
|
|
||||||
if (!compiler_decorators(c, decos))
|
if (!compiler_decorators(c, decos))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (args->kwonlyargs) {
|
||||||
|
int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs,
|
||||||
|
args->kw_defaults);
|
||||||
|
if (res < 0)
|
||||||
|
return 0;
|
||||||
|
kw_default_count = res;
|
||||||
|
}
|
||||||
if (args->defaults)
|
if (args->defaults)
|
||||||
VISIT_SEQ(c, expr, args->defaults);
|
VISIT_SEQ(c, expr, args->defaults);
|
||||||
|
|
||||||
if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s,
|
if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s,
|
||||||
s->lineno))
|
s->lineno))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1379,6 +1408,7 @@ compiler_function(struct compiler *c, stmt_ty s)
|
||||||
compiler_arguments(c, args);
|
compiler_arguments(c, args);
|
||||||
|
|
||||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||||
|
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||||
n = asdl_seq_LEN(s->v.FunctionDef.body);
|
n = asdl_seq_LEN(s->v.FunctionDef.body);
|
||||||
/* if there was a docstring, we need to skip the first statement */
|
/* if there was a docstring, we need to skip the first statement */
|
||||||
for (i = docstring; i < n; i++) {
|
for (i = docstring; i < n; i++) {
|
||||||
|
@ -1390,7 +1420,9 @@ compiler_function(struct compiler *c, stmt_ty s)
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));
|
arglength = asdl_seq_LEN(args->defaults);
|
||||||
|
arglength |= kw_default_count << 8;
|
||||||
|
compiler_make_closure(c, co, arglength);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
for (i = 0; i < asdl_seq_LEN(decos); i++) {
|
for (i = 0; i < asdl_seq_LEN(decos); i++) {
|
||||||
|
@ -1485,6 +1517,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
{
|
{
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
static identifier name;
|
static identifier name;
|
||||||
|
int kw_default_count = 0, arglength;
|
||||||
arguments_ty args = e->v.Lambda.args;
|
arguments_ty args = e->v.Lambda.args;
|
||||||
assert(e->kind == Lambda_kind);
|
assert(e->kind == Lambda_kind);
|
||||||
|
|
||||||
|
@ -1494,6 +1527,12 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args->kwonlyargs) {
|
||||||
|
int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs,
|
||||||
|
args->kw_defaults);
|
||||||
|
if (res < 0) return 0;
|
||||||
|
kw_default_count = res;
|
||||||
|
}
|
||||||
if (args->defaults)
|
if (args->defaults)
|
||||||
VISIT_SEQ(c, expr, args->defaults);
|
VISIT_SEQ(c, expr, args->defaults);
|
||||||
if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
|
if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
|
||||||
|
@ -1503,6 +1542,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
compiler_arguments(c, args);
|
compiler_arguments(c, args);
|
||||||
|
|
||||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||||
|
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||||
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
|
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
|
||||||
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
|
@ -1510,7 +1550,9 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));
|
arglength = asdl_seq_LEN(args->defaults);
|
||||||
|
arglength |= kw_default_count << 8;
|
||||||
|
compiler_make_closure(c, co, arglength);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -3791,7 +3833,8 @@ makecode(struct compiler *c, struct assembler *a)
|
||||||
Py_DECREF(consts);
|
Py_DECREF(consts);
|
||||||
consts = tmp;
|
consts = tmp;
|
||||||
|
|
||||||
co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c), flags,
|
co = PyCode_New(c->u->u_argcount, c->u->u_kwonlyargcount,
|
||||||
|
nlocals, stackdepth(c), flags,
|
||||||
bytecode, consts, names, varnames,
|
bytecode, consts, names, varnames,
|
||||||
freevars, cellvars,
|
freevars, cellvars,
|
||||||
filename, c->u->u_name,
|
filename, c->u->u_name,
|
||||||
|
|
|
@ -146,14 +146,16 @@ static arc arcs_7_1[3] = {
|
||||||
{27, 5},
|
{27, 5},
|
||||||
{0, 1},
|
{0, 1},
|
||||||
};
|
};
|
||||||
static arc arcs_7_2[1] = {
|
static arc arcs_7_2[3] = {
|
||||||
{19, 6},
|
{19, 6},
|
||||||
|
{27, 7},
|
||||||
|
{0, 2},
|
||||||
};
|
};
|
||||||
static arc arcs_7_3[1] = {
|
static arc arcs_7_3[1] = {
|
||||||
{19, 7},
|
{19, 8},
|
||||||
};
|
};
|
||||||
static arc arcs_7_4[1] = {
|
static arc arcs_7_4[1] = {
|
||||||
{26, 8},
|
{26, 9},
|
||||||
};
|
};
|
||||||
static arc arcs_7_5[4] = {
|
static arc arcs_7_5[4] = {
|
||||||
{24, 1},
|
{24, 1},
|
||||||
|
@ -162,30 +164,41 @@ static arc arcs_7_5[4] = {
|
||||||
{0, 5},
|
{0, 5},
|
||||||
};
|
};
|
||||||
static arc arcs_7_6[2] = {
|
static arc arcs_7_6[2] = {
|
||||||
{27, 9},
|
{27, 7},
|
||||||
{0, 6},
|
{0, 6},
|
||||||
};
|
};
|
||||||
static arc arcs_7_7[1] = {
|
static arc arcs_7_7[2] = {
|
||||||
{0, 7},
|
{19, 10},
|
||||||
};
|
|
||||||
static arc arcs_7_8[2] = {
|
|
||||||
{27, 5},
|
|
||||||
{0, 8},
|
|
||||||
};
|
|
||||||
static arc arcs_7_9[1] = {
|
|
||||||
{29, 3},
|
{29, 3},
|
||||||
};
|
};
|
||||||
static state states_7[10] = {
|
static arc arcs_7_8[1] = {
|
||||||
|
{0, 8},
|
||||||
|
};
|
||||||
|
static arc arcs_7_9[2] = {
|
||||||
|
{27, 5},
|
||||||
|
{0, 9},
|
||||||
|
};
|
||||||
|
static arc arcs_7_10[3] = {
|
||||||
|
{27, 7},
|
||||||
|
{25, 11},
|
||||||
|
{0, 10},
|
||||||
|
};
|
||||||
|
static arc arcs_7_11[1] = {
|
||||||
|
{26, 6},
|
||||||
|
};
|
||||||
|
static state states_7[12] = {
|
||||||
{3, arcs_7_0},
|
{3, arcs_7_0},
|
||||||
{3, arcs_7_1},
|
{3, arcs_7_1},
|
||||||
{1, arcs_7_2},
|
{3, arcs_7_2},
|
||||||
{1, arcs_7_3},
|
{1, arcs_7_3},
|
||||||
{1, arcs_7_4},
|
{1, arcs_7_4},
|
||||||
{4, arcs_7_5},
|
{4, arcs_7_5},
|
||||||
{2, arcs_7_6},
|
{2, arcs_7_6},
|
||||||
{1, arcs_7_7},
|
{2, arcs_7_7},
|
||||||
{2, arcs_7_8},
|
{1, arcs_7_8},
|
||||||
{1, arcs_7_9},
|
{2, arcs_7_9},
|
||||||
|
{3, arcs_7_10},
|
||||||
|
{1, arcs_7_11},
|
||||||
};
|
};
|
||||||
static arc arcs_8_0[2] = {
|
static arc arcs_8_0[2] = {
|
||||||
{19, 1},
|
{19, 1},
|
||||||
|
@ -1766,7 +1779,7 @@ static dfa dfas[83] = {
|
||||||
"\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
"\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||||
{262, "parameters", 0, 4, states_6,
|
{262, "parameters", 0, 4, states_6,
|
||||||
"\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
"\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||||
{263, "varargslist", 0, 10, states_7,
|
{263, "varargslist", 0, 12, states_7,
|
||||||
"\000\040\010\060\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
"\000\040\010\060\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||||
{264, "fpdef", 0, 4, states_8,
|
{264, "fpdef", 0, 4, states_8,
|
||||||
"\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
"\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
|
||||||
|
|
|
@ -67,9 +67,10 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
|
||||||
Python 3000: 3000
|
Python 3000: 3000
|
||||||
3010 (removed UNARY_CONVERT)
|
3010 (removed UNARY_CONVERT)
|
||||||
3020 (added BUILD_SET)
|
3020 (added BUILD_SET)
|
||||||
|
3030 (added keyword-only parameters)
|
||||||
.
|
.
|
||||||
*/
|
*/
|
||||||
#define MAGIC (3020 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
#define MAGIC (3030 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||||
|
|
||||||
/* Magic word as global; note that _PyImport_Init() can change the
|
/* Magic word as global; note that _PyImport_Init() can change the
|
||||||
value of this global to accommodate for alterations of how the
|
value of this global to accommodate for alterations of how the
|
||||||
|
|
|
@ -349,6 +349,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
PyCodeObject *co = (PyCodeObject *)v;
|
PyCodeObject *co = (PyCodeObject *)v;
|
||||||
w_byte(TYPE_CODE, p);
|
w_byte(TYPE_CODE, p);
|
||||||
w_long(co->co_argcount, p);
|
w_long(co->co_argcount, p);
|
||||||
|
w_long(co->co_kwonlyargcount, p);
|
||||||
w_long(co->co_nlocals, p);
|
w_long(co->co_nlocals, p);
|
||||||
w_long(co->co_stacksize, p);
|
w_long(co->co_stacksize, p);
|
||||||
w_long(co->co_flags, p);
|
w_long(co->co_flags, p);
|
||||||
|
@ -815,6 +816,7 @@ r_object(RFILE *p)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int argcount;
|
int argcount;
|
||||||
|
int kwonlyargcount;
|
||||||
int nlocals;
|
int nlocals;
|
||||||
int stacksize;
|
int stacksize;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -832,6 +834,7 @@ r_object(RFILE *p)
|
||||||
v = NULL;
|
v = NULL;
|
||||||
|
|
||||||
argcount = r_long(p);
|
argcount = r_long(p);
|
||||||
|
kwonlyargcount = r_long(p);
|
||||||
nlocals = r_long(p);
|
nlocals = r_long(p);
|
||||||
stacksize = r_long(p);
|
stacksize = r_long(p);
|
||||||
flags = r_long(p);
|
flags = r_long(p);
|
||||||
|
@ -865,7 +868,8 @@ r_object(RFILE *p)
|
||||||
goto code_error;
|
goto code_error;
|
||||||
|
|
||||||
v = (PyObject *) PyCode_New(
|
v = (PyObject *) PyCode_New(
|
||||||
argcount, nlocals, stacksize, flags,
|
argcount, kwonlyargcount,
|
||||||
|
nlocals, stacksize, flags,
|
||||||
code, consts, names, varnames,
|
code, consts, names, varnames,
|
||||||
freevars, cellvars, filename, name,
|
freevars, cellvars, filename, name,
|
||||||
firstlineno, lnotab);
|
firstlineno, lnotab);
|
||||||
|
|
|
@ -893,6 +893,17 @@ error:
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VISIT_KWONLYDEFAULTS(ST, KW_DEFAULTS) { \
|
||||||
|
int i = 0; \
|
||||||
|
asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \
|
||||||
|
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
|
||||||
|
expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \
|
||||||
|
if (!elt) continue; /* can be NULL */ \
|
||||||
|
if (!symtable_visit_expr((ST), elt)) \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
symtable_new_tmpname(struct symtable *st)
|
symtable_new_tmpname(struct symtable *st)
|
||||||
{
|
{
|
||||||
|
@ -910,6 +921,8 @@ symtable_new_tmpname(struct symtable *st)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
{
|
{
|
||||||
|
@ -919,6 +932,9 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
if (s->v.FunctionDef.args->defaults)
|
if (s->v.FunctionDef.args->defaults)
|
||||||
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
|
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
|
||||||
|
if (s->v.FunctionDef.args->kw_defaults)
|
||||||
|
VISIT_KWONLYDEFAULTS(st,
|
||||||
|
s->v.FunctionDef.args->kw_defaults);
|
||||||
if (s->v.FunctionDef.decorators)
|
if (s->v.FunctionDef.decorators)
|
||||||
VISIT_SEQ(st, expr, s->v.FunctionDef.decorators);
|
VISIT_SEQ(st, expr, s->v.FunctionDef.decorators);
|
||||||
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
||||||
|
@ -1262,6 +1278,8 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a)
|
||||||
*/
|
*/
|
||||||
if (a->args && !symtable_visit_params(st, a->args, 1))
|
if (a->args && !symtable_visit_params(st, a->args, 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1))
|
||||||
|
return 0;
|
||||||
if (a->vararg) {
|
if (a->vararg) {
|
||||||
if (!symtable_add_def(st, a->vararg, DEF_PARAM))
|
if (!symtable_add_def(st, a->vararg, DEF_PARAM))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
Module: doc*, node
|
Module: doc*, node
|
||||||
Stmt: nodes!
|
Stmt: nodes!
|
||||||
Decorators: nodes!
|
Decorators: nodes!
|
||||||
Function: decorators&, name*, argnames*, defaults!, flags*, doc*, code
|
Function: decorators&, name*, argnames*, defaults!, kwonlyargs*, flags*, doc*, code
|
||||||
Lambda: argnames*, defaults!, flags*, code
|
Lambda: argnames*, defaults!, kwonlyargs*, flags*, code
|
||||||
Class: name*, bases!, doc*, code
|
Class: name*, bases!, doc*, code
|
||||||
Pass:
|
Pass:
|
||||||
Break:
|
Break:
|
||||||
|
@ -97,6 +97,7 @@ init(Lambda):
|
||||||
init(GenExpr):
|
init(GenExpr):
|
||||||
self.argnames = ['.0']
|
self.argnames = ['.0']
|
||||||
self.varargs = self.kwargs = None
|
self.varargs = self.kwargs = None
|
||||||
|
self.kwonlyargs = ()
|
||||||
|
|
||||||
init(GenExprFor):
|
init(GenExprFor):
|
||||||
self.is_outmost = False
|
self.is_outmost = False
|
||||||
|
|
Loading…
Reference in New Issue