PEP 3107 - Function Annotations thanks to Tony Lownds
This commit is contained in:
parent
f6657e67b3
commit
c150536b5e
|
@ -21,13 +21,20 @@ eval_input: testlist NEWLINE* ENDMARKER
|
|||
|
||||
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
|
||||
decorators: decorator+
|
||||
funcdef: [decorators] 'def' NAME parameters ':' suite
|
||||
parameters: '(' [varargslist] ')'
|
||||
varargslist: ((fpdef ['=' test] ',')*
|
||||
('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME) |
|
||||
fpdef ['=' test] (',' fpdef ['=' test])* [','])
|
||||
fpdef: NAME | '(' fplist ')'
|
||||
fplist: fpdef (',' fpdef)* [',']
|
||||
funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite
|
||||
parameters: '(' [typedargslist] ')'
|
||||
typedargslist: ((tfpdef ['=' test] ',')*
|
||||
('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname)
|
||||
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
tname: NAME [':' test]
|
||||
tfpdef: tname | '(' tfplist ')'
|
||||
tfplist: tfpdef (',' tfpdef)* [',']
|
||||
varargslist: ((vfpdef ['=' test] ',')*
|
||||
('*' [vname] (',' vname ['=' test])* [',' '**' vname] | '**' vname)
|
||||
| vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
|
||||
vname: NAME
|
||||
vfpdef: vname | '(' vfplist ')'
|
||||
vfplist: vfpdef (',' vfpdef)* [',']
|
||||
|
||||
stmt: simple_stmt | compound_stmt
|
||||
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
|
||||
|
|
|
@ -30,6 +30,8 @@ typedef struct _excepthandler *excepthandler_ty;
|
|||
|
||||
typedef struct _arguments *arguments_ty;
|
||||
|
||||
typedef struct _arg *arg_ty;
|
||||
|
||||
typedef struct _keyword *keyword_ty;
|
||||
|
||||
typedef struct _alias *alias_ty;
|
||||
|
@ -74,6 +76,7 @@ struct _stmt {
|
|||
arguments_ty args;
|
||||
asdl_seq *body;
|
||||
asdl_seq *decorators;
|
||||
expr_ty returns;
|
||||
} FunctionDef;
|
||||
|
||||
struct {
|
||||
|
@ -328,12 +331,30 @@ struct _excepthandler {
|
|||
struct _arguments {
|
||||
asdl_seq *args;
|
||||
identifier vararg;
|
||||
expr_ty varargannotation;
|
||||
asdl_seq *kwonlyargs;
|
||||
identifier kwarg;
|
||||
expr_ty kwargannotation;
|
||||
asdl_seq *defaults;
|
||||
asdl_seq *kw_defaults;
|
||||
};
|
||||
|
||||
enum _arg_kind {SimpleArg_kind=1, NestedArgs_kind=2};
|
||||
struct _arg {
|
||||
enum _arg_kind kind;
|
||||
union {
|
||||
struct {
|
||||
identifier arg;
|
||||
expr_ty annotation;
|
||||
} SimpleArg;
|
||||
|
||||
struct {
|
||||
asdl_seq *args;
|
||||
} NestedArgs;
|
||||
|
||||
} v;
|
||||
};
|
||||
|
||||
struct _keyword {
|
||||
identifier arg;
|
||||
expr_ty value;
|
||||
|
@ -350,8 +371,8 @@ mod_ty Interactive(asdl_seq * body, PyArena *arena);
|
|||
mod_ty Expression(expr_ty body, PyArena *arena);
|
||||
mod_ty Suite(asdl_seq * body, PyArena *arena);
|
||||
stmt_ty FunctionDef(identifier name, arguments_ty args, asdl_seq * body,
|
||||
asdl_seq * decorators, int lineno, int col_offset, PyArena
|
||||
*arena);
|
||||
asdl_seq * decorators, expr_ty returns, int lineno, int
|
||||
col_offset, PyArena *arena);
|
||||
stmt_ty ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, int
|
||||
lineno, int col_offset, PyArena *arena);
|
||||
stmt_ty Return(expr_ty value, int lineno, int col_offset, PyArena *arena);
|
||||
|
@ -429,9 +450,12 @@ comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs,
|
|||
PyArena *arena);
|
||||
excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int
|
||||
lineno, int col_offset, PyArena *arena);
|
||||
arguments_ty arguments(asdl_seq * args, identifier vararg, asdl_seq *
|
||||
kwonlyargs, identifier kwarg, asdl_seq * defaults,
|
||||
arguments_ty arguments(asdl_seq * args, identifier vararg, expr_ty
|
||||
varargannotation, asdl_seq * kwonlyargs, identifier
|
||||
kwarg, expr_ty kwargannotation, asdl_seq * defaults,
|
||||
asdl_seq * kw_defaults, PyArena *arena);
|
||||
arg_ty SimpleArg(identifier arg, expr_ty annotation, PyArena *arena);
|
||||
arg_ty NestedArgs(asdl_seq * args, PyArena *arena);
|
||||
keyword_ty keyword(identifier arg, expr_ty value, PyArena *arena);
|
||||
alias_ty alias(identifier name, identifier asname, PyArena *arena);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef struct {
|
|||
PyObject *func_dict; /* The __dict__ attribute, a dict or NULL */
|
||||
PyObject *func_weakreflist; /* List of weak references */
|
||||
PyObject *func_module; /* The __module__ attribute, can be anything */
|
||||
PyObject *func_annotations; /* Annotations, a dict or NULL */
|
||||
|
||||
/* Invariant:
|
||||
* func_closure contains the bindings for func_code->co_freevars, so
|
||||
|
@ -52,6 +53,8 @@ PyAPI_FUNC(PyObject *) PyFunction_GetKwDefaults(PyObject *);
|
|||
PyAPI_FUNC(int) PyFunction_SetKwDefaults(PyObject *, PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyFunction_GetClosure(PyObject *);
|
||||
PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyFunction_GetAnnotations(PyObject *);
|
||||
PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *);
|
||||
|
||||
/* Macros for direct access to these values. Type checks are *not*
|
||||
done, so use with care. */
|
||||
|
@ -67,6 +70,8 @@ PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
|||
(((PyFunctionObject *)func) -> func_kwdefaults)
|
||||
#define PyFunction_GET_CLOSURE(func) \
|
||||
(((PyFunctionObject *)func) -> func_closure)
|
||||
#define PyFunction_GET_ANNOTATIONS(func) \
|
||||
(((PyFunctionObject *)func) -> func_annotations)
|
||||
|
||||
/* The classmethod and staticmethod types lives here, too */
|
||||
PyAPI_DATA(PyTypeObject) PyClassMethod_Type;
|
||||
|
|
|
@ -5,79 +5,84 @@
|
|||
#define decorators 260
|
||||
#define funcdef 261
|
||||
#define parameters 262
|
||||
#define varargslist 263
|
||||
#define fpdef 264
|
||||
#define fplist 265
|
||||
#define stmt 266
|
||||
#define simple_stmt 267
|
||||
#define small_stmt 268
|
||||
#define expr_stmt 269
|
||||
#define augassign 270
|
||||
#define print_stmt 271
|
||||
#define del_stmt 272
|
||||
#define pass_stmt 273
|
||||
#define flow_stmt 274
|
||||
#define break_stmt 275
|
||||
#define continue_stmt 276
|
||||
#define return_stmt 277
|
||||
#define yield_stmt 278
|
||||
#define raise_stmt 279
|
||||
#define import_stmt 280
|
||||
#define import_name 281
|
||||
#define import_from 282
|
||||
#define import_as_name 283
|
||||
#define dotted_as_name 284
|
||||
#define import_as_names 285
|
||||
#define dotted_as_names 286
|
||||
#define dotted_name 287
|
||||
#define global_stmt 288
|
||||
#define assert_stmt 289
|
||||
#define compound_stmt 290
|
||||
#define if_stmt 291
|
||||
#define while_stmt 292
|
||||
#define for_stmt 293
|
||||
#define try_stmt 294
|
||||
#define with_stmt 295
|
||||
#define with_var 296
|
||||
#define except_clause 297
|
||||
#define suite 298
|
||||
#define testlist_safe 299
|
||||
#define old_test 300
|
||||
#define old_lambdef 301
|
||||
#define test 302
|
||||
#define or_test 303
|
||||
#define and_test 304
|
||||
#define not_test 305
|
||||
#define comparison 306
|
||||
#define comp_op 307
|
||||
#define expr 308
|
||||
#define xor_expr 309
|
||||
#define and_expr 310
|
||||
#define shift_expr 311
|
||||
#define arith_expr 312
|
||||
#define term 313
|
||||
#define factor 314
|
||||
#define power 315
|
||||
#define atom 316
|
||||
#define listmaker 317
|
||||
#define testlist_gexp 318
|
||||
#define lambdef 319
|
||||
#define trailer 320
|
||||
#define subscriptlist 321
|
||||
#define subscript 322
|
||||
#define sliceop 323
|
||||
#define exprlist 324
|
||||
#define testlist 325
|
||||
#define dictsetmaker 326
|
||||
#define classdef 327
|
||||
#define arglist 328
|
||||
#define argument 329
|
||||
#define list_iter 330
|
||||
#define list_for 331
|
||||
#define list_if 332
|
||||
#define gen_iter 333
|
||||
#define gen_for 334
|
||||
#define gen_if 335
|
||||
#define testlist1 336
|
||||
#define encoding_decl 337
|
||||
#define yield_expr 338
|
||||
#define typedargslist 263
|
||||
#define tname 264
|
||||
#define tfpdef 265
|
||||
#define tfplist 266
|
||||
#define varargslist 267
|
||||
#define vname 268
|
||||
#define vfpdef 269
|
||||
#define vfplist 270
|
||||
#define stmt 271
|
||||
#define simple_stmt 272
|
||||
#define small_stmt 273
|
||||
#define expr_stmt 274
|
||||
#define augassign 275
|
||||
#define print_stmt 276
|
||||
#define del_stmt 277
|
||||
#define pass_stmt 278
|
||||
#define flow_stmt 279
|
||||
#define break_stmt 280
|
||||
#define continue_stmt 281
|
||||
#define return_stmt 282
|
||||
#define yield_stmt 283
|
||||
#define raise_stmt 284
|
||||
#define import_stmt 285
|
||||
#define import_name 286
|
||||
#define import_from 287
|
||||
#define import_as_name 288
|
||||
#define dotted_as_name 289
|
||||
#define import_as_names 290
|
||||
#define dotted_as_names 291
|
||||
#define dotted_name 292
|
||||
#define global_stmt 293
|
||||
#define assert_stmt 294
|
||||
#define compound_stmt 295
|
||||
#define if_stmt 296
|
||||
#define while_stmt 297
|
||||
#define for_stmt 298
|
||||
#define try_stmt 299
|
||||
#define with_stmt 300
|
||||
#define with_var 301
|
||||
#define except_clause 302
|
||||
#define suite 303
|
||||
#define testlist_safe 304
|
||||
#define old_test 305
|
||||
#define old_lambdef 306
|
||||
#define test 307
|
||||
#define or_test 308
|
||||
#define and_test 309
|
||||
#define not_test 310
|
||||
#define comparison 311
|
||||
#define comp_op 312
|
||||
#define expr 313
|
||||
#define xor_expr 314
|
||||
#define and_expr 315
|
||||
#define shift_expr 316
|
||||
#define arith_expr 317
|
||||
#define term 318
|
||||
#define factor 319
|
||||
#define power 320
|
||||
#define atom 321
|
||||
#define listmaker 322
|
||||
#define testlist_gexp 323
|
||||
#define lambdef 324
|
||||
#define trailer 325
|
||||
#define subscriptlist 326
|
||||
#define subscript 327
|
||||
#define sliceop 328
|
||||
#define exprlist 329
|
||||
#define testlist 330
|
||||
#define dictsetmaker 331
|
||||
#define classdef 332
|
||||
#define arglist 333
|
||||
#define argument 334
|
||||
#define list_iter 335
|
||||
#define list_for 336
|
||||
#define list_if 337
|
||||
#define gen_iter 338
|
||||
#define gen_for 339
|
||||
#define gen_if 340
|
||||
#define testlist1 341
|
||||
#define encoding_decl 342
|
||||
#define yield_expr 343
|
||||
|
|
|
@ -58,10 +58,11 @@ extern "C" {
|
|||
#define DOUBLESLASH 48
|
||||
#define DOUBLESLASHEQUAL 49
|
||||
#define AT 50
|
||||
#define RARROW 51
|
||||
/* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
|
||||
#define OP 51
|
||||
#define ERRORTOKEN 52
|
||||
#define N_TOKENS 53
|
||||
#define OP 52
|
||||
#define ERRORTOKEN 53
|
||||
#define N_TOKENS 54
|
||||
|
||||
/* Special definitions for cooperation with parser */
|
||||
|
||||
|
|
|
@ -33,7 +33,10 @@ class Node:
|
|||
pass # implemented by subclasses
|
||||
|
||||
class EmptyNode(Node):
|
||||
pass
|
||||
def getChildNodes(self):
|
||||
return ()
|
||||
def getChildren(self):
|
||||
return ()
|
||||
|
||||
class Expression(Node):
|
||||
# Expression is an artificial node class to support "eval"
|
||||
|
@ -487,12 +490,13 @@ class From(Node):
|
|||
return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
|
||||
|
||||
class Function(Node):
|
||||
def __init__(self, decorators, name, argnames, defaults, kwonlyargs, flags, doc, code, lineno=None):
|
||||
def __init__(self, decorators, name, arguments, defaults, kwonlyargs, returns, flags, doc, code, lineno=None):
|
||||
self.decorators = decorators
|
||||
self.name = name
|
||||
self.argnames = argnames
|
||||
self.arguments = arguments
|
||||
self.defaults = defaults
|
||||
self.kwonlyargs = kwonlyargs
|
||||
self.returns = returns
|
||||
self.flags = flags
|
||||
self.doc = doc
|
||||
self.code = code
|
||||
|
@ -508,9 +512,10 @@ class Function(Node):
|
|||
children = []
|
||||
children.append(self.decorators)
|
||||
children.append(self.name)
|
||||
children.append(self.argnames)
|
||||
children.extend(flatten(self.arguments))
|
||||
children.extend(flatten(self.defaults))
|
||||
children.append(self.kwonlyargs)
|
||||
children.extend(flatten(self.kwonlyargs))
|
||||
children.append(self.returns)
|
||||
children.append(self.flags)
|
||||
children.append(self.doc)
|
||||
children.append(self.code)
|
||||
|
@ -520,18 +525,22 @@ class Function(Node):
|
|||
nodelist = []
|
||||
if self.decorators is not None:
|
||||
nodelist.append(self.decorators)
|
||||
nodelist.extend(flatten_nodes(self.arguments))
|
||||
nodelist.extend(flatten_nodes(self.defaults))
|
||||
nodelist.extend(flatten_nodes(self.kwonlyargs))
|
||||
if self.returns is not None:
|
||||
nodelist.append(self.returns)
|
||||
nodelist.append(self.code)
|
||||
return tuple(nodelist)
|
||||
|
||||
def __repr__(self):
|
||||
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))
|
||||
return "Function(%s, %s, %s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.arguments), repr(self.defaults), repr(self.kwonlyargs), repr(self.returns), repr(self.flags), repr(self.doc), repr(self.code))
|
||||
|
||||
class GenExpr(Node):
|
||||
def __init__(self, code, lineno=None):
|
||||
self.code = code
|
||||
self.lineno = lineno
|
||||
self.argnames = ['.0']
|
||||
self.arguments = [SimpleArg('.0', None)]
|
||||
self.varargs = self.kwargs = None
|
||||
self.kwonlyargs = ()
|
||||
|
||||
|
@ -715,9 +724,24 @@ class Keyword(Node):
|
|||
def __repr__(self):
|
||||
return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
|
||||
|
||||
class Kwarg(Node):
|
||||
def __init__(self, arg, expr, lineno=None):
|
||||
self.arg = arg
|
||||
self.expr = expr
|
||||
self.lineno = lineno
|
||||
|
||||
def getChildren(self):
|
||||
return self.arg, self.expr
|
||||
|
||||
def getChildNodes(self):
|
||||
return self.arg, self.expr
|
||||
|
||||
def __repr__(self):
|
||||
return "Kwarg(%s, %s)" % (repr(self.arg), repr(self.expr))
|
||||
|
||||
class Lambda(Node):
|
||||
def __init__(self, argnames, defaults, kwonlyargs, flags, code, lineno=None):
|
||||
self.argnames = argnames
|
||||
def __init__(self, arguments, defaults, kwonlyargs, flags, code, lineno=None):
|
||||
self.arguments = arguments
|
||||
self.defaults = defaults
|
||||
self.kwonlyargs = kwonlyargs
|
||||
self.flags = flags
|
||||
|
@ -728,25 +752,28 @@ class Lambda(Node):
|
|||
self.varargs = 1
|
||||
if flags & CO_VARKEYWORDS:
|
||||
self.kwargs = 1
|
||||
self.returns = None
|
||||
|
||||
|
||||
def getChildren(self):
|
||||
children = []
|
||||
children.append(self.argnames)
|
||||
children.extend(flatten(self.arguments))
|
||||
children.extend(flatten(self.defaults))
|
||||
children.append(self.kwonlyargs)
|
||||
children.extend(flatten(self.kwonlyargs))
|
||||
children.append(self.flags)
|
||||
children.append(self.code)
|
||||
return tuple(children)
|
||||
|
||||
def getChildNodes(self):
|
||||
nodelist = []
|
||||
nodelist.extend(flatten_nodes(self.arguments))
|
||||
nodelist.extend(flatten_nodes(self.defaults))
|
||||
nodelist.extend(flatten_nodes(self.kwonlyargs))
|
||||
nodelist.append(self.code)
|
||||
return tuple(nodelist)
|
||||
|
||||
def __repr__(self):
|
||||
return "Lambda(%s, %s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.kwonlyargs), repr(self.flags), repr(self.code))
|
||||
return "Lambda(%s, %s, %s, %s, %s)" % (repr(self.arguments), repr(self.defaults), repr(self.kwonlyargs), repr(self.flags), repr(self.code))
|
||||
|
||||
class LeftShift(Node):
|
||||
def __init__(self, (left, right), lineno=None):
|
||||
|
@ -897,6 +924,22 @@ class Name(Node):
|
|||
def __repr__(self):
|
||||
return "Name(%s)" % (repr(self.name),)
|
||||
|
||||
class NestedArgs(Node):
|
||||
def __init__(self, args, lineno=None):
|
||||
self.args = args
|
||||
self.lineno = lineno
|
||||
|
||||
def getChildren(self):
|
||||
return tuple(flatten(self.args))
|
||||
|
||||
def getChildNodes(self):
|
||||
nodelist = []
|
||||
nodelist.extend(flatten_nodes(self.args))
|
||||
return tuple(nodelist)
|
||||
|
||||
def __repr__(self):
|
||||
return "NestedArgs(%s)" % (repr(self.args),)
|
||||
|
||||
class Not(Node):
|
||||
def __init__(self, expr, lineno=None):
|
||||
self.expr = expr
|
||||
|
@ -1071,6 +1114,27 @@ class Set(Node):
|
|||
def __repr__(self):
|
||||
return "Set(%s)" % (repr(self.items),)
|
||||
|
||||
class SimpleArg(Node):
|
||||
def __init__(self, name, annotation, lineno=None):
|
||||
self.name = name
|
||||
self.annotation = annotation
|
||||
self.lineno = lineno
|
||||
|
||||
def getChildren(self):
|
||||
children = []
|
||||
children.append(self.name)
|
||||
children.append(self.annotation)
|
||||
return tuple(children)
|
||||
|
||||
def getChildNodes(self):
|
||||
nodelist = []
|
||||
if self.annotation is not None:
|
||||
nodelist.append(self.annotation)
|
||||
return tuple(nodelist)
|
||||
|
||||
def __repr__(self):
|
||||
return "SimpleArg(%s, %s)" % (repr(self.name), repr(self.annotation))
|
||||
|
||||
class Slice(Node):
|
||||
def __init__(self, expr, flags, lower, upper, lineno=None):
|
||||
self.expr = expr
|
||||
|
|
|
@ -314,7 +314,7 @@ class PyFlowGraph(FlowGraph):
|
|||
super_init = FlowGraph.__init__
|
||||
|
||||
def __init__(self, name, filename,
|
||||
args=(), kwonlyargs={}, optimized=0, klass=None):
|
||||
args=(), kwonlyargs=(), optimized=0, klass=None):
|
||||
self.super_init()
|
||||
self.name = name
|
||||
self.filename = filename
|
||||
|
@ -338,24 +338,40 @@ class PyFlowGraph(FlowGraph):
|
|||
# The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both
|
||||
# kinds of variables.
|
||||
self.closure = []
|
||||
self.varnames = list(args) or []
|
||||
for i in range(len(self.varnames)):
|
||||
# The varnames list needs to be computed after flags have been set
|
||||
self.varnames = []
|
||||
self.stage = RAW
|
||||
|
||||
def computeVarnames(self):
|
||||
# self.args is positional, vararg, kwarg, kwonly, unpacked. This
|
||||
# order is due to the visit order in symbol module and could change.
|
||||
# argcount is # len(self.args) - len(unpacked). We want
|
||||
# self.varnames to be positional, kwonly, vararg, kwarg, unpacked
|
||||
# and argcount to be len(positional).
|
||||
|
||||
# determine starting index of unpacked, kwonly, vararg
|
||||
u = self.argcount # starting index of unpacked
|
||||
k = u - len(self.kwonlyargs) # starting index of kwonly
|
||||
v = k - self.checkFlag(CO_VARARGS) - self.checkFlag(CO_VARKEYWORDS)
|
||||
|
||||
vars = list(self.args)
|
||||
self.varnames = vars[:v] + vars[k:u] + vars[v:k] + vars[u:]
|
||||
self.argcount = v
|
||||
|
||||
# replace TupleArgs with calculated var name
|
||||
for i in range(self.argcount):
|
||||
var = self.varnames[i]
|
||||
if isinstance(var, TupleArg):
|
||||
self.varnames[i] = var.getName()
|
||||
self.stage = RAW
|
||||
|
||||
def setDocstring(self, doc):
|
||||
self.docstring = doc
|
||||
|
||||
def setFlag(self, flag):
|
||||
self.flags = self.flags | flag
|
||||
if flag == CO_VARARGS:
|
||||
self.argcount = self.argcount - 1
|
||||
|
||||
def checkFlag(self, flag):
|
||||
if self.flags & flag:
|
||||
return 1
|
||||
return (self.flags & flag) == flag
|
||||
|
||||
def setFreeVars(self, names):
|
||||
self.freevars = list(names)
|
||||
|
@ -366,6 +382,7 @@ class PyFlowGraph(FlowGraph):
|
|||
def getCode(self):
|
||||
"""Get a Python code object"""
|
||||
assert self.stage == RAW
|
||||
self.computeVarnames()
|
||||
self.computeStackDepth()
|
||||
self.flattenGraph()
|
||||
assert self.stage == FLAT
|
||||
|
@ -575,6 +592,12 @@ class PyFlowGraph(FlowGraph):
|
|||
lnotab.nextLine(oparg)
|
||||
continue
|
||||
hi, lo = twobyte(oparg)
|
||||
|
||||
extended, hi = twobyte(hi)
|
||||
if extended:
|
||||
ehi, elo = twobyte(extended)
|
||||
lnotab.addCode(self.opnum['EXTENDED_ARG'], elo, ehi)
|
||||
|
||||
try:
|
||||
lnotab.addCode(self.opnum[opname], lo, hi)
|
||||
except ValueError:
|
||||
|
@ -595,8 +618,6 @@ class PyFlowGraph(FlowGraph):
|
|||
else:
|
||||
nlocals = len(self.varnames)
|
||||
argcount = self.argcount
|
||||
if self.flags & CO_VARKEYWORDS:
|
||||
argcount = argcount - 1
|
||||
kwonlyargcount = len(self.kwonlyargs)
|
||||
return new.code(argcount, kwonlyargcount,
|
||||
nlocals, self.stacksize, self.flags,
|
||||
|
@ -809,7 +830,8 @@ class StackDepthTracker:
|
|||
return self.CALL_FUNCTION(argc)-2
|
||||
def MAKE_FUNCTION(self, argc):
|
||||
hi, lo = divmod(argc, 256)
|
||||
return -(lo + hi * 2)
|
||||
ehi, hi = divmod(hi, 256)
|
||||
return -(lo + hi * 2 + ehi)
|
||||
def MAKE_CLOSURE(self, argc):
|
||||
# XXX need to account for free variables too!
|
||||
return -argc
|
||||
|
|
|
@ -378,18 +378,57 @@ class CodeGenerator:
|
|||
walk(node.code, gen)
|
||||
gen.finish()
|
||||
self.set_lineno(node)
|
||||
num_kwargs = 0
|
||||
for keyword in node.kwonlyargs:
|
||||
default = keyword.expr
|
||||
if isinstance(default, ast.EmptyNode):
|
||||
continue
|
||||
self.emit('LOAD_CONST', keyword.name)
|
||||
self.emit('LOAD_CONST', keyword.arg.name)
|
||||
self.visit(default)
|
||||
num_kwargs += 1
|
||||
for default in node.defaults:
|
||||
self.visit(default)
|
||||
self._makeClosure(gen, len(node.defaults))
|
||||
|
||||
num_annotations = self._visit_annotations(node)
|
||||
|
||||
oparg = len(node.defaults)
|
||||
oparg |= num_kwargs << 8
|
||||
oparg |= num_annotations << 16
|
||||
|
||||
self._makeClosure(gen, oparg)
|
||||
for i in range(ndecorators):
|
||||
self.emit('CALL_FUNCTION', 1)
|
||||
|
||||
def _visit_annotations(self, node):
|
||||
# emit code, return num_annotations
|
||||
annotations = []
|
||||
annotations.extend(self._visit_argument_annotations(node.arguments))
|
||||
annotations.extend(self._visit_kwarg_annotations(node.kwonlyargs))
|
||||
if node.returns:
|
||||
self.visit(node.returns)
|
||||
annotations.append('return')
|
||||
if not annotations:
|
||||
return 0
|
||||
self.emit('LOAD_CONST', tuple(annotations))
|
||||
return len(annotations) + 1
|
||||
|
||||
def _visit_argument_annotations(self, arguments):
|
||||
for arg in arguments:
|
||||
if isinstance(arg, ast.SimpleArg):
|
||||
if arg.annotation:
|
||||
self.visit(arg.annotation)
|
||||
yield arg.name
|
||||
else:
|
||||
for name in self._visit_argument_annotations(arg.args):
|
||||
yield name
|
||||
|
||||
def _visit_kwarg_annotations(self, kwargs):
|
||||
for kwarg in kwargs:
|
||||
arg = kwarg.arg
|
||||
if arg.annotation:
|
||||
self.visit(arg.annotation)
|
||||
yield arg.name
|
||||
|
||||
def visitClass(self, node):
|
||||
gen = self.ClassGen(node, self.scopes,
|
||||
self.get_module())
|
||||
|
@ -1323,7 +1362,7 @@ class AbstractFunctionCode:
|
|||
else:
|
||||
name = func.name
|
||||
|
||||
args, hasTupleArg = generateArgList(func.argnames)
|
||||
args, hasTupleArg = generateArgList(func.arguments)
|
||||
kwonlyargs = generateKwonlyArgList(func.kwonlyargs)
|
||||
self.graph = pyassem.PyFlowGraph(name, func.filename, args,
|
||||
kwonlyargs=kwonlyargs,
|
||||
|
@ -1334,7 +1373,7 @@ class AbstractFunctionCode:
|
|||
if not isLambda and func.doc:
|
||||
self.setDocstring(func.doc)
|
||||
|
||||
lnf = walk(func.code, self.NameFinder(args), verbose=0)
|
||||
lnf = walk(func.code, self.NameFinder(args+kwonlyargs), verbose=0)
|
||||
self.locals.push(lnf.getLocals())
|
||||
if func.varargs:
|
||||
self.graph.setFlag(CO_VARARGS)
|
||||
|
@ -1342,7 +1381,7 @@ class AbstractFunctionCode:
|
|||
self.graph.setFlag(CO_VARKEYWORDS)
|
||||
self.set_lineno(func)
|
||||
if hasTupleArg:
|
||||
self.generateArgUnpack(func.argnames)
|
||||
self.generateArgUnpack(func.arguments)
|
||||
|
||||
def get_module(self):
|
||||
return self.module
|
||||
|
@ -1356,9 +1395,9 @@ class AbstractFunctionCode:
|
|||
def generateArgUnpack(self, args):
|
||||
for i in range(len(args)):
|
||||
arg = args[i]
|
||||
if isinstance(arg, tuple):
|
||||
if isinstance(arg, ast.NestedArgs):
|
||||
self.emit('LOAD_FAST', '.%d' % (i * 2))
|
||||
self.unpackSequence(arg)
|
||||
self.unpackSequence(tuple(_nested_names(arg)))
|
||||
|
||||
def unpackSequence(self, tup):
|
||||
if VERSION > 1:
|
||||
|
@ -1452,21 +1491,29 @@ def generateArgList(arglist):
|
|||
count = 0
|
||||
for i in range(len(arglist)):
|
||||
elt = arglist[i]
|
||||
if isinstance(elt, str):
|
||||
args.append(elt)
|
||||
elif isinstance(elt, tuple):
|
||||
args.append(TupleArg(i * 2, elt))
|
||||
extra.extend(misc.flatten(elt))
|
||||
if isinstance(elt, ast.SimpleArg):
|
||||
args.append(elt.name)
|
||||
elif isinstance(elt, ast.NestedArgs):
|
||||
t = tuple(_nested_names(elt))
|
||||
args.append(TupleArg(i * 2, t))
|
||||
extra.extend(misc.flatten(t))
|
||||
count = count + 1
|
||||
else:
|
||||
raise ValueError, "unexpect argument type:", elt
|
||||
return args + extra, count
|
||||
|
||||
def _nested_names(elt):
|
||||
for arg in elt.args:
|
||||
if isinstance(arg, ast.SimpleArg):
|
||||
yield arg.name
|
||||
elif isinstance(arg, ast.NestedArgs):
|
||||
yield tuple(_nested_names(arg))
|
||||
|
||||
def generateKwonlyArgList(keywordOnlyArgs):
|
||||
kwonlyargs = {}
|
||||
kwonlyargs = []
|
||||
for elt in keywordOnlyArgs:
|
||||
assert isinstance(elt, ast.Keyword)
|
||||
kwonlyargs[elt.name] = elt.expr
|
||||
assert isinstance(elt, ast.Kwarg)
|
||||
kwonlyargs.append(elt.arg.name)
|
||||
return kwonlyargs
|
||||
|
||||
def findOp(node):
|
||||
|
|
|
@ -233,7 +233,12 @@ class SymbolVisitor:
|
|||
if parent.nested or isinstance(parent, FunctionScope):
|
||||
scope.nested = 1
|
||||
self.scopes[node] = scope
|
||||
self._do_args(scope, node.argnames)
|
||||
|
||||
args = node.arguments
|
||||
for kwonly in node.kwonlyargs:
|
||||
args.append(kwonly.arg)
|
||||
self._do_arguments(scope, args)
|
||||
|
||||
self.visit(node.code, scope)
|
||||
self.handle_free_vars(scope, parent)
|
||||
|
||||
|
@ -275,16 +280,18 @@ class SymbolVisitor:
|
|||
if parent.nested or isinstance(parent, FunctionScope):
|
||||
scope.nested = 1
|
||||
self.scopes[node] = scope
|
||||
self._do_args(scope, node.argnames)
|
||||
self._do_arguments(scope, node.arguments)
|
||||
self.visit(node.code, scope)
|
||||
self.handle_free_vars(scope, parent)
|
||||
|
||||
def _do_args(self, scope, args):
|
||||
for name in args:
|
||||
if type(name) == types.TupleType:
|
||||
self._do_args(scope, name)
|
||||
def _do_arguments(self, scope, arguments):
|
||||
for node in arguments:
|
||||
if isinstance(node, ast.SimpleArg):
|
||||
scope.add_param(node.name)
|
||||
if node.annotation:
|
||||
self.visit(node.annotation, scope)
|
||||
else:
|
||||
scope.add_param(name)
|
||||
self._do_arguments(scope, node.args)
|
||||
|
||||
def handle_free_vars(self, scope, parent):
|
||||
parent.add_child(scope)
|
||||
|
|
|
@ -234,25 +234,24 @@ class Transformer:
|
|||
return Decorators(items)
|
||||
|
||||
def funcdef(self, nodelist):
|
||||
# -6 -5 -4 -3 -2 -1
|
||||
# funcdef: [decorators] 'def' NAME parameters ':' suite
|
||||
# parameters: '(' [varargslist] ')'
|
||||
|
||||
if len(nodelist) == 6:
|
||||
assert nodelist[0][0] == symbol.decorators
|
||||
# 0 1 2 4 -1
|
||||
# funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite
|
||||
# parameters: '(' [typedargslist] ')'
|
||||
if nodelist[0][0] == symbol.decorators:
|
||||
decorators = self.decorators(nodelist[0][1:])
|
||||
nodelist = nodelist[1:]
|
||||
else:
|
||||
assert len(nodelist) == 5
|
||||
decorators = None
|
||||
assert len(nodelist) in (5, 7)
|
||||
|
||||
lineno = nodelist[-4][2]
|
||||
name = nodelist[-4][1]
|
||||
args = nodelist[-3][2]
|
||||
lineno = nodelist[0][2]
|
||||
name = nodelist[1][1]
|
||||
args = nodelist[2][2]
|
||||
|
||||
if args[0] == symbol.varargslist:
|
||||
names, defaults, kwonlyargs, flags = self.com_arglist(args[1:])
|
||||
if args[0] == symbol.varargslist or args[0] == symbol.typedargslist:
|
||||
arguments, defaults, kwonly, flags = self.com_arglist(args[1:])
|
||||
else:
|
||||
names = defaults = kwonlyargs = ()
|
||||
arguments = defaults = kwonly = ()
|
||||
flags = 0
|
||||
doc = self.get_docstring(nodelist[-1])
|
||||
|
||||
|
@ -263,22 +262,28 @@ class Transformer:
|
|||
assert isinstance(code, Stmt)
|
||||
assert isinstance(code.nodes[0], Discard)
|
||||
del code.nodes[0]
|
||||
return Function(decorators, name, names, defaults,
|
||||
kwonlyargs, flags, doc, code, lineno=lineno)
|
||||
|
||||
if len(nodelist) == 7:
|
||||
returns = self.com_node(nodelist[4])
|
||||
else:
|
||||
returns = None
|
||||
|
||||
return Function(decorators, name, arguments, defaults,
|
||||
kwonly, returns, flags, doc, code, lineno=lineno)
|
||||
|
||||
def lambdef(self, nodelist):
|
||||
# lambdef: 'lambda' [varargslist] ':' test
|
||||
if nodelist[2][0] == symbol.varargslist:
|
||||
names, defaults, kwonlyargs, flags = \
|
||||
arguments, defaults, kwonlyargs, flags = \
|
||||
self.com_arglist(nodelist[2][1:])
|
||||
else:
|
||||
names = defaults = kwonlyargs = ()
|
||||
arguments = defaults = kwonlyargs = ()
|
||||
flags = 0
|
||||
|
||||
# code for lambda
|
||||
code = self.com_node(nodelist[-1])
|
||||
|
||||
return Lambda(names, defaults, kwonlyargs,
|
||||
return Lambda(arguments, defaults, kwonlyargs,
|
||||
flags, code, lineno=nodelist[1][2])
|
||||
old_lambdef = lambdef
|
||||
|
||||
|
@ -324,10 +329,25 @@ class Transformer:
|
|||
def varargslist(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def fpdef(self, nodelist):
|
||||
def vfpdef(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def fplist(self, nodelist):
|
||||
def vfplist(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def vname(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def typedargslist(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def tfpdef(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def tfplist(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def tname(self, nodelist):
|
||||
raise WalkerError
|
||||
|
||||
def dotted_name(self, nodelist):
|
||||
|
@ -786,9 +806,10 @@ class Transformer:
|
|||
return Discard(Const(None))
|
||||
|
||||
def keywordonlyargs(self, nodelist):
|
||||
# (',' NAME ['=' test])*
|
||||
# (',' tname ['=' test])*
|
||||
# ^^^
|
||||
# ------+
|
||||
# tname and vname are handled.
|
||||
kwonlyargs = []
|
||||
i = 0
|
||||
while i < len(nodelist):
|
||||
|
@ -802,11 +823,26 @@ class Transformer:
|
|||
i += 2
|
||||
if node[0] == token.DOUBLESTAR:
|
||||
return kwonlyargs, i
|
||||
elif node[0] == token.NAME:
|
||||
kwonlyargs.append(Keyword(node[1], default, lineno=node[2]))
|
||||
elif node[0] in (symbol.vname, symbol.tname):
|
||||
lineno = extractLineNo(node)
|
||||
kwarg = Kwarg(self._simplearg(node), default, lineno=lineno)
|
||||
kwonlyargs.append(kwarg)
|
||||
i += 2
|
||||
return kwonlyargs, i
|
||||
|
||||
def _simplearg(self, node):
|
||||
# tname: NAME [':' test]
|
||||
# vname: NAME
|
||||
assert node[0] == symbol.vname or node[0] == symbol.tname
|
||||
name = node[1][1]
|
||||
lineno = node[1][2]
|
||||
assert isinstance(name, str)
|
||||
if len(node) > 2:
|
||||
annotation = self.com_node(node[3])
|
||||
else:
|
||||
annotation = None
|
||||
return SimpleArg(name, annotation, lineno)
|
||||
|
||||
def com_arglist(self, nodelist):
|
||||
# varargslist:
|
||||
# (fpdef ['=' test] ',')*
|
||||
|
@ -814,7 +850,7 @@ class Transformer:
|
|||
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
# fpdef: NAME | '(' fplist ')'
|
||||
# fplist: fpdef (',' fpdef)* [',']
|
||||
names = []
|
||||
arguments = []
|
||||
kwonlyargs = []
|
||||
defaults = []
|
||||
flags = 0
|
||||
|
@ -825,14 +861,15 @@ class Transformer:
|
|||
if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
|
||||
if node[0] == token.STAR:
|
||||
node = nodelist[i+1]
|
||||
if node[0] == token.NAME: # vararg
|
||||
names.append(node[1])
|
||||
if node[0] in (symbol.tname, symbol.vname): # vararg
|
||||
arguments.append(self._simplearg(node))
|
||||
flags = flags | CO_VARARGS
|
||||
i = i + 3
|
||||
else: # no vararg
|
||||
assert node[0] == token.COMMA
|
||||
i += 2
|
||||
if i < len(nodelist) and nodelist[i][0] == token.NAME:
|
||||
if i < len(nodelist) and \
|
||||
nodelist[i][0] in (symbol.tname, symbol.vname):
|
||||
kwonlyargs, skip = self.keywordonlyargs(nodelist[i:])
|
||||
i += skip
|
||||
|
||||
|
@ -843,13 +880,13 @@ class Transformer:
|
|||
node = nodelist[i+1]
|
||||
else:
|
||||
raise ValueError, "unexpected token: %s" % t
|
||||
names.append(node[1])
|
||||
arguments.append(self._simplearg(node))
|
||||
flags = flags | CO_VARKEYWORDS
|
||||
|
||||
break
|
||||
|
||||
# fpdef: NAME | '(' fplist ')'
|
||||
names.append(self.com_fpdef(node))
|
||||
# tfpdef: tname | '(' tfplist ')'
|
||||
arguments.append(self.com_tfpdef(node))
|
||||
|
||||
i = i + 1
|
||||
if i < len(nodelist) and nodelist[i][0] == token.EQUAL:
|
||||
|
@ -863,21 +900,24 @@ class Transformer:
|
|||
# skip the comma
|
||||
i = i + 1
|
||||
|
||||
return names, defaults, kwonlyargs, flags
|
||||
return arguments, defaults, kwonlyargs, flags
|
||||
|
||||
def com_fpdef(self, node):
|
||||
# fpdef: NAME | '(' fplist ')'
|
||||
def com_tfpdef(self, node):
|
||||
# tfpdef: tname | '(' tfplist ')'
|
||||
# def f((x)): -- x is not nested
|
||||
while node[1][0] == token.LPAR and len(node[2]) == 2:
|
||||
node = node[2][1]
|
||||
if node[1][0] == token.LPAR:
|
||||
return self.com_fplist(node[2])
|
||||
return node[1][1]
|
||||
return NestedArgs(self.com_tfplist(node[2]))
|
||||
return self._simplearg(node[1])
|
||||
|
||||
def com_fplist(self, node):
|
||||
# fplist: fpdef (',' fpdef)* [',']
|
||||
def com_tfplist(self, node):
|
||||
# tfplist: tfpdef (',' tfpdef)* [',']
|
||||
if len(node) == 2:
|
||||
return self.com_fpdef(node[1])
|
||||
return self.com_tfpdef(node[1]),
|
||||
list = []
|
||||
for i in range(1, len(node), 2):
|
||||
list.append(self.com_fpdef(node[i]))
|
||||
list.append(self.com_tfpdef(node[i]))
|
||||
return tuple(list)
|
||||
|
||||
def com_dotted_name(self, node):
|
||||
|
|
157
Lib/symbol.py
157
Lib/symbol.py
|
@ -17,82 +17,87 @@ decorator = 259
|
|||
decorators = 260
|
||||
funcdef = 261
|
||||
parameters = 262
|
||||
varargslist = 263
|
||||
fpdef = 264
|
||||
fplist = 265
|
||||
stmt = 266
|
||||
simple_stmt = 267
|
||||
small_stmt = 268
|
||||
expr_stmt = 269
|
||||
augassign = 270
|
||||
print_stmt = 271
|
||||
del_stmt = 272
|
||||
pass_stmt = 273
|
||||
flow_stmt = 274
|
||||
break_stmt = 275
|
||||
continue_stmt = 276
|
||||
return_stmt = 277
|
||||
yield_stmt = 278
|
||||
raise_stmt = 279
|
||||
import_stmt = 280
|
||||
import_name = 281
|
||||
import_from = 282
|
||||
import_as_name = 283
|
||||
dotted_as_name = 284
|
||||
import_as_names = 285
|
||||
dotted_as_names = 286
|
||||
dotted_name = 287
|
||||
global_stmt = 288
|
||||
assert_stmt = 289
|
||||
compound_stmt = 290
|
||||
if_stmt = 291
|
||||
while_stmt = 292
|
||||
for_stmt = 293
|
||||
try_stmt = 294
|
||||
with_stmt = 295
|
||||
with_var = 296
|
||||
except_clause = 297
|
||||
suite = 298
|
||||
testlist_safe = 299
|
||||
old_test = 300
|
||||
old_lambdef = 301
|
||||
test = 302
|
||||
or_test = 303
|
||||
and_test = 304
|
||||
not_test = 305
|
||||
comparison = 306
|
||||
comp_op = 307
|
||||
expr = 308
|
||||
xor_expr = 309
|
||||
and_expr = 310
|
||||
shift_expr = 311
|
||||
arith_expr = 312
|
||||
term = 313
|
||||
factor = 314
|
||||
power = 315
|
||||
atom = 316
|
||||
listmaker = 317
|
||||
testlist_gexp = 318
|
||||
lambdef = 319
|
||||
trailer = 320
|
||||
subscriptlist = 321
|
||||
subscript = 322
|
||||
sliceop = 323
|
||||
exprlist = 324
|
||||
testlist = 325
|
||||
dictsetmaker = 326
|
||||
classdef = 327
|
||||
arglist = 328
|
||||
argument = 329
|
||||
list_iter = 330
|
||||
list_for = 331
|
||||
list_if = 332
|
||||
gen_iter = 333
|
||||
gen_for = 334
|
||||
gen_if = 335
|
||||
testlist1 = 336
|
||||
encoding_decl = 337
|
||||
yield_expr = 338
|
||||
typedargslist = 263
|
||||
tname = 264
|
||||
tfpdef = 265
|
||||
tfplist = 266
|
||||
varargslist = 267
|
||||
vname = 268
|
||||
vfpdef = 269
|
||||
vfplist = 270
|
||||
stmt = 271
|
||||
simple_stmt = 272
|
||||
small_stmt = 273
|
||||
expr_stmt = 274
|
||||
augassign = 275
|
||||
print_stmt = 276
|
||||
del_stmt = 277
|
||||
pass_stmt = 278
|
||||
flow_stmt = 279
|
||||
break_stmt = 280
|
||||
continue_stmt = 281
|
||||
return_stmt = 282
|
||||
yield_stmt = 283
|
||||
raise_stmt = 284
|
||||
import_stmt = 285
|
||||
import_name = 286
|
||||
import_from = 287
|
||||
import_as_name = 288
|
||||
dotted_as_name = 289
|
||||
import_as_names = 290
|
||||
dotted_as_names = 291
|
||||
dotted_name = 292
|
||||
global_stmt = 293
|
||||
assert_stmt = 294
|
||||
compound_stmt = 295
|
||||
if_stmt = 296
|
||||
while_stmt = 297
|
||||
for_stmt = 298
|
||||
try_stmt = 299
|
||||
with_stmt = 300
|
||||
with_var = 301
|
||||
except_clause = 302
|
||||
suite = 303
|
||||
testlist_safe = 304
|
||||
old_test = 305
|
||||
old_lambdef = 306
|
||||
test = 307
|
||||
or_test = 308
|
||||
and_test = 309
|
||||
not_test = 310
|
||||
comparison = 311
|
||||
comp_op = 312
|
||||
expr = 313
|
||||
xor_expr = 314
|
||||
and_expr = 315
|
||||
shift_expr = 316
|
||||
arith_expr = 317
|
||||
term = 318
|
||||
factor = 319
|
||||
power = 320
|
||||
atom = 321
|
||||
listmaker = 322
|
||||
testlist_gexp = 323
|
||||
lambdef = 324
|
||||
trailer = 325
|
||||
subscriptlist = 326
|
||||
subscript = 327
|
||||
sliceop = 328
|
||||
exprlist = 329
|
||||
testlist = 330
|
||||
dictsetmaker = 331
|
||||
classdef = 332
|
||||
arglist = 333
|
||||
argument = 334
|
||||
list_iter = 335
|
||||
list_for = 336
|
||||
list_if = 337
|
||||
gen_iter = 338
|
||||
gen_for = 339
|
||||
gen_if = 340
|
||||
testlist1 = 341
|
||||
encoding_decl = 342
|
||||
yield_expr = 343
|
||||
#--end constants--
|
||||
|
||||
sym_name = {}
|
||||
|
|
|
@ -682,4 +682,20 @@ test_tokenize
|
|||
177,11-177,15: NAME 'pass'
|
||||
177,15-177,16: NEWLINE '\n'
|
||||
178,0-178,1: NL '\n'
|
||||
179,0-179,0: ENDMARKER ''
|
||||
179,0-179,1: OP '@'
|
||||
179,1-179,13: NAME 'staticmethod'
|
||||
179,13-179,14: NEWLINE '\n'
|
||||
180,0-180,3: NAME 'def'
|
||||
180,4-180,7: NAME 'foo'
|
||||
180,7-180,8: OP '('
|
||||
180,8-180,9: NAME 'x'
|
||||
180,9-180,10: OP ':'
|
||||
180,10-180,11: NUMBER '1'
|
||||
180,11-180,12: OP ')'
|
||||
180,12-180,14: OP '->'
|
||||
180,14-180,15: NUMBER '1'
|
||||
180,15-180,16: OP ':'
|
||||
180,17-180,21: NAME 'pass'
|
||||
180,21-180,22: NEWLINE '\n'
|
||||
181,0-181,1: NL '\n'
|
||||
182,0-182,0: ENDMARKER ''
|
||||
|
|
|
@ -151,9 +151,9 @@ def run_tests():
|
|||
|
||||
#### EVERYTHING BELOW IS GENERATED #####
|
||||
exec_results = [
|
||||
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], None, [], []), [('Pass', (1, 9))], [])]),
|
||||
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Pass', (1, 9))], [], None)]),
|
||||
('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, [], None, None, [], []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]),
|
||||
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]),
|
||||
('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))]),
|
||||
|
@ -180,13 +180,13 @@ eval_results = [
|
|||
('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', ('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, [], None, None, [], []), ('Name', (1, 7), 'None', ('Load',)))),
|
||||
('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', ('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', ('Compare', (1, 0), ('Num', (1, 0), 1), [('Lt',), ('Lt',)], [('Num', (1, 4), 2), ('Num', (1, 8), 3)])),
|
||||
('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Num', (1, 2), 1), ('Num', (1, 4), 2)], [('keyword', 'c', ('Num', (1, 8), 3))], ('Name', (1, 11), 'd', ('Load',)), ('Name', (1, 15), 'e', ('Load',)))),
|
||||
('Expression', ('Num', (1, 0), 10L)),
|
||||
('Expression', ('Num', (1, 0), 10)),
|
||||
('Expression', ('Str', (1, 0), 'string')),
|
||||
('Expression', ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',))),
|
||||
('Expression', ('Subscript', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Slice', ('Name', (1, 2), 'b', ('Load',)), ('Name', (1, 4), 'c', ('Load',)), None), ('Load',))),
|
||||
|
|
|
@ -115,6 +115,24 @@ class CompilerTest(unittest.TestCase):
|
|||
dct = {}
|
||||
exec(c, dct)
|
||||
self.assertEquals(dct.get('result'), 3)
|
||||
c = compiler.compile('def g(a):\n'
|
||||
' def f(): return a + 2\n'
|
||||
' return f()\n'
|
||||
'result = g(1)',
|
||||
'<string>',
|
||||
'exec')
|
||||
dct = {}
|
||||
exec(c, dct)
|
||||
self.assertEquals(dct.get('result'), 3)
|
||||
c = compiler.compile('def g((a, b)):\n'
|
||||
' def f(): return a + b\n'
|
||||
' return f()\n'
|
||||
'result = g((1, 2))',
|
||||
'<string>',
|
||||
'exec')
|
||||
dct = {}
|
||||
exec(c, dct)
|
||||
self.assertEquals(dct.get('result'), 3)
|
||||
|
||||
def testGenExp(self):
|
||||
c = compiler.compile('list((i,j) for i in range(3) if i < 3'
|
||||
|
@ -123,6 +141,22 @@ class CompilerTest(unittest.TestCase):
|
|||
'eval')
|
||||
self.assertEquals(eval(c), [(0, 3), (1, 3), (2, 3)])
|
||||
|
||||
def testFuncAnnotations(self):
|
||||
testdata = [
|
||||
('def f(a: 1): pass', {'a': 1}),
|
||||
('''def f(a, (b:1, c:2, d), e:3=4, f=5,
|
||||
*g:6, h:7, i=8, j:9=10, **k:11) -> 12: pass
|
||||
''', {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9,
|
||||
'k': 11, 'return': 12}),
|
||||
]
|
||||
for sourcecode, expected in testdata:
|
||||
# avoid IndentationError: unexpected indent from trailing lines
|
||||
sourcecode = sourcecode.rstrip()+'\n'
|
||||
c = compiler.compile(sourcecode, '<string>', 'exec')
|
||||
dct = {}
|
||||
exec(c, dct)
|
||||
self.assertEquals(dct['f'].func_annotations, expected)
|
||||
|
||||
|
||||
NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
|
||||
|
||||
|
@ -167,10 +201,11 @@ from math import *
|
|||
|
||||
###############################################################################
|
||||
|
||||
def test_main():
|
||||
def test_main(all=False):
|
||||
global TEST_ALL
|
||||
TEST_ALL = test.test_support.is_resource_enabled("compiler")
|
||||
TEST_ALL = all or test.test_support.is_resource_enabled("compiler")
|
||||
test.test_support.run_unittest(CompilerTest)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
import sys
|
||||
test_main('all' in sys.argv)
|
||||
|
|
|
@ -138,16 +138,22 @@ class GrammarTests(unittest.TestCase):
|
|||
x = eval('1, 0 or 1')
|
||||
|
||||
def testFuncdef(self):
|
||||
### 'def' NAME parameters ':' suite
|
||||
### parameters: '(' [varargslist] ')'
|
||||
### varargslist: (fpdef ['=' test] ',')*
|
||||
### ('*' (NAME|',' fpdef ['=' test]) [',' ('**'|'*' '*') NAME]
|
||||
### | ('**'|'*' '*') NAME)
|
||||
### | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
### fpdef: NAME | '(' fplist ')'
|
||||
### fplist: fpdef (',' fpdef)* [',']
|
||||
### arglist: (argument ',')* (argument | *' test [',' '**' test] | '**' test)
|
||||
### argument: [test '='] test # Really [keyword '='] test
|
||||
### [decorators] 'def' NAME parameters ['->' test] ':' suite
|
||||
### decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
|
||||
### decorators: decorator+
|
||||
### parameters: '(' [typedargslist] ')'
|
||||
### typedargslist: ((tfpdef ['=' test] ',')*
|
||||
### ('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname)
|
||||
### | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
### tname: NAME [':' test]
|
||||
### tfpdef: tname | '(' tfplist ')'
|
||||
### tfplist: tfpdef (',' tfpdef)* [',']
|
||||
### varargslist: ((vfpdef ['=' test] ',')*
|
||||
### ('*' [vname] (',' vname ['=' test])* [',' '**' vname] | '**' vname)
|
||||
### | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
|
||||
### vname: NAME
|
||||
### vfpdef: vname | '(' vfplist ')'
|
||||
### vfplist: vfpdef (',' vfpdef)* [',']
|
||||
def f1(): pass
|
||||
f1()
|
||||
f1(*())
|
||||
|
@ -294,6 +300,28 @@ class GrammarTests(unittest.TestCase):
|
|||
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
|
||||
pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
|
||||
|
||||
# argument annotation tests
|
||||
def f(x) -> list: pass
|
||||
self.assertEquals(f.func_annotations, {'return': list})
|
||||
def f(x:int): pass
|
||||
self.assertEquals(f.func_annotations, {'x': int})
|
||||
def f(*x:str): pass
|
||||
self.assertEquals(f.func_annotations, {'x': str})
|
||||
def f(**x:float): pass
|
||||
self.assertEquals(f.func_annotations, {'x': float})
|
||||
def f(x, y:1+2): pass
|
||||
self.assertEquals(f.func_annotations, {'y': 3})
|
||||
def f(a, (b:1, c:2, d)): pass
|
||||
self.assertEquals(f.func_annotations, {'b': 1, 'c': 2})
|
||||
def f(a, (b:1, c:2, d), e:3=4, f=5, *g:6): pass
|
||||
self.assertEquals(f.func_annotations,
|
||||
{'b': 1, 'c': 2, 'e': 3, 'g': 6})
|
||||
def f(a, (b:1, c:2, d), e:3=4, f=5, *g:6, h:7, i=8, j:9=10,
|
||||
**k:11) -> 12: pass
|
||||
self.assertEquals(f.func_annotations,
|
||||
{'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9,
|
||||
'k': 11, 'return': 12})
|
||||
|
||||
def testLambdef(self):
|
||||
### lambdef: 'lambda' [varargslist] ':' test
|
||||
l1 = lambda : 0
|
||||
|
|
|
@ -219,5 +219,15 @@ def foo():
|
|||
if verbose:
|
||||
print 'finished'
|
||||
|
||||
def test_rarrow():
|
||||
"""
|
||||
This function exists solely to test the tokenization of the RARROW
|
||||
operator.
|
||||
|
||||
>>> tokenize(iter(['->']).next) #doctest: +NORMALIZE_WHITESPACE
|
||||
1,0-1,2:\tOP\t'->'
|
||||
2,0-2,0:\tENDMARKER\t''
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
|
|
|
@ -176,3 +176,6 @@ x = sys.modules['time'].time()
|
|||
@staticmethod
|
||||
def foo(): pass
|
||||
|
||||
@staticmethod
|
||||
def foo(x:1)->1: pass
|
||||
|
||||
|
|
|
@ -60,9 +60,10 @@ DOUBLESTAREQUAL = 47
|
|||
DOUBLESLASH = 48
|
||||
DOUBLESLASHEQUAL = 49
|
||||
AT = 50
|
||||
OP = 51
|
||||
ERRORTOKEN = 52
|
||||
N_TOKENS = 53
|
||||
RARROW = 51
|
||||
OP = 52
|
||||
ERRORTOKEN = 53
|
||||
N_TOKENS = 54
|
||||
NT_OFFSET = 256
|
||||
#--end constants--
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ String = group(r"[uU]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
|
|||
# longest operators first (e.g., if = came before ==, == would get
|
||||
# recognized as two instances of =).
|
||||
Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=",
|
||||
r"//=?",
|
||||
r"//=?", r"->",
|
||||
r"[+\-*/%&|^=<>]=?",
|
||||
r"~")
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ TO DO
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Added function annotations per PEP 3107.
|
||||
|
||||
- Moved intern() to sys.intern().
|
||||
|
||||
- exec is now a function.
|
||||
|
|
|
@ -854,7 +854,7 @@ VALIDATER(node); VALIDATER(small_stmt);
|
|||
VALIDATER(class); VALIDATER(node);
|
||||
VALIDATER(parameters); VALIDATER(suite);
|
||||
VALIDATER(testlist); VALIDATER(varargslist);
|
||||
VALIDATER(fpdef); VALIDATER(fplist);
|
||||
VALIDATER(vfpdef); VALIDATER(vfplist);
|
||||
VALIDATER(stmt); VALIDATER(simple_stmt);
|
||||
VALIDATER(expr_stmt); VALIDATER(power);
|
||||
VALIDATER(print_stmt); VALIDATER(del_stmt);
|
||||
|
@ -863,7 +863,7 @@ VALIDATER(raise_stmt); VALIDATER(import_stmt);
|
|||
VALIDATER(import_name); VALIDATER(import_from);
|
||||
VALIDATER(global_stmt); VALIDATER(list_if);
|
||||
VALIDATER(assert_stmt); VALIDATER(list_for);
|
||||
VALIDATER(compound_stmt);
|
||||
VALIDATER(compound_stmt); VALIDATER(vname);
|
||||
VALIDATER(while); VALIDATER(for);
|
||||
VALIDATER(try); VALIDATER(except_clause);
|
||||
VALIDATER(test); VALIDATER(and_test);
|
||||
|
@ -1120,7 +1120,32 @@ validate_testlist_safe(node *tree)
|
|||
}
|
||||
|
||||
|
||||
/* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||
/* validate either vname or tname.
|
||||
* vname: NAME
|
||||
* tname: NAME [':' test]
|
||||
*/
|
||||
static int
|
||||
validate_vname(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
if (TYPE(tree) == vname) {
|
||||
return nch == 1 && validate_name(CHILD(tree, 0), NULL);
|
||||
}
|
||||
else if (TYPE(tree) == tname) {
|
||||
if (nch == 1) {
|
||||
return validate_name(CHILD(tree, 0), NULL);
|
||||
}
|
||||
else if (nch == 3) {
|
||||
return validate_name(CHILD(tree, 0), NULL) &&
|
||||
validate_colon(CHILD(tree, 1)) &&
|
||||
validate_test(CHILD(tree, 2));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* '*' vname (',' vname ['=' test])* [',' '**' vname] | '**' vname
|
||||
* ..or tname in place of vname. vname: NAME; tname: NAME [':' test]
|
||||
*/
|
||||
static int
|
||||
validate_varargslist_trailer(node *tree, int start)
|
||||
|
@ -1136,26 +1161,27 @@ validate_varargslist_trailer(node *tree, int start)
|
|||
sym = TYPE(CHILD(tree, start));
|
||||
if (sym == STAR) {
|
||||
/*
|
||||
* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||
* '*' vname (',' vname ['=' test])* [',' '**' vname] | '**' vname
|
||||
*/
|
||||
if (nch-start == 2)
|
||||
res = validate_name(CHILD(tree, start+1), NULL);
|
||||
res = validate_vname(CHILD(tree, start+1));
|
||||
else if (nch-start == 5 && TYPE(CHILD(tree, start+2)) == COMMA)
|
||||
res = (validate_name(CHILD(tree, start+1), NULL)
|
||||
res = (validate_vname(CHILD(tree, start+1))
|
||||
&& validate_comma(CHILD(tree, start+2))
|
||||
&& validate_doublestar(CHILD(tree, start+3))
|
||||
&& validate_name(CHILD(tree, start+4), NULL));
|
||||
&& validate_vname(CHILD(tree, start+4)));
|
||||
else {
|
||||
/* skip over [NAME] (',' NAME ['=' test])* */
|
||||
/* skip over vname (',' vname ['=' test])* */
|
||||
i = start + 1;
|
||||
if (TYPE(CHILD(tree, i)) == NAME) { /* skip over [NAME] */
|
||||
if (TYPE(CHILD(tree, i)) == vname ||
|
||||
TYPE(CHILD(tree, i)) == tname) { /* skip over vname or tname */
|
||||
i += 1;
|
||||
}
|
||||
while (res && i+1 < nch) { /* validate (',' NAME ['=' test])* */
|
||||
while (res && i+1 < nch) { /* validate (',' vname ['=' test])* */
|
||||
res = validate_comma(CHILD(tree, i));
|
||||
if (TYPE(CHILD(tree, i+1)) == DOUBLESTAR)
|
||||
break;
|
||||
res = res && validate_name(CHILD(tree, i+1), NULL);
|
||||
res = res && validate_vname(CHILD(tree, i+1));
|
||||
if (res && i+2 < nch && TYPE(CHILD(tree, i+2)) == EQUAL) {
|
||||
res = res && (i+3 < nch)
|
||||
&& validate_test(CHILD(tree, i+3));
|
||||
|
@ -1165,9 +1191,9 @@ validate_varargslist_trailer(node *tree, int start)
|
|||
i += 2;
|
||||
}
|
||||
}
|
||||
/* [',' '**' NAME] */
|
||||
/* [',' '**' vname] */
|
||||
if (res && i+1 < nch && TYPE(CHILD(tree, i+1)) == DOUBLESTAR) {
|
||||
res = validate_name(CHILD(tree, i+2), NULL);
|
||||
res = validate_vname(CHILD(tree, i+2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1176,7 +1202,7 @@ validate_varargslist_trailer(node *tree, int start)
|
|||
* '**' NAME
|
||||
*/
|
||||
if (nch-start == 2)
|
||||
res = validate_name(CHILD(tree, start+1), NULL);
|
||||
res = validate_vname(CHILD(tree, start+1));
|
||||
}
|
||||
if (!res)
|
||||
err_string("illegal variable argument trailer for varargslist");
|
||||
|
@ -1186,19 +1212,32 @@ validate_varargslist_trailer(node *tree, int start)
|
|||
|
||||
/* validate_varargslist()
|
||||
*
|
||||
* varargslist:
|
||||
* (fpdef ['=' test] ',')*
|
||||
* ('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
* Validate typedargslist or varargslist.
|
||||
*
|
||||
* typedargslist: ((tfpdef ['=' test] ',')*
|
||||
* ('*' [tname] (',' tname ['=' test])* [',' '**' tname] |
|
||||
* '**' tname)
|
||||
* | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
* tname: NAME [':' test]
|
||||
* tfpdef: tname | '(' tfplist ')'
|
||||
* tfplist: tfpdef (',' tfpdef)* [',']
|
||||
* varargslist: ((vfpdef ['=' test] ',')*
|
||||
* ('*' [vname] (',' vname ['=' test])* [',' '**' vname] |
|
||||
* '**' vname)
|
||||
* | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
|
||||
* vname: NAME
|
||||
* vfpdef: vname | '(' vfplist ')'
|
||||
* vfplist: vfpdef (',' vfpdef)* [',']
|
||||
*
|
||||
*/
|
||||
static int
|
||||
validate_varargslist(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res = validate_ntype(tree, varargslist) && (nch != 0);
|
||||
int res = (TYPE(tree) == varargslist ||
|
||||
TYPE(tree) == typedargslist) &&
|
||||
(nch != 0);
|
||||
int sym;
|
||||
|
||||
if (!res)
|
||||
return 0;
|
||||
if (nch < 1) {
|
||||
|
@ -1211,19 +1250,19 @@ validate_varargslist(node *tree)
|
|||
* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||
*/
|
||||
res = validate_varargslist_trailer(tree, 0);
|
||||
else if (sym == fpdef) {
|
||||
else if (sym == vfpdef || sym == tfpdef) {
|
||||
int i = 0;
|
||||
|
||||
sym = TYPE(CHILD(tree, nch-1));
|
||||
if (sym == NAME) {
|
||||
if (sym == vname || sym == tname) {
|
||||
/*
|
||||
* (fpdef ['=' test] ',')+
|
||||
* ('*' NAME [',' '**' NAME]
|
||||
* | '**' NAME)
|
||||
* (vfpdef ['=' test] ',')+
|
||||
* ('*' vname [',' '**' vname]
|
||||
* | '**' vname)
|
||||
*/
|
||||
/* skip over (fpdef ['=' test] ',')+ */
|
||||
/* skip over (vfpdef ['=' test] ',')+ */
|
||||
while (res && (i+2 <= nch)) {
|
||||
res = validate_fpdef(CHILD(tree, i));
|
||||
res = validate_vfpdef(CHILD(tree, i));
|
||||
++i;
|
||||
if (res && TYPE(CHILD(tree, i)) == EQUAL && (i+2 <= nch)) {
|
||||
res = (validate_equal(CHILD(tree, i))
|
||||
|
@ -1248,7 +1287,7 @@ validate_varargslist(node *tree)
|
|||
}
|
||||
else {
|
||||
/*
|
||||
* fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
* vfpdef ['=' test] (',' vfpdef ['=' test])* [',']
|
||||
*/
|
||||
/* strip trailing comma node */
|
||||
if (sym == COMMA) {
|
||||
|
@ -1258,9 +1297,9 @@ validate_varargslist(node *tree)
|
|||
--nch;
|
||||
}
|
||||
/*
|
||||
* fpdef ['=' test] (',' fpdef ['=' test])*
|
||||
* vfpdef ['=' test] (',' vfpdef ['=' test])*
|
||||
*/
|
||||
res = validate_fpdef(CHILD(tree, 0));
|
||||
res = validate_vfpdef(CHILD(tree, 0));
|
||||
++i;
|
||||
if (res && (i+2 <= nch) && TYPE(CHILD(tree, i)) == EQUAL) {
|
||||
res = (validate_equal(CHILD(tree, i))
|
||||
|
@ -1268,12 +1307,12 @@ validate_varargslist(node *tree)
|
|||
i += 2;
|
||||
}
|
||||
/*
|
||||
* ... (',' fpdef ['=' test])*
|
||||
* ... (',' vfpdef ['=' test])*
|
||||
* i ---^^^
|
||||
*/
|
||||
while (res && (nch - i) >= 2) {
|
||||
res = (validate_comma(CHILD(tree, i))
|
||||
&& validate_fpdef(CHILD(tree, i+1)));
|
||||
&& validate_vfpdef(CHILD(tree, i+1)));
|
||||
i += 2;
|
||||
if (res && (nch - i) >= 2 && TYPE(CHILD(tree, i)) == EQUAL) {
|
||||
res = (validate_equal(CHILD(tree, i))
|
||||
|
@ -1405,24 +1444,32 @@ validate_gen_if(node *tree)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* validate_fpdef()
|
||||
/* validate_vfpdef()
|
||||
*
|
||||
* Validate vfpdef or tfpdef.
|
||||
*
|
||||
* vname: NAME
|
||||
* vfpdef: vname | '(' vfplist ')'
|
||||
* vfplist: vfpdef (',' vfpdef)* [',']
|
||||
*
|
||||
* tname: NAME [':' test]
|
||||
* tfpdef: tname | '(' tfplist ')'
|
||||
* tfplist: tfpdef (',' tfpdef)* [',']
|
||||
*
|
||||
* fpdef:
|
||||
* NAME
|
||||
* | '(' fplist ')'
|
||||
*/
|
||||
static int
|
||||
validate_fpdef(node *tree)
|
||||
validate_vfpdef(node *tree)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res = validate_ntype(tree, fpdef);
|
||||
int typ = TYPE(tree);
|
||||
int res = typ == vfpdef || typ == tfpdef;
|
||||
|
||||
if (res) {
|
||||
if (nch == 1)
|
||||
res = validate_ntype(CHILD(tree, 0), NAME);
|
||||
res = validate_vname(CHILD(tree, 0));
|
||||
else if (nch == 3)
|
||||
res = (validate_lparen(CHILD(tree, 0))
|
||||
&& validate_fplist(CHILD(tree, 1))
|
||||
&& validate_vfplist(CHILD(tree, 1))
|
||||
&& validate_rparen(CHILD(tree, 2)));
|
||||
else
|
||||
res = validate_numnodes(tree, 1, "fpdef");
|
||||
|
@ -1432,10 +1479,10 @@ validate_fpdef(node *tree)
|
|||
|
||||
|
||||
static int
|
||||
validate_fplist(node *tree)
|
||||
validate_vfplist(node *tree)
|
||||
{
|
||||
return (validate_repeating_list(tree, fplist,
|
||||
validate_fpdef, "fplist"));
|
||||
return (validate_repeating_list(tree, vfplist,
|
||||
validate_vfpdef, "vfplist"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ PyFunction_New(PyObject *code, PyObject *globals)
|
|||
op->func_doc = doc;
|
||||
op->func_dict = NULL;
|
||||
op->func_module = NULL;
|
||||
op->func_annotations = NULL;
|
||||
|
||||
/* __module__: If module name is in globals, use it.
|
||||
Otherwise, use None.
|
||||
|
@ -187,6 +188,38 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure)
|
|||
return 0;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyFunction_GetAnnotations(PyObject *op)
|
||||
{
|
||||
if (!PyFunction_Check(op)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
return ((PyFunctionObject *) op) -> func_annotations;
|
||||
}
|
||||
|
||||
int
|
||||
PyFunction_SetAnnotations(PyObject *op, PyObject *annotations)
|
||||
{
|
||||
if (!PyFunction_Check(op)) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
if (annotations == Py_None)
|
||||
annotations = NULL;
|
||||
else if (annotations && PyDict_Check(annotations)) {
|
||||
Py_INCREF(annotations);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"non-dict annotations");
|
||||
return -1;
|
||||
}
|
||||
Py_XDECREF(((PyFunctionObject *)op) -> func_annotations);
|
||||
((PyFunctionObject *) op) -> func_annotations = annotations;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
#define OFF(x) offsetof(PyFunctionObject, x)
|
||||
|
@ -395,12 +428,48 @@ func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
func_get_annotations(PyFunctionObject *op)
|
||||
{
|
||||
if (op->func_annotations == NULL) {
|
||||
op->func_annotations = PyDict_New();
|
||||
if (op->func_annotations == NULL)
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(op->func_annotations);
|
||||
return op->func_annotations;
|
||||
}
|
||||
|
||||
static int
|
||||
func_set_annotations(PyFunctionObject *op, PyObject *value)
|
||||
{
|
||||
PyObject *tmp;
|
||||
|
||||
if (value == Py_None)
|
||||
value = NULL;
|
||||
/* Legal to del f.func_annotations.
|
||||
* Can only set func_annotations to NULL (through C api)
|
||||
* or a dict. */
|
||||
if (value != NULL && !PyDict_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"func_annotations must be set to a dict object");
|
||||
return -1;
|
||||
}
|
||||
tmp = op->func_annotations;
|
||||
Py_XINCREF(value);
|
||||
op->func_annotations = value;
|
||||
Py_XDECREF(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyGetSetDef func_getsetlist[] = {
|
||||
{"func_code", (getter)func_get_code, (setter)func_set_code},
|
||||
{"func_defaults", (getter)func_get_defaults,
|
||||
(setter)func_set_defaults},
|
||||
{"func_kwdefaults", (getter)func_get_kwdefaults,
|
||||
(setter)func_set_kwdefaults},
|
||||
{"func_annotations", (getter)func_get_annotations,
|
||||
(setter)func_set_annotations},
|
||||
{"func_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},
|
||||
|
@ -524,6 +593,7 @@ func_dealloc(PyFunctionObject *op)
|
|||
Py_XDECREF(op->func_doc);
|
||||
Py_XDECREF(op->func_dict);
|
||||
Py_XDECREF(op->func_closure);
|
||||
Py_XDECREF(op->func_annotations);
|
||||
PyObject_GC_Del(op);
|
||||
}
|
||||
|
||||
|
@ -546,6 +616,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
|
|||
Py_VISIT(f->func_name);
|
||||
Py_VISIT(f->func_dict);
|
||||
Py_VISIT(f->func_closure);
|
||||
Py_VISIT(f->func_annotations);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ module Python version "$Revision$"
|
|||
| Suite(stmt* body)
|
||||
|
||||
stmt = FunctionDef(identifier name, arguments args,
|
||||
stmt* body, expr* decorators)
|
||||
stmt* body, expr* decorators, expr? returns)
|
||||
| ClassDef(identifier name, expr* bases, stmt* body)
|
||||
| Return(expr? value)
|
||||
|
||||
|
@ -100,8 +100,12 @@ module Python version "$Revision$"
|
|||
excepthandler = (expr? type, expr? name, stmt* body, int lineno,
|
||||
int col_offset)
|
||||
|
||||
arguments = (expr* args, identifier? vararg, expr* kwonlyargs,
|
||||
identifier? kwarg, expr* defaults, expr* kw_defaults)
|
||||
arguments = (arg* args, identifier? vararg, expr? varargannotation,
|
||||
arg* kwonlyargs, identifier? kwarg,
|
||||
expr? kwargannotation, expr* defaults,
|
||||
expr* kw_defaults)
|
||||
arg = SimpleArg(identifier arg, expr? annotation)
|
||||
| NestedArgs(arg* args)
|
||||
|
||||
-- keyword arguments supplied to call
|
||||
keyword = (identifier arg, expr value)
|
||||
|
|
|
@ -92,6 +92,7 @@ char *_PyParser_TokenNames[] = {
|
|||
"DOUBLESLASH",
|
||||
"DOUBLESLASHEQUAL",
|
||||
"AT",
|
||||
"RARROW",
|
||||
/* This table must match the #defines in token.h! */
|
||||
"OP",
|
||||
"<ERRORTOKEN>",
|
||||
|
@ -998,6 +999,7 @@ PyToken_TwoChars(int c1, int c2)
|
|||
case '-':
|
||||
switch (c2) {
|
||||
case '=': return MINEQUAL;
|
||||
case '>': return RARROW;
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
|
|
|
@ -34,6 +34,7 @@ static char *FunctionDef_fields[]={
|
|||
"args",
|
||||
"body",
|
||||
"decorators",
|
||||
"returns",
|
||||
};
|
||||
static PyTypeObject *ClassDef_type;
|
||||
static char *ClassDef_fields[]={
|
||||
|
@ -333,11 +334,24 @@ static PyObject* ast2obj_arguments(void*);
|
|||
static char *arguments_fields[]={
|
||||
"args",
|
||||
"vararg",
|
||||
"varargannotation",
|
||||
"kwonlyargs",
|
||||
"kwarg",
|
||||
"kwargannotation",
|
||||
"defaults",
|
||||
"kw_defaults",
|
||||
};
|
||||
static PyTypeObject *arg_type;
|
||||
static PyObject* ast2obj_arg(void*);
|
||||
static PyTypeObject *SimpleArg_type;
|
||||
static char *SimpleArg_fields[]={
|
||||
"arg",
|
||||
"annotation",
|
||||
};
|
||||
static PyTypeObject *NestedArgs_type;
|
||||
static char *NestedArgs_fields[]={
|
||||
"args",
|
||||
};
|
||||
static PyTypeObject *keyword_type;
|
||||
static PyObject* ast2obj_keyword(void*);
|
||||
static char *keyword_fields[]={
|
||||
|
@ -454,7 +468,7 @@ static int init_types(void)
|
|||
if (!stmt_type) return 0;
|
||||
if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0;
|
||||
FunctionDef_type = make_type("FunctionDef", stmt_type,
|
||||
FunctionDef_fields, 4);
|
||||
FunctionDef_fields, 5);
|
||||
if (!FunctionDef_type) return 0;
|
||||
ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 3);
|
||||
if (!ClassDef_type) return 0;
|
||||
|
@ -710,8 +724,16 @@ static int init_types(void)
|
|||
excepthandler_type = make_type("excepthandler", AST_type,
|
||||
excepthandler_fields, 5);
|
||||
if (!excepthandler_type) return 0;
|
||||
arguments_type = make_type("arguments", AST_type, arguments_fields, 6);
|
||||
arguments_type = make_type("arguments", AST_type, arguments_fields, 8);
|
||||
if (!arguments_type) return 0;
|
||||
arg_type = make_type("arg", AST_type, NULL, 0);
|
||||
if (!arg_type) return 0;
|
||||
if (!add_attributes(arg_type, NULL, 0)) return 0;
|
||||
SimpleArg_type = make_type("SimpleArg", arg_type, SimpleArg_fields, 2);
|
||||
if (!SimpleArg_type) return 0;
|
||||
NestedArgs_type = make_type("NestedArgs", arg_type, NestedArgs_fields,
|
||||
1);
|
||||
if (!NestedArgs_type) return 0;
|
||||
keyword_type = make_type("keyword", AST_type, keyword_fields, 2);
|
||||
if (!keyword_type) return 0;
|
||||
alias_type = make_type("alias", AST_type, alias_fields, 2);
|
||||
|
@ -783,7 +805,8 @@ Suite(asdl_seq * body, PyArena *arena)
|
|||
|
||||
stmt_ty
|
||||
FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
|
||||
decorators, int lineno, int col_offset, PyArena *arena)
|
||||
decorators, expr_ty returns, int lineno, int col_offset, PyArena
|
||||
*arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
if (!name) {
|
||||
|
@ -806,6 +829,7 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
|
|||
p->v.FunctionDef.args = args;
|
||||
p->v.FunctionDef.body = body;
|
||||
p->v.FunctionDef.decorators = decorators;
|
||||
p->v.FunctionDef.returns = returns;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
|
@ -1830,8 +1854,9 @@ excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int
|
|||
}
|
||||
|
||||
arguments_ty
|
||||
arguments(asdl_seq * args, identifier vararg, asdl_seq * kwonlyargs, identifier
|
||||
kwarg, asdl_seq * defaults, asdl_seq * kw_defaults, PyArena *arena)
|
||||
arguments(asdl_seq * args, identifier vararg, expr_ty varargannotation,
|
||||
asdl_seq * kwonlyargs, identifier kwarg, expr_ty kwargannotation,
|
||||
asdl_seq * defaults, asdl_seq * kw_defaults, PyArena *arena)
|
||||
{
|
||||
arguments_ty p;
|
||||
p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
|
@ -1841,13 +1866,49 @@ arguments(asdl_seq * args, identifier vararg, asdl_seq * kwonlyargs, identifier
|
|||
}
|
||||
p->args = args;
|
||||
p->vararg = vararg;
|
||||
p->varargannotation = varargannotation;
|
||||
p->kwonlyargs = kwonlyargs;
|
||||
p->kwarg = kwarg;
|
||||
p->kwargannotation = kwargannotation;
|
||||
p->defaults = defaults;
|
||||
p->kw_defaults = kw_defaults;
|
||||
return p;
|
||||
}
|
||||
|
||||
arg_ty
|
||||
SimpleArg(identifier arg, expr_ty annotation, PyArena *arena)
|
||||
{
|
||||
arg_ty p;
|
||||
if (!arg) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"field arg is required for SimpleArg");
|
||||
return NULL;
|
||||
}
|
||||
p = (arg_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
p->kind = SimpleArg_kind;
|
||||
p->v.SimpleArg.arg = arg;
|
||||
p->v.SimpleArg.annotation = annotation;
|
||||
return p;
|
||||
}
|
||||
|
||||
arg_ty
|
||||
NestedArgs(asdl_seq * args, PyArena *arena)
|
||||
{
|
||||
arg_ty p;
|
||||
p = (arg_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
p->kind = NestedArgs_kind;
|
||||
p->v.NestedArgs.args = args;
|
||||
return p;
|
||||
}
|
||||
|
||||
keyword_ty
|
||||
keyword(identifier arg, expr_ty value, PyArena *arena)
|
||||
{
|
||||
|
@ -1981,6 +2042,11 @@ ast2obj_stmt(void* _o)
|
|||
if (PyObject_SetAttrString(result, "decorators", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_expr(o->v.FunctionDef.returns);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "returns", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case ClassDef_kind:
|
||||
result = PyType_GenericNew(ClassDef_type, NULL, NULL);
|
||||
|
@ -2901,7 +2967,7 @@ ast2obj_arguments(void* _o)
|
|||
|
||||
result = PyType_GenericNew(arguments_type, NULL, NULL);
|
||||
if (!result) return NULL;
|
||||
value = ast2obj_list(o->args, ast2obj_expr);
|
||||
value = ast2obj_list(o->args, ast2obj_arg);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "args", value) == -1)
|
||||
goto failed;
|
||||
|
@ -2911,7 +2977,12 @@ ast2obj_arguments(void* _o)
|
|||
if (PyObject_SetAttrString(result, "vararg", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->kwonlyargs, ast2obj_expr);
|
||||
value = ast2obj_expr(o->varargannotation);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "varargannotation", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->kwonlyargs, ast2obj_arg);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "kwonlyargs", value) == -1)
|
||||
goto failed;
|
||||
|
@ -2921,6 +2992,11 @@ ast2obj_arguments(void* _o)
|
|||
if (PyObject_SetAttrString(result, "kwarg", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_expr(o->kwargannotation);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "kwargannotation", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->defaults, ast2obj_expr);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "defaults", value) == -1)
|
||||
|
@ -2938,6 +3014,48 @@ failed:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
ast2obj_arg(void* _o)
|
||||
{
|
||||
arg_ty o = (arg_ty)_o;
|
||||
PyObject *result = NULL, *value = NULL;
|
||||
if (!o) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
switch (o->kind) {
|
||||
case SimpleArg_kind:
|
||||
result = PyType_GenericNew(SimpleArg_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
value = ast2obj_identifier(o->v.SimpleArg.arg);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "arg", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_expr(o->v.SimpleArg.annotation);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "annotation", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case NestedArgs_kind:
|
||||
result = PyType_GenericNew(NestedArgs_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
value = ast2obj_list(o->v.NestedArgs.args, ast2obj_arg);
|
||||
if (!value) goto failed;
|
||||
if (PyObject_SetAttrString(result, "args", value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
failed:
|
||||
Py_XDECREF(value);
|
||||
Py_XDECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
ast2obj_keyword(void* _o)
|
||||
{
|
||||
|
@ -3008,7 +3126,7 @@ init_ast(void)
|
|||
if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return;
|
||||
if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)
|
||||
return;
|
||||
if (PyModule_AddStringConstant(m, "__version__", "51773") < 0)
|
||||
if (PyModule_AddStringConstant(m, "__version__", "52491") < 0)
|
||||
return;
|
||||
if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return;
|
||||
if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0)
|
||||
|
@ -3146,6 +3264,11 @@ init_ast(void)
|
|||
(PyObject*)excepthandler_type) < 0) return;
|
||||
if (PyDict_SetItemString(d, "arguments", (PyObject*)arguments_type) <
|
||||
0) return;
|
||||
if (PyDict_SetItemString(d, "arg", (PyObject*)arg_type) < 0) return;
|
||||
if (PyDict_SetItemString(d, "SimpleArg", (PyObject*)SimpleArg_type) <
|
||||
0) return;
|
||||
if (PyDict_SetItemString(d, "NestedArgs", (PyObject*)NestedArgs_type) <
|
||||
0) return;
|
||||
if (PyDict_SetItemString(d, "keyword", (PyObject*)keyword_type) < 0)
|
||||
return;
|
||||
if (PyDict_SetItemString(d, "alias", (PyObject*)alias_type) < 0) return;
|
||||
|
|
259
Python/ast.c
259
Python/ast.c
|
@ -553,59 +553,74 @@ seq_for_testlist(struct compiling *c, const node *n)
|
|||
return seq;
|
||||
}
|
||||
|
||||
static expr_ty
|
||||
static arg_ty
|
||||
compiler_simple_arg(struct compiling *c, const node *n)
|
||||
{
|
||||
identifier name;
|
||||
expr_ty annotation = NULL;
|
||||
node *ch;
|
||||
|
||||
assert(TYPE(n) == tname || TYPE(n) == vname);
|
||||
ch = CHILD(n, 0);
|
||||
if (!strcmp(STR(ch), "None")) {
|
||||
ast_error(ch, "assignment to None");
|
||||
return NULL;
|
||||
}
|
||||
name = NEW_IDENTIFIER(ch);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (NCH(n) == 3 && TYPE(CHILD(n, 1)) == COLON) {
|
||||
annotation = ast_for_expr(c, CHILD(n, 2));
|
||||
if (!annotation)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return SimpleArg(name, annotation, c->c_arena);
|
||||
}
|
||||
|
||||
static arg_ty
|
||||
compiler_complex_args(struct compiling *c, const node *n)
|
||||
{
|
||||
int i, len = (NCH(n) + 1) / 2;
|
||||
expr_ty result;
|
||||
arg_ty arg;
|
||||
asdl_seq *args = asdl_seq_new(len, c->c_arena);
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
/* fpdef: NAME | '(' fplist ')'
|
||||
fplist: fpdef (',' fpdef)* [',']
|
||||
*/
|
||||
REQ(n, fplist);
|
||||
assert(TYPE(n) == tfplist || TYPE(n) == vfplist);
|
||||
for (i = 0; i < len; i++) {
|
||||
const node *fpdef_node = CHILD(n, 2*i);
|
||||
const node *child;
|
||||
expr_ty arg;
|
||||
set_name:
|
||||
/* fpdef_node is either a NAME or an fplist */
|
||||
child = CHILD(fpdef_node, 0);
|
||||
if (TYPE(child) == NAME) {
|
||||
if (!strcmp(STR(child), "None")) {
|
||||
ast_error(child, "assignment to None");
|
||||
const node *child = CHILD(n, 2*i);
|
||||
/* def foo(((x), y)): -- x is not nested complex, special case. */
|
||||
while (NCH(child) == 3 && NCH(CHILD(child, 1)) == 1)
|
||||
child = CHILD(CHILD(child, 1), 0);
|
||||
|
||||
/* child either holds a tname or '(', a tfplist, ')' */
|
||||
switch (TYPE(CHILD(child, 0))) {
|
||||
case tname:
|
||||
case vname:
|
||||
arg = compiler_simple_arg(c, CHILD(child, 0));
|
||||
break;
|
||||
case LPAR:
|
||||
arg = compiler_complex_args(c, CHILD(child, 1));
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"unexpected node in args: %d @ %d",
|
||||
TYPE(CHILD(child, 0)), i);
|
||||
arg = NULL;
|
||||
}
|
||||
if (!arg)
|
||||
return NULL;
|
||||
}
|
||||
arg = Name(NEW_IDENTIFIER(child), Store, LINENO(child),
|
||||
child->n_col_offset, c->c_arena);
|
||||
}
|
||||
else {
|
||||
assert(TYPE(fpdef_node) == fpdef);
|
||||
/* fpdef_node[0] is not a name, so it must be a '(', get CHILD[1] */
|
||||
child = CHILD(fpdef_node, 1);
|
||||
assert(TYPE(child) == fplist);
|
||||
/* NCH == 1 means we have (x), we need to elide the extra parens */
|
||||
if (NCH(child) == 1) {
|
||||
fpdef_node = CHILD(child, 0);
|
||||
assert(TYPE(fpdef_node) == fpdef);
|
||||
goto set_name;
|
||||
}
|
||||
arg = compiler_complex_args(c, child);
|
||||
}
|
||||
asdl_seq_SET(args, i, arg);
|
||||
}
|
||||
|
||||
result = Tuple(args, Store, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
if (!set_context(result, Store, n))
|
||||
return NULL;
|
||||
return result;
|
||||
return NestedArgs(args, c->c_arena);
|
||||
}
|
||||
|
||||
/* returns -1 if failed to handle keyword only arguments
|
||||
returns new position to keep processing if successful
|
||||
(',' NAME ['=' test])*
|
||||
(',' tname ['=' test])*
|
||||
^^^
|
||||
start pointing here
|
||||
*/
|
||||
|
@ -614,7 +629,8 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
|
|||
asdl_seq *kwonlyargs, asdl_seq *kwdefaults)
|
||||
{
|
||||
node *ch;
|
||||
expr_ty name;
|
||||
expr_ty expression, annotation;
|
||||
arg_ty arg;
|
||||
int i = start;
|
||||
int j = 0; /* index for kwdefaults and kwonlyargs */
|
||||
assert(kwonlyargs != NULL);
|
||||
|
@ -622,9 +638,10 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
|
|||
while (i < NCH(n)) {
|
||||
ch = CHILD(n, i);
|
||||
switch (TYPE(ch)) {
|
||||
case NAME:
|
||||
case vname:
|
||||
case tname:
|
||||
if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
|
||||
expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));
|
||||
expression = ast_for_expr(c, CHILD(n, i + 2));
|
||||
if (!expression) {
|
||||
ast_error(ch, "assignment to None");
|
||||
goto error;
|
||||
|
@ -635,18 +652,28 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
|
|||
else { /* setting NULL if no default value exists */
|
||||
asdl_seq_SET(kwdefaults, j, NULL);
|
||||
}
|
||||
if (NCH(ch) == 3) {
|
||||
/* ch is NAME ':' test */
|
||||
annotation = ast_for_expr(c, CHILD(ch, 2));
|
||||
if (!annotation) {
|
||||
ast_error(ch, "expected expression");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
annotation = NULL;
|
||||
}
|
||||
ch = CHILD(ch, 0);
|
||||
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) {
|
||||
arg = SimpleArg(NEW_IDENTIFIER(ch), annotation, c->c_arena);
|
||||
if (!arg) {
|
||||
ast_error(ch, "expecting name");
|
||||
goto error;
|
||||
}
|
||||
asdl_seq_SET(kwonlyargs, j++, name);
|
||||
asdl_seq_SET(kwonlyargs, j++, arg);
|
||||
i += 2; /* the name and the comma */
|
||||
break;
|
||||
case DOUBLESTAR:
|
||||
|
@ -666,29 +693,41 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
|
|||
static arguments_ty
|
||||
ast_for_arguments(struct compiling *c, const node *n)
|
||||
{
|
||||
/* parameters: '(' [varargslist] ')'
|
||||
varargslist: (fpdef ['=' test] ',')*
|
||||
('*' [NAME] (',' fpdef ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||
| fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
/* This function handles both typedargslist (function definition)
|
||||
and varargslist (lambda definition).
|
||||
|
||||
parameters: '(' [typedargslist] ')'
|
||||
typedargslist: ((tfpdef ['=' test] ',')*
|
||||
('*' [tname] (',' tname ['=' test])* [',' '**' tname]
|
||||
| '**' tname)
|
||||
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
varargslist: ((vfpdef ['=' test] ',')*
|
||||
('*' [vname] (',' vname ['=' test])* [',' '**' vname]
|
||||
| '**' vname)
|
||||
| vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
|
||||
*/
|
||||
int i, j, k, nposargs = 0, nkwonlyargs = 0;
|
||||
int nposdefaults = 0, found_default = 0;
|
||||
asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults;
|
||||
identifier vararg = NULL, kwarg = NULL;
|
||||
arg_ty arg;
|
||||
expr_ty varargannotation = NULL, kwargannotation = NULL;
|
||||
node *ch;
|
||||
|
||||
if (TYPE(n) == parameters) {
|
||||
if (NCH(n) == 2) /* () as argument list */
|
||||
return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||
return arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, c->c_arena);
|
||||
n = CHILD(n, 1);
|
||||
}
|
||||
REQ(n, varargslist);
|
||||
assert(TYPE(n) == typedargslist || TYPE(n) == varargslist);
|
||||
|
||||
/* first count the number of positional args & defaults */
|
||||
for (i = 0; i < NCH(n); i++) {
|
||||
ch = CHILD(n, i);
|
||||
if (TYPE(ch) == STAR) {
|
||||
if (TYPE(CHILD(n, i+1)) == NAME) {
|
||||
if (TYPE(CHILD(n, i+1)) == tname
|
||||
|| TYPE(CHILD(n, i+1)) == vname) {
|
||||
/* skip NAME of vararg */
|
||||
/* so that following can count only keyword only args */
|
||||
i += 2;
|
||||
|
@ -698,7 +737,7 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (TYPE(ch) == fpdef) nposargs++;
|
||||
if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++;
|
||||
if (TYPE(ch) == EQUAL) nposdefaults++;
|
||||
}
|
||||
/* count the number of keyword only args &
|
||||
|
@ -706,35 +745,39 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
for ( ; i < NCH(n); ++i) {
|
||||
ch = CHILD(n, i);
|
||||
if (TYPE(ch) == DOUBLESTAR) break;
|
||||
if (TYPE(ch) == NAME) nkwonlyargs++;
|
||||
if (TYPE(ch) == tname || TYPE(ch) == vname) 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 */
|
||||
goto error;
|
||||
kwonlyargs = (nkwonlyargs ?
|
||||
asdl_seq_new(nkwonlyargs, c->c_arena) : NULL);
|
||||
if (!kwonlyargs && nkwonlyargs)
|
||||
return NULL; /* Don't need to goto error; no objects allocated */
|
||||
goto error;
|
||||
posdefaults = (nposdefaults ?
|
||||
asdl_seq_new(nposdefaults, c->c_arena) : NULL);
|
||||
if (!posdefaults && nposdefaults)
|
||||
return NULL; /* Don't need to goto error; no objects allocated */
|
||||
goto error;
|
||||
/* 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 */
|
||||
goto error;
|
||||
|
||||
if (nposargs + nkwonlyargs > 255) {
|
||||
ast_error(n, "more than 255 arguments");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fpdef: NAME | '(' fplist ')'
|
||||
fplist: fpdef (',' fpdef)* [',']
|
||||
/* tname: NAME [':' test]
|
||||
tfpdef: tname | '(' tfplist ')'
|
||||
tfplist: tfpdef (',' tfpdef)* [',']
|
||||
vname: NAME
|
||||
vfpdef: NAME | '(' vfplist ')'
|
||||
vfplist: vfpdef (',' vfpdef)* [',']
|
||||
*/
|
||||
i = 0;
|
||||
j = 0; /* index for defaults */
|
||||
|
@ -742,8 +785,8 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
while (i < NCH(n)) {
|
||||
ch = CHILD(n, i);
|
||||
switch (TYPE(ch)) {
|
||||
case fpdef:
|
||||
handle_fpdef:
|
||||
case tfpdef:
|
||||
case vfpdef:
|
||||
/* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is
|
||||
anything other than EQUAL or a comma? */
|
||||
/* XXX Should NCH(n) check be made a separate check? */
|
||||
|
@ -753,7 +796,6 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
goto error;
|
||||
assert(posdefaults != NULL);
|
||||
asdl_seq_SET(posdefaults, j++, expression);
|
||||
|
||||
i += 2;
|
||||
found_default = 1;
|
||||
}
|
||||
|
@ -762,36 +804,18 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
"non-default argument follows default argument");
|
||||
goto error;
|
||||
}
|
||||
if (NCH(ch) == 3) {
|
||||
ch = CHILD(ch, 1);
|
||||
/* def foo((x)): is not complex, special case. */
|
||||
if (NCH(ch) != 1) {
|
||||
/* We have complex arguments, setup for unpacking. */
|
||||
asdl_seq_SET(posargs, k++,
|
||||
compiler_complex_args(c, ch));
|
||||
} else {
|
||||
/* def foo((x)): setup for checking NAME below. */
|
||||
/* Loop because there can be many parens and tuple
|
||||
unpacking mixed in. */
|
||||
ch = CHILD(ch, 0);
|
||||
assert(TYPE(ch) == fpdef);
|
||||
goto handle_fpdef;
|
||||
}
|
||||
}
|
||||
if (TYPE(CHILD(ch, 0)) == NAME) {
|
||||
expr_ty name;
|
||||
if (!strcmp(STR(CHILD(ch, 0)), "None")) {
|
||||
ast_error(CHILD(ch, 0), "assignment to None");
|
||||
goto error;
|
||||
}
|
||||
name = Name(NEW_IDENTIFIER(CHILD(ch, 0)),
|
||||
Param, LINENO(ch), ch->n_col_offset,
|
||||
c->c_arena);
|
||||
if (!name)
|
||||
goto error;
|
||||
asdl_seq_SET(posargs, k++, name);
|
||||
while (NCH(ch) == 3 && NCH(CHILD(ch, 1)) == 1)
|
||||
ch = CHILD(CHILD(ch, 1), 0);
|
||||
|
||||
if (NCH(ch) != 1)
|
||||
arg = compiler_complex_args(c, CHILD(ch, 1));
|
||||
else
|
||||
arg = compiler_simple_arg(c, CHILD(ch, 0));
|
||||
if (!arg)
|
||||
goto error;
|
||||
asdl_seq_SET(posargs, k++, arg);
|
||||
|
||||
}
|
||||
i += 2; /* the name and the comma */
|
||||
break;
|
||||
case STAR:
|
||||
|
@ -799,11 +823,8 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
ast_error(CHILD(n, i), "no name for vararg");
|
||||
goto error;
|
||||
}
|
||||
if (!strcmp(STR(CHILD(n, i+1)), "None")) {
|
||||
ast_error(CHILD(n, i+1), "assignment to None");
|
||||
goto error;
|
||||
}
|
||||
if (TYPE(CHILD(n, i+1)) == COMMA) {
|
||||
ch = CHILD(n, i+1); /* tname or COMMA */
|
||||
if (TYPE(ch) == COMMA) {
|
||||
int res = 0;
|
||||
i += 2; /* now follows keyword only arguments */
|
||||
res = handle_keywordonly_args(c, n, i,
|
||||
|
@ -811,10 +832,19 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
if (res == -1) goto error;
|
||||
i = res; /* res has new position to process */
|
||||
}
|
||||
else if (!strcmp(STR(CHILD(ch, 0)), "None")) {
|
||||
ast_error(CHILD(ch, 0), "assignment to None");
|
||||
goto error;
|
||||
}
|
||||
else {
|
||||
vararg = NEW_IDENTIFIER(CHILD(n, i+1));
|
||||
vararg = NEW_IDENTIFIER(CHILD(ch, 0));
|
||||
if (NCH(ch) > 1) {
|
||||
/* there is an annotation on the vararg */
|
||||
varargannotation = ast_for_expr(c, CHILD(ch, 2));
|
||||
}
|
||||
i += 3;
|
||||
if (i < NCH(n) && TYPE(CHILD(n, i)) == NAME) {
|
||||
if (i < NCH(n) && (TYPE(CHILD(n, i)) == tname
|
||||
|| TYPE(CHILD(n, i)) == vname)) {
|
||||
int res = 0;
|
||||
res = handle_keywordonly_args(c, n, i,
|
||||
kwonlyargs, kwdefaults);
|
||||
|
@ -824,11 +854,17 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
}
|
||||
break;
|
||||
case DOUBLESTAR:
|
||||
if (!strcmp(STR(CHILD(n, i+1)), "None")) {
|
||||
ast_error(CHILD(n, i+1), "assignment to None");
|
||||
ch = CHILD(n, i+1); /* tname */
|
||||
assert(TYPE(ch) == tname || TYPE(ch) == vname);
|
||||
if (!strcmp(STR(CHILD(ch, 0)), "None")) {
|
||||
ast_error(CHILD(ch, 0), "assignment to None");
|
||||
goto error;
|
||||
}
|
||||
kwarg = NEW_IDENTIFIER(CHILD(n, i+1));
|
||||
kwarg = NEW_IDENTIFIER(CHILD(ch, 0));
|
||||
if (NCH(ch) > 1) {
|
||||
/* there is an annotation on the kwarg */
|
||||
kwargannotation = ast_for_expr(c, CHILD(ch, 2));
|
||||
}
|
||||
i += 3;
|
||||
break;
|
||||
default:
|
||||
|
@ -838,8 +874,8 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
goto error;
|
||||
}
|
||||
}
|
||||
return arguments(posargs, vararg, kwonlyargs, kwarg,
|
||||
posdefaults, kwdefaults, c->c_arena);
|
||||
return arguments(posargs, vararg, varargannotation, kwonlyargs, kwarg,
|
||||
kwargannotation, posdefaults, kwdefaults, c->c_arena);
|
||||
error:
|
||||
Py_XDECREF(vararg);
|
||||
Py_XDECREF(kwarg);
|
||||
|
@ -938,11 +974,12 @@ ast_for_decorators(struct compiling *c, const node *n)
|
|||
static stmt_ty
|
||||
ast_for_funcdef(struct compiling *c, const node *n)
|
||||
{
|
||||
/* funcdef: 'def' [decorators] NAME parameters ':' suite */
|
||||
/* funcdef: 'def' [decorators] NAME parameters ['->' test] ':' suite */
|
||||
identifier name;
|
||||
arguments_ty args;
|
||||
asdl_seq *body;
|
||||
asdl_seq *decorator_seq = NULL;
|
||||
expr_ty returns = NULL;
|
||||
int name_i;
|
||||
|
||||
REQ(n, funcdef);
|
||||
|
@ -967,11 +1004,17 @@ ast_for_funcdef(struct compiling *c, const node *n)
|
|||
args = ast_for_arguments(c, CHILD(n, name_i + 1));
|
||||
if (!args)
|
||||
return NULL;
|
||||
if (TYPE(CHILD(n, name_i+2)) == RARROW) {
|
||||
returns = ast_for_expr(c, CHILD(n, name_i + 3));
|
||||
if (!returns)
|
||||
return NULL;
|
||||
name_i += 2;
|
||||
}
|
||||
body = ast_for_suite(c, CHILD(n, name_i + 3));
|
||||
if (!body)
|
||||
return NULL;
|
||||
|
||||
return FunctionDef(name, args, body, decorator_seq, LINENO(n),
|
||||
return FunctionDef(name, args, body, decorator_seq, returns, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
|
@ -983,7 +1026,8 @@ ast_for_lambdef(struct compiling *c, const node *n)
|
|||
expr_ty expression;
|
||||
|
||||
if (NCH(n) == 3) {
|
||||
args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena);
|
||||
args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, c->c_arena);
|
||||
if (!args)
|
||||
return NULL;
|
||||
expression = ast_for_expr(c, CHILD(n, 2));
|
||||
|
@ -1361,8 +1405,7 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
PyArena_AddPyObject(c->c_arena, pynum);
|
||||
return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
case DOT:
|
||||
/* Ellipsis */
|
||||
case DOT: /* Ellipsis */
|
||||
return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena);
|
||||
case LPAR: /* some parenthesized expressions */
|
||||
ch = CHILD(n, 1);
|
||||
|
|
|
@ -2293,10 +2293,37 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
{
|
||||
int posdefaults = oparg & 0xff;
|
||||
int kwdefaults = (oparg>>8) & 0xff;
|
||||
int num_annotations = (oparg >> 16) & 0x7fff;
|
||||
|
||||
v = POP(); /* code object */
|
||||
x = PyFunction_New(v, f->f_globals);
|
||||
Py_DECREF(v);
|
||||
|
||||
if (x != NULL && num_annotations > 0) {
|
||||
Py_ssize_t name_ix;
|
||||
u = POP(); /* names of args with annotations */
|
||||
v = PyDict_New();
|
||||
if (v == NULL) {
|
||||
Py_DECREF(x);
|
||||
x = NULL;
|
||||
break;
|
||||
}
|
||||
name_ix = PyTuple_Size(u);
|
||||
assert(num_annotations == name_ix+1);
|
||||
while (name_ix > 0) {
|
||||
--name_ix;
|
||||
t = PyTuple_GET_ITEM(u, name_ix);
|
||||
w = POP();
|
||||
/* XXX(nnorwitz): check for errors */
|
||||
PyDict_SetItem(v, t, w);
|
||||
Py_DECREF(w);
|
||||
}
|
||||
|
||||
err = PyFunction_SetAnnotations(x, v);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(u);
|
||||
}
|
||||
|
||||
/* XXX Maybe this should be a separate opcode? */
|
||||
if (x != NULL && posdefaults > 0) {
|
||||
v = PyTuple_New(posdefaults);
|
||||
|
@ -2322,6 +2349,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
while (--kwdefaults >= 0) {
|
||||
w = POP(); /* default value */
|
||||
u = POP(); /* kw only arg name */
|
||||
/* XXX(nnorwitz): check for errors */
|
||||
PyDict_SetItem(v, u, w);
|
||||
}
|
||||
err = PyFunction_SetKwDefaults(x, v);
|
||||
|
|
141
Python/compile.c
141
Python/compile.c
|
@ -832,7 +832,7 @@ opcode_stack_effect(int opcode, int oparg)
|
|||
|
||||
case RAISE_VARARGS:
|
||||
return -oparg;
|
||||
#define NARGS(o) (((o) % 256) + 2*((o) / 256))
|
||||
#define NARGS(o) (((o) % 256) + 2*(((o) / 256) % 256))
|
||||
case CALL_FUNCTION:
|
||||
return -NARGS(oparg);
|
||||
case CALL_FUNCTION_VAR:
|
||||
|
@ -841,7 +841,7 @@ opcode_stack_effect(int opcode, int oparg)
|
|||
case CALL_FUNCTION_VAR_KW:
|
||||
return -NARGS(oparg)-2;
|
||||
case MAKE_FUNCTION:
|
||||
return -NARGS(oparg);
|
||||
return -NARGS(oparg) - ((oparg >> 16) & 0xffff);
|
||||
#undef NARGS
|
||||
case BUILD_SLICE:
|
||||
if (oparg == 3)
|
||||
|
@ -1266,15 +1266,38 @@ compiler_decorators(struct compiler *c, asdl_seq* decos)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_unpack_nested(struct compiler *c, asdl_seq *args) {
|
||||
int i, len;
|
||||
len = asdl_seq_LEN(args);
|
||||
ADDOP_I(c, UNPACK_SEQUENCE, len);
|
||||
for (i = 0; i < len; i++) {
|
||||
arg_ty elt = (arg_ty)asdl_seq_GET(args, i);
|
||||
switch (elt->kind) {
|
||||
case SimpleArg_kind:
|
||||
if (!compiler_nameop(c, elt->v.SimpleArg.arg, Store))
|
||||
return 0;
|
||||
break;
|
||||
case NestedArgs_kind:
|
||||
if (!compiler_unpack_nested(c, elt->v.NestedArgs.args))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_arguments(struct compiler *c, arguments_ty args)
|
||||
{
|
||||
int i;
|
||||
int n = asdl_seq_LEN(args->args);
|
||||
/* Correctly handle nested argument lists */
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
expr_ty arg = (expr_ty)asdl_seq_GET(args->args, i);
|
||||
if (arg->kind == Tuple_kind) {
|
||||
arg_ty arg = (arg_ty)asdl_seq_GET(args->args, i);
|
||||
if (arg->kind == NestedArgs_kind) {
|
||||
PyObject *id = PyString_FromFormat(".%d", i);
|
||||
if (id == NULL) {
|
||||
return 0;
|
||||
|
@ -1284,7 +1307,8 @@ compiler_arguments(struct compiler *c, arguments_ty args)
|
|||
return 0;
|
||||
}
|
||||
Py_DECREF(id);
|
||||
VISIT(c, expr, arg);
|
||||
if (!compiler_unpack_nested(c, arg->v.NestedArgs.args))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
@ -1296,10 +1320,10 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs,
|
|||
{
|
||||
int i, default_count = 0;
|
||||
for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
|
||||
expr_ty arg = asdl_seq_GET(kwonlyargs, i);
|
||||
arg_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);
|
||||
ADDOP_O(c, LOAD_CONST, arg->v.SimpleArg.arg, consts);
|
||||
if (!compiler_visit_expr(c, default_)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1309,15 +1333,113 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs,
|
|||
return default_count;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_visit_argannotation(struct compiler *c, identifier id,
|
||||
expr_ty annotation, PyObject *names)
|
||||
{
|
||||
if (annotation) {
|
||||
VISIT(c, expr, annotation);
|
||||
if (PyList_Append(names, id))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_visit_argannotations(struct compiler *c, asdl_seq* args,
|
||||
PyObject *names)
|
||||
{
|
||||
int i, error;
|
||||
for (i = 0; i < asdl_seq_LEN(args); i++) {
|
||||
arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
|
||||
if (arg->kind == NestedArgs_kind)
|
||||
error = compiler_visit_argannotations(
|
||||
c,
|
||||
arg->v.NestedArgs.args,
|
||||
names);
|
||||
else
|
||||
error = compiler_visit_argannotation(
|
||||
c,
|
||||
arg->v.SimpleArg.arg,
|
||||
arg->v.SimpleArg.annotation,
|
||||
names);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_visit_annotations(struct compiler *c, arguments_ty args,
|
||||
expr_ty returns)
|
||||
{
|
||||
/* push arg annotations and a list of the argument names. return the #
|
||||
of items pushed. this is out-of-order wrt the source code. */
|
||||
static identifier return_str;
|
||||
PyObject *names;
|
||||
int len;
|
||||
names = PyList_New(0);
|
||||
if (!names)
|
||||
return -1;
|
||||
|
||||
if (compiler_visit_argannotations(c, args->args, names))
|
||||
goto error;
|
||||
if (args->varargannotation &&
|
||||
compiler_visit_argannotation(c, args->vararg,
|
||||
args->varargannotation, names))
|
||||
goto error;
|
||||
if (compiler_visit_argannotations(c, args->kwonlyargs, names))
|
||||
goto error;
|
||||
if (args->kwargannotation &&
|
||||
compiler_visit_argannotation(c, args->kwarg,
|
||||
args->kwargannotation, names))
|
||||
goto error;
|
||||
|
||||
if (!return_str) {
|
||||
return_str = PyString_InternFromString("return");
|
||||
if (!return_str)
|
||||
goto error;
|
||||
}
|
||||
if (compiler_visit_argannotation(c, return_str, returns, names)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
len = PyList_GET_SIZE(names);
|
||||
if (len) {
|
||||
/* convert names to a tuple and place on stack */
|
||||
PyObject *elt;
|
||||
int i;
|
||||
PyObject *s = PyTuple_New(len);
|
||||
if (!s)
|
||||
goto error;
|
||||
for (i = 0; i < len; i++) {
|
||||
elt = PyList_GET_ITEM(names, i);
|
||||
Py_INCREF(elt);
|
||||
PyTuple_SET_ITEM(s, i, elt);
|
||||
}
|
||||
ADDOP_O(c, LOAD_CONST, s, consts);
|
||||
Py_DECREF(s);
|
||||
len++; /* include the just-pushed tuple */
|
||||
}
|
||||
Py_DECREF(names);
|
||||
return len;
|
||||
|
||||
error:
|
||||
Py_DECREF(names);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_function(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
PyCodeObject *co;
|
||||
PyObject *first_const = Py_None;
|
||||
arguments_ty args = s->v.FunctionDef.args;
|
||||
expr_ty returns = s->v.FunctionDef.returns;
|
||||
asdl_seq* decos = s->v.FunctionDef.decorators;
|
||||
stmt_ty st;
|
||||
int i, n, docstring, kw_default_count = 0, arglength;
|
||||
int num_annotations;
|
||||
|
||||
assert(s->kind == FunctionDef_kind);
|
||||
|
||||
|
@ -1332,6 +1454,7 @@ compiler_function(struct compiler *c, stmt_ty s)
|
|||
}
|
||||
if (args->defaults)
|
||||
VISIT_SEQ(c, expr, args->defaults);
|
||||
num_annotations = compiler_visit_annotations(c, args, returns);
|
||||
|
||||
if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s,
|
||||
s->lineno))
|
||||
|
@ -1364,9 +1487,11 @@ compiler_function(struct compiler *c, stmt_ty s)
|
|||
|
||||
arglength = asdl_seq_LEN(args->defaults);
|
||||
arglength |= kw_default_count << 8;
|
||||
arglength |= num_annotations << 16;
|
||||
compiler_make_closure(c, co, arglength);
|
||||
Py_DECREF(co);
|
||||
|
||||
/* decorators */
|
||||
for (i = 0; i < asdl_seq_LEN(decos); i++) {
|
||||
ADDOP_I(c, CALL_FUNCTION, 1);
|
||||
}
|
||||
|
|
2969
Python/graminit.c
2969
Python/graminit.c
File diff suppressed because it is too large
Load Diff
|
@ -172,9 +172,12 @@ static int symtable_visit_alias(struct symtable *st, alias_ty);
|
|||
static int symtable_visit_comprehension(struct symtable *st, comprehension_ty);
|
||||
static int symtable_visit_keyword(struct symtable *st, keyword_ty);
|
||||
static int symtable_visit_slice(struct symtable *st, slice_ty);
|
||||
static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top);
|
||||
static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args);
|
||||
static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top,
|
||||
int annotations);
|
||||
static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args,
|
||||
int annotations);
|
||||
static int symtable_implicit_arg(struct symtable *st, int pos);
|
||||
static int symtable_visit_annotations(struct symtable *st, stmt_ty s);
|
||||
|
||||
|
||||
static identifier top = NULL, lambda = NULL, genexpr = NULL;
|
||||
|
@ -935,6 +938,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
if (s->v.FunctionDef.args->kw_defaults)
|
||||
VISIT_KWONLYDEFAULTS(st,
|
||||
s->v.FunctionDef.args->kw_defaults);
|
||||
if (!symtable_visit_annotations(st, s))
|
||||
return 0;
|
||||
if (s->v.FunctionDef.decorators)
|
||||
VISIT_SEQ(st, expr, s->v.FunctionDef.decorators);
|
||||
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
||||
|
@ -1219,22 +1224,29 @@ symtable_implicit_arg(struct symtable *st, int pos)
|
|||
}
|
||||
|
||||
static int
|
||||
symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel)
|
||||
symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel,
|
||||
int annotations)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!args)
|
||||
return -1;
|
||||
|
||||
/* go through all the toplevel arguments first */
|
||||
for (i = 0; i < asdl_seq_LEN(args); i++) {
|
||||
expr_ty arg = (expr_ty)asdl_seq_GET(args, i);
|
||||
if (arg->kind == Name_kind) {
|
||||
assert(arg->v.Name.ctx == Param ||
|
||||
(arg->v.Name.ctx == Store && !toplevel));
|
||||
if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM))
|
||||
arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
|
||||
if (arg->kind == SimpleArg_kind) {
|
||||
if (!annotations) {
|
||||
if (!symtable_add_def(st,
|
||||
arg->v.SimpleArg.arg,
|
||||
DEF_PARAM))
|
||||
return 0;
|
||||
}
|
||||
else if (arg->kind == Tuple_kind) {
|
||||
assert(arg->v.Tuple.ctx == Store);
|
||||
if (toplevel) {
|
||||
else if (arg->v.SimpleArg.annotation)
|
||||
VISIT(st, expr, arg->v.SimpleArg.annotation);
|
||||
}
|
||||
else if (arg->kind == NestedArgs_kind) {
|
||||
if (toplevel && !annotations) {
|
||||
if (!symtable_implicit_arg(st, i))
|
||||
return 0;
|
||||
}
|
||||
|
@ -1249,7 +1261,7 @@ symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel)
|
|||
}
|
||||
|
||||
if (!toplevel) {
|
||||
if (!symtable_visit_params_nested(st, args))
|
||||
if (!symtable_visit_params_nested(st, args, annotations))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1257,28 +1269,49 @@ symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel)
|
|||
}
|
||||
|
||||
static int
|
||||
symtable_visit_params_nested(struct symtable *st, asdl_seq *args)
|
||||
symtable_visit_params_nested(struct symtable *st, asdl_seq *args,
|
||||
int annotations)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < asdl_seq_LEN(args); i++) {
|
||||
expr_ty arg = (expr_ty)asdl_seq_GET(args, i);
|
||||
if (arg->kind == Tuple_kind &&
|
||||
!symtable_visit_params(st, arg->v.Tuple.elts, 0))
|
||||
arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
|
||||
if (arg->kind == NestedArgs_kind &&
|
||||
!symtable_visit_params(st, arg->v.NestedArgs.args, 0,
|
||||
annotations))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
symtable_visit_annotations(struct symtable *st, stmt_ty s)
|
||||
{
|
||||
arguments_ty a = s->v.FunctionDef.args;
|
||||
|
||||
if (a->args && !symtable_visit_params(st, a->args, 1, 1))
|
||||
return 0;
|
||||
if (a->varargannotation)
|
||||
VISIT(st, expr, a->varargannotation);
|
||||
if (a->kwargannotation)
|
||||
VISIT(st, expr, a->kwargannotation);
|
||||
if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1, 1))
|
||||
return 0;
|
||||
if (s->v.FunctionDef.returns)
|
||||
VISIT(st, expr, s->v.FunctionDef.returns);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_visit_arguments(struct symtable *st, arguments_ty a)
|
||||
{
|
||||
/* skip default arguments inside function block
|
||||
XXX should ast be different?
|
||||
*/
|
||||
if (a->args && !symtable_visit_params(st, a->args, 1))
|
||||
if (a->args && !symtable_visit_params(st, a->args, 1, 0))
|
||||
return 0;
|
||||
if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1))
|
||||
if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1, 0))
|
||||
return 0;
|
||||
if (a->vararg) {
|
||||
if (!symtable_add_def(st, a->vararg, DEF_PARAM))
|
||||
|
@ -1290,7 +1323,7 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a)
|
|||
return 0;
|
||||
st->st_cur->ste_varkeywords = 1;
|
||||
}
|
||||
if (a->args && !symtable_visit_params_nested(st, a->args))
|
||||
if (a->args && !symtable_visit_params_nested(st, a->args, 0))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
Module: doc*, node
|
||||
Stmt: nodes!
|
||||
Decorators: nodes!
|
||||
Function: decorators&, name*, argnames*, defaults!, kwonlyargs*, flags*, doc*, code
|
||||
Lambda: argnames*, defaults!, kwonlyargs*, flags*, code
|
||||
Function: decorators&, name*, arguments!, defaults!, kwonlyargs!, returns&, flags*, doc*, code
|
||||
Lambda: arguments!, defaults!, kwonlyargs!, flags*, code
|
||||
SimpleArg: name*, annotation&
|
||||
NestedArgs: args!
|
||||
Kwarg: arg, expr
|
||||
Class: name*, bases!, doc*, code
|
||||
Pass:
|
||||
Break:
|
||||
|
@ -93,9 +96,10 @@ init(Lambda):
|
|||
self.varargs = 1
|
||||
if flags & CO_VARKEYWORDS:
|
||||
self.kwargs = 1
|
||||
self.returns = None
|
||||
|
||||
init(GenExpr):
|
||||
self.argnames = ['.0']
|
||||
self.arguments = [SimpleArg('.0', None)]
|
||||
self.varargs = self.kwargs = None
|
||||
self.kwonlyargs = ()
|
||||
|
||||
|
|
|
@ -266,7 +266,10 @@ class Node:
|
|||
pass # implemented by subclasses
|
||||
|
||||
class EmptyNode(Node):
|
||||
pass
|
||||
def getChildNodes(self):
|
||||
return ()
|
||||
def getChildren(self):
|
||||
return ()
|
||||
|
||||
class Expression(Node):
|
||||
# Expression is an artificial node class to support "eval"
|
||||
|
|
Loading…
Reference in New Issue