mirror of
https://github.com/python/cpython.git
synced 2025-08-23 02:04:56 +00:00
Jiwon Seo's PEP 3102 implementation.
See SF#1549670. The compiler package has not yet been updated.
This commit is contained in:
parent
fc2a0a8e3c
commit
4f72a78684
31 changed files with 739 additions and 227 deletions
239
Python/ast.c
239
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++;
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
|
||||
/* 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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue