Jiwon Seo's PEP 3102 implementation.

See SF#1549670.
The compiler package has not yet been updated.
This commit is contained in:
Guido van Rossum 2006-10-27 23:31:49 +00:00
parent fc2a0a8e3c
commit 4f72a78684
31 changed files with 739 additions and 227 deletions

View file

@ -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));