diff options
author | Guido van Rossum <guido@python.org> | 2006-10-27 23:31:49 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2006-10-27 23:31:49 (GMT) |
commit | 4f72a78684bbfcdc43ceeabb240ceee54706c4b0 (patch) | |
tree | 743c27c5125dcef580cffe77395fe97bedf40d5f /Python/ast.c | |
parent | fc2a0a8e3cb1d40fd965576060c28c8bd2ea1ad5 (diff) | |
download | cpython-4f72a78684bbfcdc43ceeabb240ceee54706c4b0.zip cpython-4f72a78684bbfcdc43ceeabb240ceee54706c4b0.tar.gz cpython-4f72a78684bbfcdc43ceeabb240ceee54706c4b0.tar.bz2 |
Jiwon Seo's PEP 3102 implementation.
See SF#1549670.
The compiler package has not yet been updated.
Diffstat (limited to 'Python/ast.c')
-rw-r--r-- | Python/ast.c | 241 |
1 files changed, 178 insertions, 63 deletions
diff --git a/Python/ast.c b/Python/ast.c index bb2f3a3..672a715 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -591,6 +591,63 @@ compiler_complex_args(struct compiling *c, const node *n) return result; } +/* returns -1 if failed to handle keyword only arguments + returns new position to keep processing if successful + (',' NAME ['=' test])* + ^^^ + start pointing here + */ +static int +handle_keywordonly_args(struct compiling *c, const node *n, int start, + asdl_seq *kwonlyargs, asdl_seq *kwdefaults) +{ + node *ch; + expr_ty name; + int i = start; + int j = 0; /* index for kwdefaults and kwonlyargs */ + assert(kwonlyargs != NULL); + assert(kwdefaults != NULL); + while (i < NCH(n)) { + ch = CHILD(n, i); + switch (TYPE(ch)) { + case NAME: + if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { + expr_ty expression = ast_for_expr(c, CHILD(n, i + 2)); + if (!expression) { + ast_error(ch, "assignment to None"); + goto error; + } + asdl_seq_SET(kwdefaults, j, expression); + i += 2; /* '=' and test */ + } + else { /* setting NULL if no default value exists */ + asdl_seq_SET(kwdefaults, j, NULL); + } + if (!strcmp(STR(ch), "None")) { + ast_error(ch, "assignment to None"); + goto error; + } + name = Name(NEW_IDENTIFIER(ch), + Param, LINENO(ch), ch->n_col_offset, + c->c_arena); + if (!name) { + ast_error(ch, "expecting name"); + goto error; + } + asdl_seq_SET(kwonlyargs, j++, name); + i += 2; /* the name and the comma */ + break; + case DOUBLESTAR: + return i; + default: + ast_error(ch, "unexpected node"); + goto error; + } + } + return i; + error: + return -1; +} /* Create AST for argument list. */ @@ -598,35 +655,71 @@ static arguments_ty ast_for_arguments(struct compiling *c, const node *n) { /* parameters: '(' [varargslist] ')' - varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] - | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [','] + varargslist: (fpdef ['=' test] ',')* + ('*' [NAME] (',' fpdef ['=' test])* [',' '**' NAME] | '**' NAME) + | fpdef ['=' test] (',' fpdef ['=' test])* [','] */ - int i, j, k, n_args = 0, n_defaults = 0, found_default = 0; - asdl_seq *args, *defaults; + 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; node *ch; if (TYPE(n) == parameters) { - if (NCH(n) == 2) /* () as argument list */ - return arguments(NULL, NULL, NULL, NULL, c->c_arena); - n = CHILD(n, 1); + if (NCH(n) == 2) /* () as argument list */ + return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); + n = CHILD(n, 1); } REQ(n, varargslist); - /* first count the number of normal args & defaults */ + /* first count the number of positional args & defaults */ for (i = 0; i < NCH(n); i++) { - ch = CHILD(n, i); - if (TYPE(ch) == fpdef) - n_args++; - if (TYPE(ch) == EQUAL) - n_defaults++; - } - args = (n_args ? asdl_seq_new(n_args, c->c_arena) : NULL); - if (!args && n_args) - return NULL; /* Don't need to goto error; no objects allocated */ - defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL); - if (!defaults && n_defaults) - return NULL; /* Don't need to goto error; no objects allocated */ + ch = CHILD(n, i); + if (TYPE(ch) == STAR) { + if (TYPE(CHILD(n, i+1)) == NAME) { + /* skip NAME of vararg */ + /* so that following can count only keyword only args */ + i += 2; + } + else { + i++; + } + break; + } + if (TYPE(ch) == fpdef) nposargs++; + if (TYPE(ch) == EQUAL) nposdefaults++; + } + /* count the number of keyword only args & + defaults for keyword only args */ + for ( ; i < NCH(n); ++i) { + ch = CHILD(n, i); + if (TYPE(ch) == DOUBLESTAR) break; + if (TYPE(ch) == NAME) nkwonlyargs++; + } + + posargs = (nposargs ? asdl_seq_new(nposargs, c->c_arena) : NULL); + if (!posargs && nposargs) + return NULL; /* Don't need to goto error; no objects allocated */ + kwonlyargs = (nkwonlyargs ? + asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); + if (!kwonlyargs && nkwonlyargs) + return NULL; /* Don't need to goto error; no objects allocated */ + posdefaults = (nposdefaults ? + asdl_seq_new(nposdefaults, c->c_arena) : NULL); + if (!posdefaults && nposdefaults) + return NULL; /* Don't need to goto error; no objects allocated */ + /* The length of kwonlyargs and kwdefaults are same + since we set NULL as default for keyword only argument w/o default + - we have sequence data structure, but no dictionary */ + kwdefaults = (nkwonlyargs ? + asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); + if (!kwdefaults && nkwonlyargs) + return NULL; /* Don't need to goto error; no objects allocated */ + + if (nposargs + nkwonlyargs > 255) { + ast_error(n, "more than 255 arguments"); + return NULL; + } /* fpdef: NAME | '(' fplist ')' fplist: fpdef (',' fpdef)* [','] @@ -635,8 +728,8 @@ ast_for_arguments(struct compiling *c, const node *n) j = 0; /* index for defaults */ k = 0; /* index for args */ while (i < NCH(n)) { - ch = CHILD(n, i); - switch (TYPE(ch)) { + ch = CHILD(n, i); + switch (TYPE(ch)) { case fpdef: /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is anything other than EQUAL or a comma? */ @@ -644,57 +737,80 @@ ast_for_arguments(struct compiling *c, const node *n) if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { expr_ty expression = ast_for_expr(c, CHILD(n, i + 2)); if (!expression) - goto error; - assert(defaults != NULL); - asdl_seq_SET(defaults, j++, expression); + goto error; + assert(posdefaults != NULL); + asdl_seq_SET(posdefaults, j++, expression); + i += 2; - found_default = 1; + found_default = 1; + } + else if (found_default) { + ast_error(n, + "non-default argument follows default argument"); + goto error; } - else if (found_default) { - ast_error(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(args, k++, compiler_complex_args(c, ch)); - } else { - /* def foo((x)): setup for checking NAME below. */ - ch = CHILD(ch, 0); - } + 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. */ + ch = CHILD(ch, 0); + } } 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; - } + 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(args, k++, name); - - } + asdl_seq_SET(posargs, k++, name); + + } i += 2; /* the name and the comma */ break; case STAR: - if (!strcmp(STR(CHILD(n, i+1)), "None")) { - ast_error(CHILD(n, i+1), "assignment to None"); - goto error; - } - vararg = NEW_IDENTIFIER(CHILD(n, i+1)); - i += 3; + 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; + } + if (TYPE(CHILD(n, i+1)) == COMMA) { + int res = 0; + i += 2; /* now follows keyword only arguments */ + res = handle_keywordonly_args(c, n, i, + kwonlyargs, kwdefaults); + if (res == -1) goto error; + i = res; /* res has new position to process */ + } + else { + vararg = NEW_IDENTIFIER(CHILD(n, i+1)); + i += 3; + if (i < NCH(n) && TYPE(CHILD(n, i)) == NAME) { + int res = 0; + res = handle_keywordonly_args(c, n, i, + kwonlyargs, kwdefaults); + if (res == -1) goto error; + i = res; /* res has new position to process */ + } + } break; case DOUBLESTAR: - if (!strcmp(STR(CHILD(n, i+1)), "None")) { - ast_error(CHILD(n, i+1), "assignment to None"); - goto error; - } + if (!strcmp(STR(CHILD(n, i+1)), "None")) { + ast_error(CHILD(n, i+1), "assignment to None"); + goto error; + } kwarg = NEW_IDENTIFIER(CHILD(n, i+1)); i += 3; break; @@ -703,11 +819,10 @@ ast_for_arguments(struct compiling *c, const node *n) "unexpected node in varargslist: %d @ %d", TYPE(ch), i); goto error; - } + } } - - return arguments(args, vararg, kwarg, defaults, c->c_arena); - + return arguments(posargs, vararg, kwonlyargs, kwarg, + posdefaults, kwdefaults, c->c_arena); error: Py_XDECREF(vararg); Py_XDECREF(kwarg); @@ -851,7 +966,7 @@ ast_for_lambdef(struct compiling *c, const node *n) expr_ty expression; if (NCH(n) == 3) { - args = arguments(NULL, NULL, NULL, NULL, c->c_arena); + args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); if (!args) return NULL; expression = ast_for_expr(c, CHILD(n, 2)); |