diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2019-04-29 12:36:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-29 12:36:57 (GMT) |
commit | 8c77b8cb9188165a123f2512026e3629bf03dc9b (patch) | |
tree | 863ea19f5f2c8ec179c32b3d06dc8366859ae26e /Python/ast.c | |
parent | 99fcc616d400cd31af0733c3f8cc93bcc1d32a44 (diff) | |
download | cpython-8c77b8cb9188165a123f2512026e3629bf03dc9b.zip cpython-8c77b8cb9188165a123f2512026e3629bf03dc9b.tar.gz cpython-8c77b8cb9188165a123f2512026e3629bf03dc9b.tar.bz2 |
bpo-36540: PEP 570 -- Implementation (GH-12701)
This commit contains the implementation of PEP570: Python positional-only parameters.
* Update Grammar/Grammar with new typedarglist and varargslist
* Regenerate grammar files
* Update and regenerate AST related files
* Update code object
* Update marshal.c
* Update compiler and symtable
* Regenerate importlib files
* Update callable objects
* Implement positional-only args logic in ceval.c
* Regenerate frozen data
* Update standard library to account for positional-only args
* Add test file for positional-only args
* Update other test files to account for positional-only args
* Add News entry
* Update inspect module and related tests
Diffstat (limited to 'Python/ast.c')
-rw-r--r-- | Python/ast.c | 100 |
1 files changed, 82 insertions, 18 deletions
diff --git a/Python/ast.c b/Python/ast.c index 913e53a..4687f81 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -110,8 +110,9 @@ expr_context_name(expr_context_ty ctx) static int validate_arguments(arguments_ty args) { - if (!validate_args(args->args)) + if (!validate_args(args->posonlyargs) || !validate_args(args->args)) { return 0; + } if (args->vararg && args->vararg->annotation && !validate_expr(args->vararg->annotation, Load)) { return 0; @@ -1431,31 +1432,73 @@ ast_for_arguments(struct compiling *c, const node *n) and varargslist (lambda definition). parameters: '(' [typedargslist] ')' - typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [ - '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] - | '**' tfpdef [',']]] - | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] - | '**' tfpdef [',']) + + The following definition for typedarglist is equivalent to this set of rules: + + arguments = argument (',' [TYPE_COMMENT] argument)* + argument = tfpdef ['=' test] + kwargs = '**' tfpdef [','] [TYPE_COMMENT] + args = '*' [tfpdef] + kwonly_kwargs = (',' [TYPE_COMMENT] argument)* (TYPE_COMMENT | [',' + [TYPE_COMMENT] [kwargs]]) + args_kwonly_kwargs = args kwonly_kwargs | kwargs + poskeyword_args_kwonly_kwargs = arguments ( TYPE_COMMENT | [',' + [TYPE_COMMENT] [args_kwonly_kwargs]]) + typedargslist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs + typedarglist = (arguments ',' [TYPE_COMMENT] '/' [',' [[TYPE_COMMENT] + typedargslist_no_posonly]])|(typedargslist_no_posonly)" + + typedargslist: ( (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* + ',' [TYPE_COMMENT] '/' [',' [ [TYPE_COMMENT] tfpdef ['=' test] ( ',' + [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*' + [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' + [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [','] + [TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* + (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | + '**' tfpdef [','] [TYPE_COMMENT]]] ) | (tfpdef ['=' test] (',' + [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*' + [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' + [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [','] + [TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* + (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | + '**' tfpdef [','] [TYPE_COMMENT])) + tfpdef: NAME [':' test] - varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ - '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] - | '**' vfpdef [',']]] - | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] - | '**' vfpdef [','] - ) + + The following definition for varargslist is equivalent to this set of rules: + + arguments = argument (',' argument )* + argument = vfpdef ['=' test] + kwargs = '**' vfpdef [','] + args = '*' [vfpdef] + kwonly_kwargs = (',' argument )* [',' [kwargs]] + args_kwonly_kwargs = args kwonly_kwargs | kwargs + poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]] + vararglist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs + varargslist = arguments ',' '/' [','[(vararglist_no_posonly)]] | + (vararglist_no_posonly) + + varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [ (vfpdef ['=' + test] (',' vfpdef ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' + ['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* + [',' ['**' vfpdef [',']]] | '**' vfpdef [',']) ]] | (vfpdef ['=' test] (',' vfpdef + ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef + [',']]] | '**' vfpdef [',']) + vfpdef: NAME */ - int i, j, k, nposargs = 0, nkwonlyargs = 0; + int i, j, k, l, nposonlyargs=0, nposargs = 0, nkwonlyargs = 0; int nposdefaults = 0, found_default = 0; - asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults; + asdl_seq *posonlyargs, *posargs, *posdefaults, *kwonlyargs, *kwdefaults; arg_ty vararg = NULL, kwarg = NULL; arg_ty arg = 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, c->c_arena); n = CHILD(n, 1); } assert(TYPE(n) == typedargslist || TYPE(n) == varargslist); @@ -1479,6 +1522,10 @@ ast_for_arguments(struct compiling *c, const node *n) if (TYPE(ch) == DOUBLESTAR) break; if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++; if (TYPE(ch) == EQUAL) nposdefaults++; + if (TYPE(ch) == SLASH ) { + nposonlyargs = nposargs; + nposargs = 0; + } } /* count the number of keyword only args & defaults for keyword only args */ @@ -1487,6 +1534,10 @@ ast_for_arguments(struct compiling *c, const node *n) if (TYPE(ch) == DOUBLESTAR) break; if (TYPE(ch) == tfpdef || TYPE(ch) == vfpdef) nkwonlyargs++; } + posonlyargs = (nposonlyargs ? _Py_asdl_seq_new(nposonlyargs, c->c_arena) : NULL); + if (!posonlyargs && nposonlyargs) { + return NULL; + } posargs = (nposargs ? _Py_asdl_seq_new(nposargs, c->c_arena) : NULL); if (!posargs && nposargs) return NULL; @@ -1512,6 +1563,7 @@ ast_for_arguments(struct compiling *c, const node *n) i = 0; j = 0; /* index for defaults */ k = 0; /* index for args */ + l = 0; /* index for posonlyargs */ while (i < NCH(n)) { ch = CHILD(n, i); switch (TYPE(ch)) { @@ -1537,11 +1589,23 @@ ast_for_arguments(struct compiling *c, const node *n) arg = ast_for_arg(c, ch); if (!arg) return NULL; - asdl_seq_SET(posargs, k++, arg); + if (l < nposonlyargs) { + asdl_seq_SET(posonlyargs, l++, arg); + } else { + asdl_seq_SET(posargs, k++, arg); + } i += 1; /* the name */ if (i < NCH(n) && TYPE(CHILD(n, i)) == COMMA) i += 1; /* the comma, if present */ break; + case SLASH: + /* Advance the slash and the comma. If there are more names + * after the slash there will be a comma so we are advancing + * the correct number of nodes. If the slash is the last item, + * we will be advancing an extra token but then * i > NCH(n) + * and the enclosing while will finish correctly. */ + i += 2; + break; case STAR: if (i+1 >= NCH(n) || (i+2 == NCH(n) && (TYPE(CHILD(n, i+1)) == COMMA @@ -1621,7 +1685,7 @@ ast_for_arguments(struct compiling *c, const node *n) return NULL; } } - return arguments(posargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena); + return arguments(posargs, posonlyargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena); } static expr_ty @@ -1909,7 +1973,7 @@ 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, c->c_arena); if (!args) return NULL; expression = ast_for_expr(c, CHILD(n, 2)); |