diff options
Diffstat (limited to 'Python/ast.c')
-rw-r--r-- | Python/ast.c | 303 |
1 files changed, 173 insertions, 130 deletions
diff --git a/Python/ast.c b/Python/ast.c index 411c42f..5ccd6f5 100644 --- a/Python/ast.c +++ b/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; - } - if (!strcmp(STR(CHILD(n, i+1)), "None")) { - ast_error(CHILD(n, i+1), "assignment to None"); - goto error; + 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: |