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 | |
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')
-rw-r--r-- | Python/Python-ast.c | 22 | ||||
-rw-r--r-- | Python/ast.c | 241 | ||||
-rw-r--r-- | Python/ceval.c | 78 | ||||
-rw-r--r-- | Python/compile.c | 55 | ||||
-rw-r--r-- | Python/graminit.c | 45 | ||||
-rw-r--r-- | Python/import.c | 3 | ||||
-rw-r--r-- | Python/marshal.c | 6 | ||||
-rw-r--r-- | Python/symtable.c | 18 |
8 files changed, 363 insertions, 105 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 0ecddb7..2839c0b 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -333,8 +333,10 @@ static PyObject* ast2obj_arguments(void*); static char *arguments_fields[]={ "args", "vararg", + "kwonlyargs", "kwarg", "defaults", + "kw_defaults", }; static PyTypeObject *keyword_type; static PyObject* ast2obj_keyword(void*); @@ -708,7 +710,7 @@ static int init_types(void) excepthandler_type = make_type("excepthandler", AST_type, excepthandler_fields, 5); if (!excepthandler_type) return 0; - arguments_type = make_type("arguments", AST_type, arguments_fields, 4); + arguments_type = make_type("arguments", AST_type, arguments_fields, 6); if (!arguments_type) return 0; keyword_type = make_type("keyword", AST_type, keyword_fields, 2); if (!keyword_type) return 0; @@ -1828,8 +1830,8 @@ excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int } arguments_ty -arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq * - defaults, PyArena *arena) +arguments(asdl_seq * args, identifier vararg, asdl_seq * kwonlyargs, identifier + kwarg, asdl_seq * defaults, asdl_seq * kw_defaults, PyArena *arena) { arguments_ty p; p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p)); @@ -1839,8 +1841,10 @@ arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq * } p->args = args; p->vararg = vararg; + p->kwonlyargs = kwonlyargs; p->kwarg = kwarg; p->defaults = defaults; + p->kw_defaults = kw_defaults; return p; } @@ -2907,6 +2911,11 @@ ast2obj_arguments(void* _o) if (PyObject_SetAttrString(result, "vararg", value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(o->kwonlyargs, ast2obj_expr); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "kwonlyargs", value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_identifier(o->kwarg); if (!value) goto failed; if (PyObject_SetAttrString(result, "kwarg", value) == -1) @@ -2917,6 +2926,11 @@ ast2obj_arguments(void* _o) if (PyObject_SetAttrString(result, "defaults", value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(o->kw_defaults, ast2obj_expr); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "kw_defaults", value) == -1) + goto failed; + Py_DECREF(value); return result; failed: Py_XDECREF(value); @@ -2994,7 +3008,7 @@ init_ast(void) if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return; - if (PyModule_AddStringConstant(m, "__version__", "51631") < 0) + if (PyModule_AddStringConstant(m, "__version__", "51773") < 0) return; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return; if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) 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)); diff --git a/Python/ceval.c b/Python/ceval.c index dcbe53d..5d5acd0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -494,7 +494,7 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) (PyObject **)NULL, 0, (PyObject **)NULL, 0, (PyObject **)NULL, 0, - NULL); + NULL, NULL); } @@ -2290,26 +2290,46 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } case MAKE_FUNCTION: + { + int posdefaults = oparg & 0xff; + int kwdefaults = (oparg>>8) & 0xff; + v = POP(); /* code object */ x = PyFunction_New(v, f->f_globals); Py_DECREF(v); /* XXX Maybe this should be a separate opcode? */ - if (x != NULL && oparg > 0) { - v = PyTuple_New(oparg); + if (x != NULL && posdefaults > 0) { + v = PyTuple_New(posdefaults); if (v == NULL) { Py_DECREF(x); x = NULL; break; } - while (--oparg >= 0) { + while (--posdefaults >= 0) { w = POP(); - PyTuple_SET_ITEM(v, oparg, w); + PyTuple_SET_ITEM(v, posdefaults, w); } err = PyFunction_SetDefaults(x, v); Py_DECREF(v); } + if (x != NULL && kwdefaults > 0) { + v = PyDict_New(); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--kwdefaults >= 0) { + w = POP(); /* default value */ + u = POP(); /* kw only arg name */ + PyDict_SetItem(v, u, w); + } + err = PyFunction_SetKwDefaults(x, v); + Py_DECREF(v); + } PUSH(x); break; + } case MAKE_CLOSURE: { @@ -2577,7 +2597,7 @@ fast_yield: PyObject * PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, PyObject **args, int argcount, PyObject **kws, int kwcount, - PyObject **defs, int defcount, PyObject *closure) + PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) { register PyFrameObject *f; register PyObject *retval = NULL; @@ -2601,6 +2621,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, freevars = f->f_localsplus + co->co_nlocals; if (co->co_argcount > 0 || + co->co_kwonlyargcount > 0 || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { int i; int n = argcount; @@ -2609,7 +2630,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, kwdict = PyDict_New(); if (kwdict == NULL) goto fail; - i = co->co_argcount; + i = co->co_argcount + co->co_kwonlyargcount; if (co->co_flags & CO_VARARGS) i++; SETLOCAL(i, kwdict); @@ -2618,7 +2639,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, if (!(co->co_flags & CO_VARARGS)) { PyErr_Format(PyExc_TypeError, "%.200s() takes %s %d " - "%sargument%s (%d given)", + "%spositional argument%s (%d given)", PyString_AsString(co->co_name), defcount ? "at most" : "exactly", co->co_argcount, @@ -2638,7 +2659,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, u = PyTuple_New(argcount - n); if (u == NULL) goto fail; - SETLOCAL(co->co_argcount, u); + SETLOCAL(co->co_argcount + co->co_kwonlyargcount, u); for (i = n; i < argcount; i++) { x = args[i]; Py_INCREF(x); @@ -2656,7 +2677,9 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, goto fail; } /* XXX slow -- speed up using dictionary? */ - for (j = 0; j < co->co_argcount; j++) { + for (j = 0; + j < co->co_argcount + co->co_kwonlyargcount; + j++) { PyObject *nm = PyTuple_GET_ITEM( co->co_varnames, j); int cmp = PyObject_RichCompareBool( @@ -2669,7 +2692,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, /* Check errors from Compare */ if (PyErr_Occurred()) goto fail; - if (j >= co->co_argcount) { + if (j >= co->co_argcount + co->co_kwonlyargcount) { if (kwdict == NULL) { PyErr_Format(PyExc_TypeError, "%.200s() got an unexpected " @@ -2694,13 +2717,38 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, SETLOCAL(j, value); } } + if (co->co_kwonlyargcount > 0) { + for (i = co->co_argcount; + i < co->co_argcount + co->co_kwonlyargcount; + i++) { + if (GETLOCAL(i) != NULL) + continue; + PyObject *name = + PyTuple_GET_ITEM(co->co_varnames, i); + PyObject *def = NULL; + if (kwdefs != NULL) + def = PyDict_GetItem(kwdefs, name); + if (def != NULL) { + Py_INCREF(def); + SETLOCAL(i, def); + continue; + } + PyErr_Format(PyExc_TypeError, + "%.200s() needs " + "keyword only argument %s", + PyString_AsString(co->co_name), + PyString_AsString(name)); + goto fail; + } + } if (argcount < co->co_argcount) { int m = co->co_argcount - defcount; for (i = argcount; i < m; i++) { if (GETLOCAL(i) == NULL) { PyErr_Format(PyExc_TypeError, "%.200s() takes %s %d " - "%sargument%s (%d given)", + "%spositional argument%s " + "(%d given)", PyString_AsString(co->co_name), ((co->co_flags & CO_VARARGS) || defcount) ? "at least" @@ -3565,12 +3613,14 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); PyObject **d = NULL; int nd = 0; PCALL(PCALL_FUNCTION); PCALL(PCALL_FAST_FUNCTION); - if (argdefs == NULL && co->co_argcount == n && nk==0 && + if (argdefs == NULL && co->co_argcount == n && + co->co_kwonlyargcount == 0 && nk==0 && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { PyFrameObject *f; PyObject *retval = NULL; @@ -3608,7 +3658,7 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) } return PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, (*pp_stack)-n, na, - (*pp_stack)-2*nk, nk, d, nd, + (*pp_stack)-2*nk, nk, d, nd, kwdefs, PyFunction_GET_CLOSURE(func)); } diff --git a/Python/compile.c b/Python/compile.c index 40ac2d7..1ab315b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -115,6 +115,7 @@ struct compiler_unit { PyObject *u_private; /* for private name mangling */ int u_argcount; /* number of arguments for block */ + int u_kwonlyargcount; /* number of keyword only arguments for block */ /* Pointer to the most recently allocated block. By following b_list members, you can reach all early allocated blocks. */ basicblock *u_blocks; @@ -494,6 +495,7 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, } memset(u, 0, sizeof(struct compiler_unit)); u->u_argcount = 0; + u->u_kwonlyargcount = 0; u->u_ste = PySymtable_Lookup(c->c_st, key); if (!u->u_ste) { compiler_unit_free(u); @@ -896,9 +898,9 @@ opcode_stack_effect(int opcode, int oparg) return -NARGS(oparg)-1; case CALL_FUNCTION_VAR_KW: return -NARGS(oparg)-2; -#undef NARGS case MAKE_FUNCTION: - return -oparg; + return -NARGS(oparg); +#undef NARGS case BUILD_SLICE: if (oparg == 3) return -2; @@ -1347,6 +1349,25 @@ compiler_arguments(struct compiler *c, arguments_ty args) } static int +compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, + asdl_seq *kw_defaults) +{ + int i, default_count = 0; + for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { + expr_ty arg = asdl_seq_GET(kwonlyargs, i); + expr_ty default_ = asdl_seq_GET(kw_defaults, i); + if (default_) { + ADDOP_O(c, LOAD_CONST, arg->v.Name.id, consts); + if (!compiler_visit_expr(c, default_)) { + return -1; + } + default_count++; + } + } + return default_count; +} + +static int compiler_function(struct compiler *c, stmt_ty s) { PyCodeObject *co; @@ -1354,14 +1375,22 @@ compiler_function(struct compiler *c, stmt_ty s) arguments_ty args = s->v.FunctionDef.args; asdl_seq* decos = s->v.FunctionDef.decorators; stmt_ty st; - int i, n, docstring; + int i, n, docstring, kw_default_count = 0, arglength; assert(s->kind == FunctionDef_kind); if (!compiler_decorators(c, decos)) return 0; + if (args->kwonlyargs) { + int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, + args->kw_defaults); + if (res < 0) + return 0; + kw_default_count = res; + } if (args->defaults) VISIT_SEQ(c, expr, args->defaults); + if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, s->lineno)) return 0; @@ -1379,6 +1408,7 @@ compiler_function(struct compiler *c, stmt_ty s) compiler_arguments(c, args); c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); n = asdl_seq_LEN(s->v.FunctionDef.body); /* if there was a docstring, we need to skip the first statement */ for (i = docstring; i < n; i++) { @@ -1390,7 +1420,9 @@ compiler_function(struct compiler *c, stmt_ty s) if (co == NULL) return 0; - compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); + arglength = asdl_seq_LEN(args->defaults); + arglength |= kw_default_count << 8; + compiler_make_closure(c, co, arglength); Py_DECREF(co); for (i = 0; i < asdl_seq_LEN(decos); i++) { @@ -1485,6 +1517,7 @@ compiler_lambda(struct compiler *c, expr_ty e) { PyCodeObject *co; static identifier name; + int kw_default_count = 0, arglength; arguments_ty args = e->v.Lambda.args; assert(e->kind == Lambda_kind); @@ -1494,6 +1527,12 @@ compiler_lambda(struct compiler *c, expr_ty e) return 0; } + if (args->kwonlyargs) { + int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, + args->kw_defaults); + if (res < 0) return 0; + kw_default_count = res; + } if (args->defaults) VISIT_SEQ(c, expr, args->defaults); if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) @@ -1503,6 +1542,7 @@ compiler_lambda(struct compiler *c, expr_ty e) compiler_arguments(c, args); c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); ADDOP_IN_SCOPE(c, RETURN_VALUE); co = assemble(c, 1); @@ -1510,7 +1550,9 @@ compiler_lambda(struct compiler *c, expr_ty e) if (co == NULL) return 0; - compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); + arglength = asdl_seq_LEN(args->defaults); + arglength |= kw_default_count << 8; + compiler_make_closure(c, co, arglength); Py_DECREF(co); return 1; @@ -3791,7 +3833,8 @@ makecode(struct compiler *c, struct assembler *a) Py_DECREF(consts); consts = tmp; - co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c), flags, + co = PyCode_New(c->u->u_argcount, c->u->u_kwonlyargcount, + nlocals, stackdepth(c), flags, bytecode, consts, names, varnames, freevars, cellvars, filename, c->u->u_name, diff --git a/Python/graminit.c b/Python/graminit.c index 912fdf2..0e94db4 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -146,14 +146,16 @@ static arc arcs_7_1[3] = { {27, 5}, {0, 1}, }; -static arc arcs_7_2[1] = { +static arc arcs_7_2[3] = { {19, 6}, + {27, 7}, + {0, 2}, }; static arc arcs_7_3[1] = { - {19, 7}, + {19, 8}, }; static arc arcs_7_4[1] = { - {26, 8}, + {26, 9}, }; static arc arcs_7_5[4] = { {24, 1}, @@ -162,30 +164,41 @@ static arc arcs_7_5[4] = { {0, 5}, }; static arc arcs_7_6[2] = { - {27, 9}, + {27, 7}, {0, 6}, }; -static arc arcs_7_7[1] = { - {0, 7}, +static arc arcs_7_7[2] = { + {19, 10}, + {29, 3}, }; -static arc arcs_7_8[2] = { - {27, 5}, +static arc arcs_7_8[1] = { {0, 8}, }; -static arc arcs_7_9[1] = { - {29, 3}, +static arc arcs_7_9[2] = { + {27, 5}, + {0, 9}, +}; +static arc arcs_7_10[3] = { + {27, 7}, + {25, 11}, + {0, 10}, +}; +static arc arcs_7_11[1] = { + {26, 6}, }; -static state states_7[10] = { +static state states_7[12] = { {3, arcs_7_0}, {3, arcs_7_1}, - {1, arcs_7_2}, + {3, arcs_7_2}, {1, arcs_7_3}, {1, arcs_7_4}, {4, arcs_7_5}, {2, arcs_7_6}, - {1, arcs_7_7}, - {2, arcs_7_8}, - {1, arcs_7_9}, + {2, arcs_7_7}, + {1, arcs_7_8}, + {2, arcs_7_9}, + {3, arcs_7_10}, + {1, arcs_7_11}, }; static arc arcs_8_0[2] = { {19, 1}, @@ -1766,7 +1779,7 @@ static dfa dfas[83] = { "\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {262, "parameters", 0, 4, states_6, "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {263, "varargslist", 0, 10, states_7, + {263, "varargslist", 0, 12, states_7, "\000\040\010\060\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {264, "fpdef", 0, 4, states_8, "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, diff --git a/Python/import.c b/Python/import.c index 49e844a..4c6c05a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -67,9 +67,10 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *); Python 3000: 3000 3010 (removed UNARY_CONVERT) 3020 (added BUILD_SET) + 3030 (added keyword-only parameters) . */ -#define MAGIC (3020 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3030 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the diff --git a/Python/marshal.c b/Python/marshal.c index c3bc87f..2667b65 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -349,6 +349,7 @@ w_object(PyObject *v, WFILE *p) PyCodeObject *co = (PyCodeObject *)v; w_byte(TYPE_CODE, p); w_long(co->co_argcount, p); + w_long(co->co_kwonlyargcount, p); w_long(co->co_nlocals, p); w_long(co->co_stacksize, p); w_long(co->co_flags, p); @@ -815,6 +816,7 @@ r_object(RFILE *p) } else { int argcount; + int kwonlyargcount; int nlocals; int stacksize; int flags; @@ -832,6 +834,7 @@ r_object(RFILE *p) v = NULL; argcount = r_long(p); + kwonlyargcount = r_long(p); nlocals = r_long(p); stacksize = r_long(p); flags = r_long(p); @@ -865,7 +868,8 @@ r_object(RFILE *p) goto code_error; v = (PyObject *) PyCode_New( - argcount, nlocals, stacksize, flags, + argcount, kwonlyargcount, + nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, firstlineno, lnotab); diff --git a/Python/symtable.c b/Python/symtable.c index 8f19e0b..b0ebed4 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -893,6 +893,17 @@ error: } \ } +#define VISIT_KWONLYDEFAULTS(ST, KW_DEFAULTS) { \ + int i = 0; \ + asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \ + for (i = 0; i < asdl_seq_LEN(seq); i++) { \ + expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ + if (!elt) continue; /* can be NULL */ \ + if (!symtable_visit_expr((ST), elt)) \ + return 0; \ + } \ +} + static int symtable_new_tmpname(struct symtable *st) { @@ -910,6 +921,8 @@ symtable_new_tmpname(struct symtable *st) return 1; } + + static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { @@ -919,6 +932,9 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) return 0; if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); + if (s->v.FunctionDef.args->kw_defaults) + VISIT_KWONLYDEFAULTS(st, + s->v.FunctionDef.args->kw_defaults); if (s->v.FunctionDef.decorators) VISIT_SEQ(st, expr, s->v.FunctionDef.decorators); if (!symtable_enter_block(st, s->v.FunctionDef.name, @@ -1262,6 +1278,8 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) */ if (a->args && !symtable_visit_params(st, a->args, 1)) return 0; + if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1)) + return 0; if (a->vararg) { if (!symtable_add_def(st, a->vararg, DEF_PARAM)) return 0; |