mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +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
|
@ -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)
|
||||
|
|
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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -1346,6 +1348,25 @@ compiler_arguments(struct compiler *c, arguments_ty args)
|
|||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
|
|
@ -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_8[2] = {
|
||||
{27, 5},
|
||||
{0, 8},
|
||||
};
|
||||
static arc arcs_7_9[1] = {
|
||||
static arc arcs_7_7[2] = {
|
||||
{19, 10},
|
||||
{29, 3},
|
||||
};
|
||||
static state states_7[10] = {
|
||||
static arc arcs_7_8[1] = {
|
||||
{0, 8},
|
||||
};
|
||||
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[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"},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue