summaryrefslogtreecommitdiffstats
path: root/Python/ast.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2006-10-27 23:31:49 (GMT)
committerGuido van Rossum <guido@python.org>2006-10-27 23:31:49 (GMT)
commit4f72a78684bbfcdc43ceeabb240ceee54706c4b0 (patch)
tree743c27c5125dcef580cffe77395fe97bedf40d5f /Python/ast.c
parentfc2a0a8e3cb1d40fd965576060c28c8bd2ea1ad5 (diff)
downloadcpython-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.c241
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));