mirror of
https://github.com/python/cpython.git
synced 2025-07-15 23:35:23 +00:00
PEP 3107 - Function Annotations thanks to Tony Lownds
This commit is contained in:
parent
f6657e67b3
commit
c150536b5e
32 changed files with 2855 additions and 1897 deletions
|
@ -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;
|
||||
|
|
303
Python/ast.c
303
Python/ast.c
|
@ -388,14 +388,14 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n)
|
|||
expr_name = "list comprehension";
|
||||
break;
|
||||
case Dict_kind:
|
||||
case Set_kind:
|
||||
case Set_kind:
|
||||
case Num_kind:
|
||||
case Str_kind:
|
||||
expr_name = "literal";
|
||||
break;
|
||||
case Ellipsis_kind:
|
||||
expr_name = "Ellipsis";
|
||||
break;
|
||||
case Ellipsis_kind:
|
||||
expr_name = "Ellipsis";
|
||||
break;
|
||||
case Compare_kind:
|
||||
expr_name = "comparison";
|
||||
break;
|
||||
|
@ -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");
|
||||
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);
|
||||
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;
|
||||
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 ?
|
||||
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;
|
||||
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,59 +804,47 @@ 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);
|
||||
/* def foo((x)): is not complex, special case. */
|
||||
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:
|
||||
if (i+1 >= NCH(n)) {
|
||||
ast_error(CHILD(n, i), "no name for vararg");
|
||||
goto error;
|
||||
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) {
|
||||
int res = 0;
|
||||
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,
|
||||
kwonlyargs, kwdefaults);
|
||||
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,9 +1405,8 @@ 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 */
|
||||
return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena);
|
||||
case DOT: /* Ellipsis */
|
||||
return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena);
|
||||
case LPAR: /* some parenthesized expressions */
|
||||
ch = CHILD(n, 1);
|
||||
|
||||
|
@ -1394,13 +1437,13 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
else
|
||||
return ast_for_listcomp(c, ch);
|
||||
case LBRACE: {
|
||||
/* dictsetmaker: test ':' test (',' test ':' test)* [','] |
|
||||
* test (',' test)* [','] */
|
||||
int i, size;
|
||||
asdl_seq *keys, *values;
|
||||
|
||||
ch = CHILD(n, 1);
|
||||
if (NCH(ch) == 1 || (NCH(ch) > 0 && STR(CHILD(ch, 1))[0] == ',')) {
|
||||
/* dictsetmaker: test ':' test (',' test ':' test)* [','] |
|
||||
* test (',' test)* [','] */
|
||||
int i, size;
|
||||
asdl_seq *keys, *values;
|
||||
|
||||
ch = CHILD(n, 1);
|
||||
if (NCH(ch) == 1 || (NCH(ch) > 0 && STR(CHILD(ch, 1))[0] == ',')) {
|
||||
/* it's a set */
|
||||
size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */
|
||||
keys = asdl_seq_new(size, c->c_arena);
|
||||
|
@ -3046,10 +3089,10 @@ ast_for_stmt(struct compiling *c, const node *n)
|
|||
n = CHILD(n, 0);
|
||||
}
|
||||
if (TYPE(n) == small_stmt) {
|
||||
REQ(n, small_stmt);
|
||||
n = CHILD(n, 0);
|
||||
/* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt
|
||||
| flow_stmt | import_stmt | global_stmt | assert_stmt
|
||||
REQ(n, small_stmt);
|
||||
n = CHILD(n, 0);
|
||||
/* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt
|
||||
| flow_stmt | import_stmt | global_stmt | assert_stmt
|
||||
*/
|
||||
switch (TYPE(n)) {
|
||||
case expr_stmt:
|
||||
|
|
|
@ -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))
|
||||
return 0;
|
||||
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->v.SimpleArg.annotation)
|
||||
VISIT(st, expr, arg->v.SimpleArg.annotation);
|
||||
}
|
||||
else if (arg->kind == Tuple_kind) {
|
||||
assert(arg->v.Tuple.ctx == Store);
|
||||
if (toplevel) {
|
||||
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,16 +1269,37 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -1276,9 +1309,9 @@ 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue