diff options
Diffstat (limited to 'Python/symtable.c')
-rw-r--r-- | Python/symtable.c | 1488 |
1 files changed, 573 insertions, 915 deletions
diff --git a/Python/symtable.c b/Python/symtable.c index b871358..23aeaaa 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1,51 +1,25 @@ #include "Python.h" -#include "pycore_pystate.h" +#include "Python-ast.h" +#include "code.h" #include "symtable.h" -#undef Yield /* undefine macro conflicting with <winbase.h> */ #include "structmember.h" /* error strings used for warnings */ -#define GLOBAL_PARAM \ -"name '%U' is parameter and global" - -#define NONLOCAL_PARAM \ -"name '%U' is parameter and nonlocal" - #define GLOBAL_AFTER_ASSIGN \ -"name '%U' is assigned to before global declaration" - -#define NONLOCAL_AFTER_ASSIGN \ -"name '%U' is assigned to before nonlocal declaration" +"name '%.400s' is assigned to before global declaration" #define GLOBAL_AFTER_USE \ -"name '%U' is used prior to global declaration" - -#define NONLOCAL_AFTER_USE \ -"name '%U' is used prior to nonlocal declaration" - -#define GLOBAL_ANNOT \ -"annotated name '%U' can't be global" - -#define NONLOCAL_ANNOT \ -"annotated name '%U' can't be nonlocal" +"name '%.400s' is used prior to global declaration" #define IMPORT_STAR_WARNING "import * only allowed at module level" -#define NAMED_EXPR_COMP_IN_CLASS \ -"assignment expression within a comprehension cannot be used in a class body" +#define RETURN_VAL_IN_GENERATOR \ + "'return' with argument inside generator" -#define NAMED_EXPR_COMP_CONFLICT \ -"assignment expression cannot rebind comprehension iteration variable '%U'" - -#define NAMED_EXPR_COMP_INNER_LOOP_CONFLICT \ -"comprehension inner loop cannot rebind assignment expression target '%U'" - -#define NAMED_EXPR_COMP_ITER_EXPR \ -"assignment expression cannot be used in a comprehension iterable expression" static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, - void *key, int lineno, int col_offset) + void *key, int lineno) { PySTEntryObject *ste = NULL; PyObject *k = NULL; @@ -61,24 +35,34 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_table = st; ste->ste_id = k; /* ste owns reference to k */ - Py_INCREF(name); ste->ste_name = name; + Py_INCREF(name); ste->ste_symbols = NULL; ste->ste_varnames = NULL; ste->ste_children = NULL; - ste->ste_directives = NULL; + ste->ste_symbols = PyDict_New(); + if (ste->ste_symbols == NULL) + goto fail; + + ste->ste_varnames = PyList_New(0); + if (ste->ste_varnames == NULL) + goto fail; + + ste->ste_children = PyList_New(0); + if (ste->ste_children == NULL) + goto fail; ste->ste_type = block; + ste->ste_unoptimized = 0; ste->ste_nested = 0; ste->ste_free = 0; ste->ste_varargs = 0; ste->ste_varkeywords = 0; ste->ste_opt_lineno = 0; - ste->ste_opt_col_offset = 0; + ste->ste_tmpname = 0; ste->ste_lineno = lineno; - ste->ste_col_offset = col_offset; if (st->st_cur != NULL && (st->st_cur->ste_nested || @@ -86,22 +70,9 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_nested = 1; ste->ste_child_free = 0; ste->ste_generator = 0; - ste->ste_coroutine = 0; - ste->ste_comprehension = 0; ste->ste_returns_value = 0; - ste->ste_needs_class_closure = 0; - ste->ste_comp_iter_target = 0; - ste->ste_comp_iter_expr = 0; - - ste->ste_symbols = PyDict_New(); - ste->ste_varnames = PyList_New(0); - ste->ste_children = PyList_New(0); - if (ste->ste_symbols == NULL - || ste->ste_varnames == NULL - || ste->ste_children == NULL) - goto fail; - if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0) + if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) goto fail; return ste; @@ -113,9 +84,13 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, static PyObject * ste_repr(PySTEntryObject *ste) { - return PyUnicode_FromFormat("<symtable entry %U(%ld), line %d>", - ste->ste_name, - PyLong_AS_LONG(ste->ste_id), ste->ste_lineno); + char buf[256]; + + PyOS_snprintf(buf, sizeof(buf), + "<symtable entry %.100s(%ld), line %d>", + PyString_AS_STRING(ste->ste_name), + PyInt_AS_LONG(ste->ste_id), ste->ste_lineno); + return PyString_FromString(buf); } static void @@ -127,7 +102,6 @@ ste_dealloc(PySTEntryObject *ste) Py_XDECREF(ste->ste_symbols); Py_XDECREF(ste->ste_varnames); Py_XDECREF(ste->ste_children); - Py_XDECREF(ste->ste_directives); PyObject_Del(ste); } @@ -139,6 +113,7 @@ static PyMemberDef ste_memberlist[] = { {"symbols", T_OBJECT, OFF(ste_symbols), READONLY}, {"varnames", T_OBJECT, OFF(ste_varnames), READONLY}, {"children", T_OBJECT, OFF(ste_children), READONLY}, + {"optimized",T_INT, OFF(ste_unoptimized), READONLY}, {"nested", T_INT, OFF(ste_nested), READONLY}, {"type", T_INT, OFF(ste_type), READONLY}, {"lineno", T_INT, OFF(ste_lineno), READONLY}, @@ -151,10 +126,10 @@ PyTypeObject PySTEntry_Type = { sizeof(PySTEntryObject), 0, (destructor)ste_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + 0, /* tp_compare */ (reprfunc)ste_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -187,38 +162,36 @@ PyTypeObject PySTEntry_Type = { }; static int symtable_analyze(struct symtable *st); +static int symtable_warn(struct symtable *st, + PyObject *warn, const char *msg, int lineno); static int symtable_enter_block(struct symtable *st, identifier name, - _Py_block_ty block, void *ast, int lineno, - int col_offset); + _Py_block_ty block, void *ast, int lineno); static int symtable_exit_block(struct symtable *st, void *ast); static int symtable_visit_stmt(struct symtable *st, stmt_ty s); static int symtable_visit_expr(struct symtable *st, expr_ty s); +static int symtable_visit_listcomp(struct symtable *st, expr_ty e); static int symtable_visit_genexp(struct symtable *st, expr_ty s); -static int symtable_visit_listcomp(struct symtable *st, expr_ty s); -static int symtable_visit_setcomp(struct symtable *st, expr_ty s); -static int symtable_visit_dictcomp(struct symtable *st, expr_ty s); +static int symtable_visit_setcomp(struct symtable *st, expr_ty e); +static int symtable_visit_dictcomp(struct symtable *st, expr_ty e); static int symtable_visit_arguments(struct symtable *st, arguments_ty); static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty); static int symtable_visit_alias(struct symtable *st, alias_ty); static int symtable_visit_comprehension(struct symtable *st, comprehension_ty); static int symtable_visit_keyword(struct symtable *st, keyword_ty); static int symtable_visit_slice(struct symtable *st, slice_ty); -static int symtable_visit_params(struct symtable *st, asdl_seq *args); -static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args); +static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top); +static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args); static int symtable_implicit_arg(struct symtable *st, int pos); -static int symtable_visit_annotations(struct symtable *st, stmt_ty s, arguments_ty, expr_ty); -static int symtable_visit_withitem(struct symtable *st, withitem_ty item); -static identifier top = NULL, lambda = NULL, genexpr = NULL, - listcomp = NULL, setcomp = NULL, dictcomp = NULL, - __class__ = NULL; +static identifier top = NULL, lambda = NULL, genexpr = NULL, setcomp = NULL, + dictcomp = NULL; #define GET_IDENTIFIER(VAR) \ - ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) + ((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR))) #define DUPLICATE_ARGUMENT \ -"duplicate argument '%U' in function definition" +"duplicate argument '%s' in function definition" static struct symtable * symtable_new(void) @@ -232,11 +205,11 @@ symtable_new(void) } st->st_filename = NULL; - st->st_blocks = NULL; + st->st_symbols = NULL; if ((st->st_stack = PyList_New(0)) == NULL) goto fail; - if ((st->st_blocks = PyDict_New()) == NULL) + if ((st->st_symbols = PyDict_New()) == NULL) goto fail; st->st_cur = NULL; st->st_private = NULL; @@ -246,59 +219,26 @@ symtable_new(void) return NULL; } -/* When compiling the use of C stack is probably going to be a lot - lighter than when executing Python code but still can overflow - and causing a Python crash if not checked (e.g. eval("()"*300000)). - Using the current recursion limit for the compiler seems too - restrictive (it caused at least one test to fail) so a factor is - used to allow deeper recursion when compiling an expression. - - Using a scaling factor means this should automatically adjust when - the recursion limit is adjusted for small or large C stack allocations. -*/ -#define COMPILER_STACK_FRAME_SCALE 3 - struct symtable * -PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) +PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { struct symtable *st = symtable_new(); asdl_seq *seq; int i; - PyThreadState *tstate; - int recursion_limit = Py_GetRecursionLimit(); - int starting_recursion_depth; if (st == NULL) - return NULL; - if (filename == NULL) { - PySymtable_Free(st); - return NULL; - } - Py_INCREF(filename); + return st; st->st_filename = filename; st->st_future = future; - - /* Setup recursion depth check counters */ - tstate = _PyThreadState_GET(); - if (!tstate) { - PySymtable_Free(st); - return NULL; - } - /* Be careful here to prevent overflow. */ - starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? - tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth; - st->recursion_depth = starting_recursion_depth; - st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? - recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; - - /* Make the initial symbol information gathering pass */ if (!GET_IDENTIFIER(top) || - !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0, 0)) { + !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) { PySymtable_Free(st); return NULL; } st->st_top = st->st_cur; + st->st_cur->ste_unoptimized = OPT_TOPLEVEL; + /* Any other top-level initialization? */ switch (mod->kind) { case Module_kind: seq = mod->v.Module.body; @@ -322,24 +262,11 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) PyErr_SetString(PyExc_RuntimeError, "this compiler does not handle Suites"); goto error; - case FunctionType_kind: - PyErr_SetString(PyExc_RuntimeError, - "this compiler does not handle FunctionTypes"); - goto error; } if (!symtable_exit_block(st, (void *)mod)) { PySymtable_Free(st); return NULL; } - /* Check that the recursion depth counting balanced correctly */ - if (st->recursion_depth != starting_recursion_depth) { - PyErr_Format(PyExc_SystemError, - "symtable analysis recursion depth mismatch (before=%d, after=%d)", - starting_recursion_depth, st->recursion_depth); - PySymtable_Free(st); - return NULL; - } - /* Make the second symbol analysis pass */ if (symtable_analyze(st)) return st; PySymtable_Free(st); @@ -350,24 +277,10 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } -struct symtable * -PySymtable_Build(mod_ty mod, const char *filename_str, PyFutureFeatures *future) -{ - PyObject *filename; - struct symtable *st; - filename = PyUnicode_DecodeFSDefault(filename_str); - if (filename == NULL) - return NULL; - st = PySymtable_BuildObject(mod, filename, future); - Py_DECREF(filename); - return st; -} - void PySymtable_Free(struct symtable *st) { - Py_XDECREF(st->st_filename); - Py_XDECREF(st->st_blocks); + Py_XDECREF(st->st_symbols); Py_XDECREF(st->st_stack); PyMem_Free((void *)st); } @@ -380,12 +293,12 @@ PySymtable_Lookup(struct symtable *st, void *key) k = PyLong_FromVoidPtr(key); if (k == NULL) return NULL; - v = PyDict_GetItemWithError(st->st_blocks, k); + v = PyDict_GetItem(st->st_symbols, k); if (v) { assert(PySTEntry_Check(v)); Py_INCREF(v); } - else if (!PyErr_Occurred()) { + else { PyErr_SetString(PyExc_KeyError, "unknown symbol table entry"); } @@ -394,55 +307,25 @@ PySymtable_Lookup(struct symtable *st, void *key) return (PySTEntryObject *)v; } -static long -_PyST_GetSymbol(PySTEntryObject *ste, PyObject *name) +int +PyST_GetScope(PySTEntryObject *ste, PyObject *name) { PyObject *v = PyDict_GetItem(ste->ste_symbols, name); if (!v) return 0; - assert(PyLong_Check(v)); - return PyLong_AS_LONG(v); -} - -int -PyST_GetScope(PySTEntryObject *ste, PyObject *name) -{ - long symbol = _PyST_GetSymbol(ste, name); - return (symbol >> SCOPE_OFFSET) & SCOPE_MASK; -} - -static int -error_at_directive(PySTEntryObject *ste, PyObject *name) -{ - Py_ssize_t i; - PyObject *data; - assert(ste->ste_directives); - for (i = 0; i < PyList_GET_SIZE(ste->ste_directives); i++) { - data = PyList_GET_ITEM(ste->ste_directives, i); - assert(PyTuple_CheckExact(data)); - assert(PyUnicode_CheckExact(PyTuple_GET_ITEM(data, 0))); - if (PyUnicode_Compare(PyTuple_GET_ITEM(data, 0), name) == 0) { - PyErr_SyntaxLocationObject(ste->ste_table->st_filename, - PyLong_AsLong(PyTuple_GET_ITEM(data, 1)), - PyLong_AsLong(PyTuple_GET_ITEM(data, 2)) + 1); - - return 0; - } - } - PyErr_SetString(PyExc_RuntimeError, - "BUG: internal directive bookkeeping broken"); - return 0; + assert(PyInt_Check(v)); + return (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK; } /* Analyze raw symbol information to determine scope of each name. - The next several functions are helpers for symtable_analyze(), + The next several functions are helpers for PySymtable_Analyze(), which determines whether a name is local, global, or free. In addition, it determines which local variables are cell variables; they provide bindings that are used for free variables in enclosed blocks. - There are also two kinds of global variables, implicit and explicit. An + There are also two kinds of free variables, implicit and explicit. An explicit global is declared with the global statement. An implicit global is a free variable for which the compiler has found no binding in an enclosing function scope. The implicit global is either a global @@ -452,36 +335,28 @@ error_at_directive(PySTEntryObject *ste, PyObject *name) is treated as a local. The symbol table requires two passes to determine the scope of each name. - The first pass collects raw facts from the AST via the symtable_visit_* - functions: the name is a parameter here, the name is used but not defined - here, etc. The second pass analyzes these facts during a pass over the - PySTEntryObjects created during pass 1. + The first pass collects raw facts from the AST: the name is a parameter + here, the name is used by not defined here, etc. The second pass analyzes + these facts during a pass over the PySTEntryObjects created during pass 1. When a function is entered during the second pass, the parent passes the set of all name bindings visible to its children. These bindings - are used to determine if non-local variables are free or implicit globals. - Names which are explicitly declared nonlocal must exist in this set of - visible names - if they do not, a syntax error is raised. After doing - the local analysis, it analyzes each of its child blocks using an - updated set of name bindings. - - The children update the free variable set. If a local variable is added to - the free variable set by the child, the variable is marked as a cell. The - function object being defined must provide runtime storage for the variable - that may outlive the function's frame. Cell variables are removed from the - free set before the analyze function returns to its parent. - - During analysis, the names are: - symbols: dict mapping from symbol names to flag values (including offset scope values) - scopes: dict mapping from symbol names to scope values (no offset) - local: set of all symbol names local to the current scope - bound: set of all symbol names local to a containing function scope - free: set of all symbol names referenced but not bound in child scopes - global: set of all symbol names explicitly declared as global + are used to determine if the variable is free or an implicit global. + After doing the local analysis, it analyzes each of its child blocks + using an updated set of name bindings. + + The children update the free variable set. If a local variable is free + in a child, the variable is marked as a cell. The current function must + provide runtime storage for the variable that may outlive the function's + frame. Cell variables are removed from the free set before the analyze + function returns to its parent. + + The sets of bound and free variables are implemented as dictionaries + mapping strings to None. */ #define SET_SCOPE(DICT, NAME, I) { \ - PyObject *o = PyLong_FromLong(I); \ + PyObject *o = PyInt_FromLong(I); \ if (!o) \ return 0; \ if (PyDict_SetItem((DICT), (NAME), o) < 0) { \ @@ -499,47 +374,37 @@ error_at_directive(PySTEntryObject *ste, PyObject *name) */ static int -analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, +analyze_name(PySTEntryObject *ste, PyObject *dict, PyObject *name, long flags, PyObject *bound, PyObject *local, PyObject *free, PyObject *global) { if (flags & DEF_GLOBAL) { - if (flags & DEF_NONLOCAL) { + if (flags & DEF_PARAM) { PyErr_Format(PyExc_SyntaxError, - "name '%U' is nonlocal and global", - name); - return error_at_directive(ste, name); - } - SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); - if (PySet_Add(global, name) < 0) - return 0; - if (bound && (PySet_Discard(bound, name) < 0)) + "name '%s' is local and global", + PyString_AS_STRING(name)); + PyErr_SyntaxLocation(ste->ste_table->st_filename, + ste->ste_lineno); + return 0; - return 1; - } - if (flags & DEF_NONLOCAL) { - if (!bound) { - PyErr_Format(PyExc_SyntaxError, - "nonlocal declaration not allowed at module level"); - return error_at_directive(ste, name); } - if (!PySet_Contains(bound, name)) { - PyErr_Format(PyExc_SyntaxError, - "no binding for nonlocal '%U' found", - name); - - return error_at_directive(ste, name); + SET_SCOPE(dict, name, GLOBAL_EXPLICIT); + if (PyDict_SetItem(global, name, Py_None) < 0) + return 0; + if (bound && PyDict_GetItem(bound, name)) { + if (PyDict_DelItem(bound, name) < 0) + return 0; } - SET_SCOPE(scopes, name, FREE); - ste->ste_free = 1; - return PySet_Add(free, name) >= 0; + return 1; } if (flags & DEF_BOUND) { - SET_SCOPE(scopes, name, LOCAL); - if (PySet_Add(local, name) < 0) - return 0; - if (PySet_Discard(global, name) < 0) + SET_SCOPE(dict, name, LOCAL); + if (PyDict_SetItem(local, name, Py_None) < 0) return 0; + if (PyDict_GetItem(global, name)) { + if (PyDict_DelItem(global, name) < 0) + return 0; + } return 1; } /* If an enclosing block has a binding for this name, it @@ -547,22 +412,30 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, Note that having a non-NULL bound implies that the block is nested. */ - if (bound && PySet_Contains(bound, name)) { - SET_SCOPE(scopes, name, FREE); + if (bound && PyDict_GetItem(bound, name)) { + SET_SCOPE(dict, name, FREE); ste->ste_free = 1; - return PySet_Add(free, name) >= 0; + if (PyDict_SetItem(free, name, Py_None) < 0) + return 0; + return 1; } /* If a parent has a global statement, then call it global explicit? It could also be global implicit. */ - if (global && PySet_Contains(global, name)) { - SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); + else if (global && PyDict_GetItem(global, name)) { + SET_SCOPE(dict, name, GLOBAL_IMPLICIT); return 1; } - if (ste->ste_nested) - ste->ste_free = 1; - SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); - return 1; + else { + if (ste->ste_nested) + ste->ste_free = 1; + SET_SCOPE(dict, name, GLOBAL_IMPLICIT); + return 1; + } + /* Should never get here. */ + PyErr_Format(PyExc_SystemError, "failed to set scope for %s", + PyString_AS_STRING(name)); + return 0; } #undef SET_SCOPE @@ -576,142 +449,153 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, */ static int -analyze_cells(PyObject *scopes, PyObject *free) +analyze_cells(PyObject *scope, PyObject *free) { - PyObject *name, *v, *v_cell; + PyObject *name, *v, *w; int success = 0; Py_ssize_t pos = 0; - v_cell = PyLong_FromLong(CELL); - if (!v_cell) + w = PyInt_FromLong(CELL); + if (!w) return 0; - while (PyDict_Next(scopes, &pos, &name, &v)) { - long scope; - assert(PyLong_Check(v)); - scope = PyLong_AS_LONG(v); - if (scope != LOCAL) + while (PyDict_Next(scope, &pos, &name, &v)) { + long flags; + assert(PyInt_Check(v)); + flags = PyInt_AS_LONG(v); + if (flags != LOCAL) continue; - if (!PySet_Contains(free, name)) + if (!PyDict_GetItem(free, name)) continue; /* Replace LOCAL with CELL for this name, and remove from free. It is safe to replace the value of name in the dict, because it will not cause a resize. */ - if (PyDict_SetItem(scopes, name, v_cell) < 0) + if (PyDict_SetItem(scope, name, w) < 0) goto error; - if (PySet_Discard(free, name) < 0) + if (PyDict_DelItem(free, name) < 0) goto error; } success = 1; error: - Py_DECREF(v_cell); + Py_DECREF(w); return success; } +/* Check for illegal statements in unoptimized namespaces */ static int -drop_class_free(PySTEntryObject *ste, PyObject *free) -{ - int res; - if (!GET_IDENTIFIER(__class__)) - return 0; - res = PySet_Discard(free, __class__); - if (res < 0) - return 0; - if (res) - ste->ste_needs_class_closure = 1; - return 1; +check_unoptimized(const PySTEntryObject* ste) { + char buf[300]; + const char* trailer; + + if (ste->ste_type != FunctionBlock || !ste->ste_unoptimized + || !(ste->ste_free || ste->ste_child_free)) + return 1; + + trailer = (ste->ste_child_free ? + "contains a nested function with free variables" : + "is a nested function"); + + switch (ste->ste_unoptimized) { + case OPT_TOPLEVEL: /* exec / import * at top-level is fine */ + case OPT_EXEC: /* qualified exec is fine */ + return 1; + case OPT_IMPORT_STAR: + PyOS_snprintf(buf, sizeof(buf), + "import * is not allowed in function '%.100s' " + "because it %s", + PyString_AS_STRING(ste->ste_name), trailer); + break; + case OPT_BARE_EXEC: + PyOS_snprintf(buf, sizeof(buf), + "unqualified exec is not allowed in function " + "'%.100s' because it %s", + PyString_AS_STRING(ste->ste_name), trailer); + break; + default: + PyOS_snprintf(buf, sizeof(buf), + "function '%.100s' uses import * and bare exec, " + "which are illegal because it %s", + PyString_AS_STRING(ste->ste_name), trailer); + break; + } + + PyErr_SetString(PyExc_SyntaxError, buf); + PyErr_SyntaxLocation(ste->ste_table->st_filename, + ste->ste_opt_lineno); + return 0; } -/* Enter the final scope information into the ste_symbols dict. +/* Enter the final scope information into the st_symbols dict. * * All arguments are dicts. Modifies symbols, others are read-only. */ static int -update_symbols(PyObject *symbols, PyObject *scopes, +update_symbols(PyObject *symbols, PyObject *scope, PyObject *bound, PyObject *free, int classflag) { - PyObject *name = NULL, *itr = NULL; - PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL; + PyObject *name, *v, *u, *w, *free_value = NULL; Py_ssize_t pos = 0; - /* Update scope information for all symbols in this scope */ while (PyDict_Next(symbols, &pos, &name, &v)) { - long scope, flags; - assert(PyLong_Check(v)); - flags = PyLong_AS_LONG(v); - v_scope = PyDict_GetItem(scopes, name); - assert(v_scope && PyLong_Check(v_scope)); - scope = PyLong_AS_LONG(v_scope); - flags |= (scope << SCOPE_OFFSET); - v_new = PyLong_FromLong(flags); - if (!v_new) + long i, flags; + assert(PyInt_Check(v)); + flags = PyInt_AS_LONG(v); + w = PyDict_GetItem(scope, name); + assert(w && PyInt_Check(w)); + i = PyInt_AS_LONG(w); + flags |= (i << SCOPE_OFF); + u = PyInt_FromLong(flags); + if (!u) return 0; - if (PyDict_SetItem(symbols, name, v_new) < 0) { - Py_DECREF(v_new); + if (PyDict_SetItem(symbols, name, u) < 0) { + Py_DECREF(u); return 0; } - Py_DECREF(v_new); + Py_DECREF(u); } - /* Record not yet resolved free variables from children (if any) */ - v_free = PyLong_FromLong(FREE << SCOPE_OFFSET); - if (!v_free) - return 0; - - itr = PyObject_GetIter(free); - if (itr == NULL) { - Py_DECREF(v_free); + free_value = PyInt_FromLong(FREE << SCOPE_OFF); + if (!free_value) return 0; - } - while ((name = PyIter_Next(itr))) { - v = PyDict_GetItemWithError(symbols, name); + /* add a free variable when it's only use is for creating a closure */ + pos = 0; + while (PyDict_Next(free, &pos, &name, &v)) { + PyObject *o = PyDict_GetItem(symbols, name); - /* Handle symbol that already exists in this scope */ - if (v) { - /* Handle a free variable in a method of + if (o) { + /* It could be a free variable in a method of the class that has the same name as a local or global in the class scope. */ if (classflag && - PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) { - long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS; - v_new = PyLong_FromLong(flags); - if (!v_new) { - goto error; + PyInt_AS_LONG(o) & (DEF_BOUND | DEF_GLOBAL)) { + long i = PyInt_AS_LONG(o) | DEF_FREE_CLASS; + o = PyInt_FromLong(i); + if (!o) { + Py_DECREF(free_value); + return 0; } - if (PyDict_SetItem(symbols, name, v_new) < 0) { - Py_DECREF(v_new); - goto error; + if (PyDict_SetItem(symbols, name, o) < 0) { + Py_DECREF(o); + Py_DECREF(free_value); + return 0; } - Py_DECREF(v_new); + Py_DECREF(o); } - /* It's a cell, or already free in this scope */ - Py_DECREF(name); + /* else it's not free, probably a cell */ continue; } - else if (PyErr_Occurred()) { - goto error; - } - /* Handle global symbol */ - if (bound && !PySet_Contains(bound, name)) { - Py_DECREF(name); + if (!PyDict_GetItem(bound, name)) continue; /* it's a global */ + + if (PyDict_SetItem(symbols, name, free_value) < 0) { + Py_DECREF(free_value); + return 0; } - /* Propagate new free symbol up the lexical stack */ - if (PyDict_SetItem(symbols, name, v_free) < 0) { - goto error; - } - Py_DECREF(name); } - Py_DECREF(itr); - Py_DECREF(v_free); + Py_DECREF(free_value); return 1; -error: - Py_XDECREF(v_free); - Py_XDECREF(itr); - Py_XDECREF(name); - return 0; } /* Make final symbol table decisions for block of ste. @@ -742,17 +626,17 @@ static int analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, PyObject *global) { - PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL, *allfree = NULL; - PyObject *temp; + PyObject *name, *v, *local = NULL, *scope = NULL; + PyObject *newbound = NULL, *newglobal = NULL; + PyObject *newfree = NULL, *allfree = NULL; int i, success = 0; Py_ssize_t pos = 0; - local = PySet_New(NULL); /* collect new names bound in block */ + local = PyDict_New(); /* collect new names bound in block */ if (!local) goto error; - scopes = PyDict_New(); /* collect scopes defined for each name */ - if (!scopes) + scope = PyDict_New(); /* collect scopes defined for each name */ + if (!scope) goto error; /* Allocate new global and bound variable dictionaries. These @@ -766,80 +650,51 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, /* TODO(jhylton): Package these dicts in a struct so that we can write reasonable helper functions? */ - newglobal = PySet_New(NULL); + newglobal = PyDict_New(); if (!newglobal) goto error; - newfree = PySet_New(NULL); - if (!newfree) - goto error; - newbound = PySet_New(NULL); + newbound = PyDict_New(); if (!newbound) goto error; + newfree = PyDict_New(); + if (!newfree) + goto error; - /* Class namespace has no effect on names visible in - nested functions, so populate the global and bound - sets to be passed to child blocks before analyzing - this one. - */ if (ste->ste_type == ClassBlock) { - /* Pass down known globals */ - temp = PyNumber_InPlaceOr(newglobal, global); - if (!temp) + if (PyDict_Update(newglobal, global) < 0) goto error; - Py_DECREF(temp); - /* Pass down previously bound symbols */ - if (bound) { - temp = PyNumber_InPlaceOr(newbound, bound); - if (!temp) + if (bound) + if (PyDict_Update(newbound, bound) < 0) goto error; - Py_DECREF(temp); - } } while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { - long flags = PyLong_AS_LONG(v); - if (!analyze_name(ste, scopes, name, flags, + long flags = PyInt_AS_LONG(v); + if (!analyze_name(ste, scope, name, flags, bound, local, free, global)) goto error; } - /* Populate global and bound sets to be passed to children. */ if (ste->ste_type != ClassBlock) { - /* Add function locals to bound set */ if (ste->ste_type == FunctionBlock) { - temp = PyNumber_InPlaceOr(newbound, local); - if (!temp) + if (PyDict_Update(newbound, local) < 0) goto error; - Py_DECREF(temp); } - /* Pass down previously bound symbols */ if (bound) { - temp = PyNumber_InPlaceOr(newbound, bound); - if (!temp) + if (PyDict_Update(newbound, bound) < 0) goto error; - Py_DECREF(temp); } - /* Pass down known globals */ - temp = PyNumber_InPlaceOr(newglobal, global); - if (!temp) - goto error; - Py_DECREF(temp); - } - else { - /* Special-case __class__ */ - if (!GET_IDENTIFIER(__class__)) - goto error; - if (PySet_Add(newbound, __class__) < 0) + if (PyDict_Update(newglobal, global) < 0) goto error; } - /* Recursively call analyze_child_block() on each child block. + /* Recursively call analyze_block() on each child block. newbound, newglobal now contain the names visible in nested blocks. The free variables in the children will be collected in allfree. */ - allfree = PySet_New(NULL); + allfree = PyDict_New(); if (!allfree) goto error; for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { @@ -850,34 +705,26 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, if (!analyze_child_block(entry, newbound, newfree, newglobal, allfree)) goto error; - /* Check if any children have free variables */ if (entry->ste_free || entry->ste_child_free) ste->ste_child_free = 1; } - temp = PyNumber_InPlaceOr(newfree, allfree); - if (!temp) - goto error; - Py_DECREF(temp); - - /* Check if any local variables must be converted to cell variables */ - if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree)) + if (PyDict_Update(newfree, allfree) < 0) goto error; - else if (ste->ste_type == ClassBlock && !drop_class_free(ste, newfree)) + if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree)) goto error; - /* Records the results of the analysis in the symbol table entry */ - if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, + if (!update_symbols(ste->ste_symbols, scope, bound, newfree, ste->ste_type == ClassBlock)) goto error; + if (!check_unoptimized(ste)) + goto error; - temp = PyNumber_InPlaceOr(free, newfree); - if (!temp) + if (PyDict_Update(free, newfree) < 0) goto error; - Py_DECREF(temp); success = 1; error: - Py_XDECREF(scopes); Py_XDECREF(local); + Py_XDECREF(scope); Py_XDECREF(newbound); Py_XDECREF(newglobal); Py_XDECREF(newfree); @@ -892,7 +739,6 @@ analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, PyObject *global, PyObject* child_free) { PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; - PyObject *temp; /* Copy the bound and global dictionaries. @@ -901,22 +747,26 @@ analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, dictionaries. */ - temp_bound = PySet_New(bound); + temp_bound = PyDict_New(); if (!temp_bound) goto error; - temp_free = PySet_New(free); + if (PyDict_Update(temp_bound, bound) < 0) + goto error; + temp_free = PyDict_New(); if (!temp_free) goto error; - temp_global = PySet_New(global); + if (PyDict_Update(temp_free, free) < 0) + goto error; + temp_global = PyDict_New(); if (!temp_global) goto error; + if (PyDict_Update(temp_global, global) < 0) + goto error; if (!analyze_block(entry, temp_bound, temp_free, temp_global)) goto error; - temp = PyNumber_InPlaceOr(child_free, temp_free); - if (!temp) + if (PyDict_Update(child_free, temp_free) < 0) goto error; - Py_DECREF(temp); Py_DECREF(temp_bound); Py_DECREF(temp_free); Py_DECREF(temp_global); @@ -934,10 +784,10 @@ symtable_analyze(struct symtable *st) PyObject *free, *global; int r; - free = PySet_New(NULL); + free = PyDict_New(); if (!free) return 0; - global = PySet_New(NULL); + global = PyDict_New(); if (!global) { Py_DECREF(free); return 0; @@ -948,6 +798,26 @@ symtable_analyze(struct symtable *st) return r; } + +static int +symtable_warn(struct symtable *st, PyObject *warn, const char *msg, int lineno) +{ + if (lineno < 0) { + lineno = st->st_cur->ste_lineno; + } + if (PyErr_WarnExplicit(warn, msg, st->st_filename, lineno, NULL, NULL) < 0) { + if (PyErr_ExceptionMatches(warn)) { + /* Replace the warning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); + PyErr_SetString(PyExc_SyntaxError, msg); + PyErr_SyntaxLocation(st->st_filename, lineno); + } + return 0; + } + return 1; +} + /* symtable_enter_block() gets a reference via ste_new. This reference is released when the block is exited, via the DECREF in symtable_exit_block(). @@ -956,47 +826,43 @@ symtable_analyze(struct symtable *st) static int symtable_exit_block(struct symtable *st, void *ast) { - Py_ssize_t size; - - st->st_cur = NULL; - size = PyList_GET_SIZE(st->st_stack); - if (size) { - if (PyList_SetSlice(st->st_stack, size - 1, size, NULL) < 0) + Py_ssize_t end; + + Py_CLEAR(st->st_cur); + end = PyList_GET_SIZE(st->st_stack) - 1; + if (end >= 0) { + st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, + end); + if (st->st_cur == NULL) + return 0; + Py_INCREF(st->st_cur); + if (PySequence_DelItem(st->st_stack, end) < 0) return 0; - if (--size) - st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, size - 1); } return 1; } static int symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, - void *ast, int lineno, int col_offset) + void *ast, int lineno) { - PySTEntryObject *prev = NULL, *ste; + PySTEntryObject *prev = NULL; - ste = ste_new(st, name, block, ast, lineno, col_offset); - if (ste == NULL) - return 0; - if (PyList_Append(st->st_stack, (PyObject *)ste) < 0) { - Py_DECREF(ste); - return 0; - } - prev = st->st_cur; - /* bpo-37757: For now, disallow *all* assignment expressions in the - * outermost iterator expression of a comprehension, even those inside - * a nested comprehension or a lambda expression. - */ - if (prev) { - ste->ste_comp_iter_expr = prev->ste_comp_iter_expr; + if (st->st_cur) { + prev = st->st_cur; + if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) { + return 0; + } + Py_DECREF(st->st_cur); } - /* The entry is owned by the stack. Borrow it for st_cur. */ - Py_DECREF(ste); - st->st_cur = ste; + st->st_cur = ste_new(st, name, block, ast, lineno); + if (st->st_cur == NULL) + return 0; if (block == ModuleBlock) st->st_global = st->st_cur->ste_symbols; if (prev) { - if (PyList_Append(prev->ste_children, (PyObject *)ste) < 0) { + if (PyList_Append(prev->ste_children, + (PyObject *)st->st_cur) < 0) { return 0; } } @@ -1006,61 +872,42 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, static long symtable_lookup(struct symtable *st, PyObject *name) { + PyObject *o; PyObject *mangled = _Py_Mangle(st->st_private, name); if (!mangled) return 0; - long ret = _PyST_GetSymbol(st->st_cur, mangled); + o = PyDict_GetItem(st->st_cur->ste_symbols, mangled); Py_DECREF(mangled); - return ret; + if (!o) + return 0; + return PyInt_AsLong(o); } static int -symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste) +symtable_add_def(struct symtable *st, PyObject *name, int flag) { PyObject *o; PyObject *dict; long val; PyObject *mangled = _Py_Mangle(st->st_private, name); - if (!mangled) return 0; - dict = ste->ste_symbols; - if ((o = PyDict_GetItemWithError(dict, mangled))) { - val = PyLong_AS_LONG(o); + dict = st->st_cur->ste_symbols; + if ((o = PyDict_GetItem(dict, mangled))) { + val = PyInt_AS_LONG(o); if ((flag & DEF_PARAM) && (val & DEF_PARAM)) { /* Is it better to use 'mangled' or 'name' here? */ - PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name); - PyErr_SyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1); + PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, + PyString_AsString(name)); + PyErr_SyntaxLocation(st->st_filename, + st->st_cur->ste_lineno); goto error; } val |= flag; - } - else if (PyErr_Occurred()) { - goto error; - } - else { + } else val = flag; - } - if (ste->ste_comp_iter_target) { - /* This name is an iteration variable in a comprehension, - * so check for a binding conflict with any named expressions. - * Otherwise, mark it as an iteration variable so subsequent - * named expressions can check for conflicts. - */ - if (val & (DEF_GLOBAL | DEF_NONLOCAL)) { - PyErr_Format(PyExc_SyntaxError, - NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name); - PyErr_SyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1); - goto error; - } - val |= DEF_COMP_ITER; - } - o = PyLong_FromLong(val); + o = PyInt_FromLong(val); if (o == NULL) goto error; if (PyDict_SetItem(dict, mangled, o) < 0) { @@ -1070,16 +917,16 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s Py_DECREF(o); if (flag & DEF_PARAM) { - if (PyList_Append(ste->ste_varnames, mangled) < 0) + if (PyList_Append(st->st_cur->ste_varnames, mangled) < 0) goto error; } else if (flag & DEF_GLOBAL) { /* XXX need to update DEF_GLOBAL for other flags too; perhaps only DEF_FREE_GLOBAL */ val = flag; if ((o = PyDict_GetItem(st->st_global, mangled))) { - val |= PyLong_AS_LONG(o); + val |= PyInt_AS_LONG(o); } - o = PyLong_FromLong(val); + o = PyInt_FromLong(val); if (o == NULL) goto error; if (PyDict_SetItem(st->st_global, mangled, o) < 0) { @@ -1096,28 +943,23 @@ error: return 0; } -static int -symtable_add_def(struct symtable *st, PyObject *name, int flag) { - return symtable_add_def_helper(st, name, flag, st->st_cur); -} - /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. They use the ASDL name to synthesize the name of the C type and the visit function. VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is useful if the first node in the sequence requires special treatment. - - VISIT_QUIT macro returns the specified value exiting from the function but - first adjusts current recursion counter depth. */ -#define VISIT_QUIT(ST, X) \ - return --(ST)->recursion_depth,(X) - #define VISIT(ST, TYPE, V) \ if (!symtable_visit_ ## TYPE((ST), (V))) \ - VISIT_QUIT((ST), 0); + return 0; + +#define VISIT_IN_BLOCK(ST, TYPE, V, S) \ + if (!symtable_visit_ ## TYPE((ST), (V))) { \ + symtable_exit_block((ST), (S)); \ + return 0; \ + } #define VISIT_SEQ(ST, TYPE, SEQ) { \ int i; \ @@ -1125,106 +967,92 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag) { for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - VISIT_QUIT((ST), 0); \ + return 0; \ } \ } -#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \ +#define VISIT_SEQ_IN_BLOCK(ST, TYPE, SEQ, S) { \ int i; \ asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = (START); i < asdl_seq_LEN(seq); i++) { \ + for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) \ - VISIT_QUIT((ST), 0); \ + if (!symtable_visit_ ## TYPE((ST), elt)) { \ + symtable_exit_block((ST), (S)); \ + return 0; \ + } \ } \ } -#define VISIT_SEQ_WITH_NULL(ST, TYPE, SEQ) { \ - int i = 0; \ +#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \ + int i; \ asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = 0; i < asdl_seq_LEN(seq); i++) { \ + for (i = (START); i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!elt) continue; /* can be NULL */ \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - VISIT_QUIT((ST), 0); \ + return 0; \ } \ } -static int -symtable_record_directive(struct symtable *st, identifier name, int lineno, int col_offset) -{ - PyObject *data, *mangled; - int res; - if (!st->st_cur->ste_directives) { - st->st_cur->ste_directives = PyList_New(0); - if (!st->st_cur->ste_directives) - return 0; - } - mangled = _Py_Mangle(st->st_private, name); - if (!mangled) - return 0; - data = Py_BuildValue("(Nii)", mangled, lineno, col_offset); - if (!data) - return 0; - res = PyList_Append(st->st_cur->ste_directives, data); - Py_DECREF(data); - return res == 0; +#define VISIT_SEQ_TAIL_IN_BLOCK(ST, TYPE, SEQ, START, S) { \ + int i; \ + asdl_seq *seq = (SEQ); /* avoid variable capture */ \ + for (i = (START); i < asdl_seq_LEN(seq); i++) { \ + TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ + if (!symtable_visit_ ## TYPE((ST), elt)) { \ + symtable_exit_block((ST), (S)); \ + return 0; \ + } \ + } \ } - static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { - if (++st->recursion_depth > st->recursion_limit) { - PyErr_SetString(PyExc_RecursionError, - "maximum recursion depth exceeded during compilation"); - VISIT_QUIT(st, 0); - } switch (s->kind) { case FunctionDef_kind: if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) - VISIT_QUIT(st, 0); + 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_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults); - if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args, - s->v.FunctionDef.returns)) - VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, - FunctionBlock, (void *)s, s->lineno, - s->col_offset)) - VISIT_QUIT(st, 0); - VISIT(st, arguments, s->v.FunctionDef.args); - VISIT_SEQ(st, stmt, s->v.FunctionDef.body); + FunctionBlock, (void *)s, s->lineno)) + return 0; + VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s); + VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s); if (!symtable_exit_block(st, s)) - VISIT_QUIT(st, 0); + return 0; break; case ClassDef_kind: { PyObject *tmp; if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) - VISIT_QUIT(st, 0); + return 0; VISIT_SEQ(st, expr, s->v.ClassDef.bases); - VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); if (s->v.ClassDef.decorator_list) VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, - (void *)s, s->lineno, s->col_offset)) - VISIT_QUIT(st, 0); + (void *)s, s->lineno)) + return 0; tmp = st->st_private; st->st_private = s->v.ClassDef.name; - VISIT_SEQ(st, stmt, s->v.ClassDef.body); + VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s); st->st_private = tmp; if (!symtable_exit_block(st, s)) - VISIT_QUIT(st, 0); + return 0; break; } case Return_kind: if (s->v.Return.value) { VISIT(st, expr, s->v.Return.value); st->st_cur->ste_returns_value = 1; + if (st->st_cur->ste_generator) { + PyErr_SetString(PyExc_SyntaxError, + RETURN_VAL_IN_GENERATOR); + PyErr_SyntaxLocation(st->st_filename, + s->lineno); + return 0; + } } break; case Delete_kind: @@ -1234,48 +1062,15 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.Assign.targets); VISIT(st, expr, s->v.Assign.value); break; - case AnnAssign_kind: - if (s->v.AnnAssign.target->kind == Name_kind) { - expr_ty e_name = s->v.AnnAssign.target; - long cur = symtable_lookup(st, e_name->v.Name.id); - if (cur < 0) { - VISIT_QUIT(st, 0); - } - if ((cur & (DEF_GLOBAL | DEF_NONLOCAL)) - && (st->st_cur->ste_symbols != st->st_global) - && s->v.AnnAssign.simple) { - PyErr_Format(PyExc_SyntaxError, - cur & DEF_GLOBAL ? GLOBAL_ANNOT : NONLOCAL_ANNOT, - e_name->v.Name.id); - PyErr_SyntaxLocationObject(st->st_filename, - s->lineno, - s->col_offset + 1); - VISIT_QUIT(st, 0); - } - if (s->v.AnnAssign.simple && - !symtable_add_def(st, e_name->v.Name.id, - DEF_ANNOT | DEF_LOCAL)) { - VISIT_QUIT(st, 0); - } - else { - if (s->v.AnnAssign.value - && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL)) { - VISIT_QUIT(st, 0); - } - } - } - else { - VISIT(st, expr, s->v.AnnAssign.target); - } - VISIT(st, expr, s->v.AnnAssign.annotation); - if (s->v.AnnAssign.value) { - VISIT(st, expr, s->v.AnnAssign.value); - } - break; case AugAssign_kind: VISIT(st, expr, s->v.AugAssign.target); VISIT(st, expr, s->v.AugAssign.value); break; + case Print_kind: + if (s->v.Print.dest) + VISIT(st, expr, s->v.Print.dest); + VISIT_SEQ(st, expr, s->v.Print.values); + break; case For_kind: VISIT(st, expr, s->v.For.target); VISIT(st, expr, s->v.For.iter); @@ -1297,18 +1092,23 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.If.orelse); break; case Raise_kind: - if (s->v.Raise.exc) { - VISIT(st, expr, s->v.Raise.exc); - if (s->v.Raise.cause) { - VISIT(st, expr, s->v.Raise.cause); + if (s->v.Raise.type) { + VISIT(st, expr, s->v.Raise.type); + if (s->v.Raise.inst) { + VISIT(st, expr, s->v.Raise.inst); + if (s->v.Raise.tback) + VISIT(st, expr, s->v.Raise.tback); } } break; - case Try_kind: - VISIT_SEQ(st, stmt, s->v.Try.body); - VISIT_SEQ(st, stmt, s->v.Try.orelse); - VISIT_SEQ(st, excepthandler, s->v.Try.handlers); - VISIT_SEQ(st, stmt, s->v.Try.finalbody); + case TryExcept_kind: + VISIT_SEQ(st, stmt, s->v.TryExcept.body); + VISIT_SEQ(st, stmt, s->v.TryExcept.orelse); + VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers); + break; + case TryFinally_kind: + VISIT_SEQ(st, stmt, s->v.TryFinally.body); + VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody); break; case Assert_kind: VISIT(st, expr, s->v.Assert.test); @@ -1317,72 +1117,55 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) break; case Import_kind: VISIT_SEQ(st, alias, s->v.Import.names); + /* XXX Don't have the lineno available inside + visit_alias */ + if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) + st->st_cur->ste_opt_lineno = s->lineno; break; case ImportFrom_kind: VISIT_SEQ(st, alias, s->v.ImportFrom.names); + /* XXX Don't have the lineno available inside + visit_alias */ + if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) + st->st_cur->ste_opt_lineno = s->lineno; + break; + case Exec_kind: + VISIT(st, expr, s->v.Exec.body); + if (!st->st_cur->ste_opt_lineno) + st->st_cur->ste_opt_lineno = s->lineno; + if (s->v.Exec.globals) { + st->st_cur->ste_unoptimized |= OPT_EXEC; + VISIT(st, expr, s->v.Exec.globals); + if (s->v.Exec.locals) + VISIT(st, expr, s->v.Exec.locals); + } else { + st->st_cur->ste_unoptimized |= OPT_BARE_EXEC; + } break; case Global_kind: { int i; asdl_seq *seq = s->v.Global.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); + char *c_name = PyString_AS_STRING(name); long cur = symtable_lookup(st, name); if (cur < 0) - VISIT_QUIT(st, 0); - if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) { - const char* msg; - if (cur & DEF_PARAM) { - msg = GLOBAL_PARAM; - } else if (cur & USE) { - msg = GLOBAL_AFTER_USE; - } else if (cur & DEF_ANNOT) { - msg = GLOBAL_ANNOT; - } else { /* DEF_LOCAL */ - msg = GLOBAL_AFTER_ASSIGN; - } - PyErr_Format(PyExc_SyntaxError, - msg, name); - PyErr_SyntaxLocationObject(st->st_filename, - s->lineno, - s->col_offset + 1); - VISIT_QUIT(st, 0); + return 0; + if (cur & (DEF_LOCAL | USE)) { + char buf[256]; + if (cur & DEF_LOCAL) + PyOS_snprintf(buf, sizeof(buf), + GLOBAL_AFTER_ASSIGN, + c_name); + else + PyOS_snprintf(buf, sizeof(buf), + GLOBAL_AFTER_USE, + c_name); + if (!symtable_warn(st, PyExc_SyntaxWarning, buf, s->lineno)) + return 0; } if (!symtable_add_def(st, name, DEF_GLOBAL)) - VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, name, s->lineno, s->col_offset)) - VISIT_QUIT(st, 0); - } - break; - } - case Nonlocal_kind: { - int i; - asdl_seq *seq = s->v.Nonlocal.names; - for (i = 0; i < asdl_seq_LEN(seq); i++) { - identifier name = (identifier)asdl_seq_GET(seq, i); - long cur = symtable_lookup(st, name); - if (cur < 0) - VISIT_QUIT(st, 0); - if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) { - const char* msg; - if (cur & DEF_PARAM) { - msg = NONLOCAL_PARAM; - } else if (cur & USE) { - msg = NONLOCAL_AFTER_USE; - } else if (cur & DEF_ANNOT) { - msg = NONLOCAL_ANNOT; - } else { /* DEF_LOCAL */ - msg = NONLOCAL_AFTER_ASSIGN; - } - PyErr_Format(PyExc_SyntaxError, msg, name); - PyErr_SyntaxLocationObject(st->st_filename, - s->lineno, - s->col_offset + 1); - VISIT_QUIT(st, 0); - } - if (!symtable_add_def(st, name, DEF_NONLOCAL)) - VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, name, s->lineno, s->col_offset)) - VISIT_QUIT(st, 0); + return 0; } break; } @@ -1395,153 +1178,20 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) /* nothing to do here */ break; case With_kind: - VISIT_SEQ(st, withitem, s->v.With.items); + VISIT(st, expr, s->v.With.context_expr); + if (s->v.With.optional_vars) { + VISIT(st, expr, s->v.With.optional_vars); + } VISIT_SEQ(st, stmt, s->v.With.body); break; - case AsyncFunctionDef_kind: - if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL)) - VISIT_QUIT(st, 0); - if (s->v.AsyncFunctionDef.args->defaults) - VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults); - if (s->v.AsyncFunctionDef.args->kw_defaults) - VISIT_SEQ_WITH_NULL(st, expr, - s->v.AsyncFunctionDef.args->kw_defaults); - if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args, - s->v.AsyncFunctionDef.returns)) - VISIT_QUIT(st, 0); - if (s->v.AsyncFunctionDef.decorator_list) - VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list); - if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name, - FunctionBlock, (void *)s, s->lineno, - s->col_offset)) - VISIT_QUIT(st, 0); - st->st_cur->ste_coroutine = 1; - VISIT(st, arguments, s->v.AsyncFunctionDef.args); - VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body); - if (!symtable_exit_block(st, s)) - VISIT_QUIT(st, 0); - break; - case AsyncWith_kind: - VISIT_SEQ(st, withitem, s->v.AsyncWith.items); - VISIT_SEQ(st, stmt, s->v.AsyncWith.body); - break; - case AsyncFor_kind: - VISIT(st, expr, s->v.AsyncFor.target); - VISIT(st, expr, s->v.AsyncFor.iter); - VISIT_SEQ(st, stmt, s->v.AsyncFor.body); - if (s->v.AsyncFor.orelse) - VISIT_SEQ(st, stmt, s->v.AsyncFor.orelse); - break; - } - VISIT_QUIT(st, 1); -} - -static int -symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) -{ - assert(st->st_stack); - assert(e->kind == Name_kind); - - PyObject *target_name = e->v.Name.id; - Py_ssize_t i, size; - struct _symtable_entry *ste; - size = PyList_GET_SIZE(st->st_stack); - assert(size); - - /* Iterate over the stack in reverse and add to the nearest adequate scope */ - for (i = size - 1; i >= 0; i--) { - ste = (struct _symtable_entry *) PyList_GET_ITEM(st->st_stack, i); - - /* If we find a comprehension scope, check for a target - * binding conflict with iteration variables, otherwise skip it - */ - if (ste->ste_comprehension) { - long target_in_scope = _PyST_GetSymbol(ste, target_name); - if (target_in_scope & DEF_COMP_ITER) { - PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT, target_name); - PyErr_SyntaxLocationObject(st->st_filename, - e->lineno, - e->col_offset); - VISIT_QUIT(st, 0); - } - continue; - } - - /* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */ - if (ste->ste_type == FunctionBlock) { - long target_in_scope = _PyST_GetSymbol(ste, target_name); - if (target_in_scope & DEF_GLOBAL) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) - VISIT_QUIT(st, 0); - } else { - if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) - VISIT_QUIT(st, 0); - } - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) - VISIT_QUIT(st, 0); - - return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste); - } - /* If we find a ModuleBlock entry, add as GLOBAL */ - if (ste->ste_type == ModuleBlock) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) - VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) - VISIT_QUIT(st, 0); - - return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste); - } - /* Disallow usage in ClassBlock */ - if (ste->ste_type == ClassBlock) { - PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS); - PyErr_SyntaxLocationObject(st->st_filename, - e->lineno, - e->col_offset); - VISIT_QUIT(st, 0); - } - } - - /* We should always find either a FunctionBlock, ModuleBlock or ClassBlock - and should never fall to this case - */ - assert(0); - return 0; -} - -static int -symtable_handle_namedexpr(struct symtable *st, expr_ty e) -{ - if (st->st_cur->ste_comp_iter_expr > 0) { - /* Assignment isn't allowed in a comprehension iterable expression */ - PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_ITER_EXPR); - PyErr_SyntaxLocationObject(st->st_filename, - e->lineno, - e->col_offset); - return 0; } - if (st->st_cur->ste_comprehension) { - /* Inside a comprehension body, so find the right target scope */ - if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) - return 0; - } - VISIT(st, expr, e->v.NamedExpr.value); - VISIT(st, expr, e->v.NamedExpr.target); return 1; } static int symtable_visit_expr(struct symtable *st, expr_ty e) { - if (++st->recursion_depth > st->recursion_limit) { - PyErr_SetString(PyExc_RecursionError, - "maximum recursion depth exceeded during compilation"); - VISIT_QUIT(st, 0); - } switch (e->kind) { - case NamedExpr_kind: - if(!symtable_handle_namedexpr(st, e)) - VISIT_QUIT(st, 0); - break; case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); break; @@ -1554,19 +1204,16 @@ symtable_visit_expr(struct symtable *st, expr_ty e) break; case Lambda_kind: { if (!GET_IDENTIFIER(lambda)) - VISIT_QUIT(st, 0); + return 0; if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); - if (e->v.Lambda.args->kw_defaults) - VISIT_SEQ_WITH_NULL(st, expr, e->v.Lambda.args->kw_defaults); if (!symtable_enter_block(st, lambda, - FunctionBlock, (void *)e, e->lineno, - e->col_offset)) - VISIT_QUIT(st, 0); - VISIT(st, arguments, e->v.Lambda.args); - VISIT(st, expr, e->v.Lambda.body); + FunctionBlock, (void *)e, e->lineno)) + return 0; + VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); + VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); if (!symtable_exit_block(st, (void *)e)) - VISIT_QUIT(st, 0); + return 0; break; } case IfExp_kind: @@ -1575,40 +1222,39 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.IfExp.orelse); break; case Dict_kind: - VISIT_SEQ_WITH_NULL(st, expr, e->v.Dict.keys); + VISIT_SEQ(st, expr, e->v.Dict.keys); VISIT_SEQ(st, expr, e->v.Dict.values); break; case Set_kind: VISIT_SEQ(st, expr, e->v.Set.elts); break; - case GeneratorExp_kind: - if (!symtable_visit_genexp(st, e)) - VISIT_QUIT(st, 0); - break; case ListComp_kind: if (!symtable_visit_listcomp(st, e)) - VISIT_QUIT(st, 0); + return 0; + break; + case GeneratorExp_kind: + if (!symtable_visit_genexp(st, e)) + return 0; break; case SetComp_kind: if (!symtable_visit_setcomp(st, e)) - VISIT_QUIT(st, 0); + return 0; break; case DictComp_kind: if (!symtable_visit_dictcomp(st, e)) - VISIT_QUIT(st, 0); + return 0; break; case Yield_kind: if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; - break; - case YieldFrom_kind: - VISIT(st, expr, e->v.YieldFrom.value); - st->st_cur->ste_generator = 1; - break; - case Await_kind: - VISIT(st, expr, e->v.Await.value); - st->st_cur->ste_coroutine = 1; + if (st->st_cur->ste_returns_value) { + PyErr_SetString(PyExc_SyntaxError, + RETURN_VAL_IN_GENERATOR); + PyErr_SyntaxLocation(st->st_filename, + e->lineno); + return 0; + } break; case Compare_kind: VISIT(st, expr, e->v.Compare.left); @@ -1617,17 +1263,17 @@ symtable_visit_expr(struct symtable *st, expr_ty e) case Call_kind: VISIT(st, expr, e->v.Call.func); VISIT_SEQ(st, expr, e->v.Call.args); - VISIT_SEQ_WITH_NULL(st, keyword, e->v.Call.keywords); - break; - case FormattedValue_kind: - VISIT(st, expr, e->v.FormattedValue.value); - if (e->v.FormattedValue.format_spec) - VISIT(st, expr, e->v.FormattedValue.format_spec); + VISIT_SEQ(st, keyword, e->v.Call.keywords); + if (e->v.Call.starargs) + VISIT(st, expr, e->v.Call.starargs); + if (e->v.Call.kwargs) + VISIT(st, expr, e->v.Call.kwargs); break; - case JoinedStr_kind: - VISIT_SEQ(st, expr, e->v.JoinedStr.values); + case Repr_kind: + VISIT(st, expr, e->v.Repr.value); break; - case Constant_kind: + case Num_kind: + case Str_kind: /* Nothing to do here. */ break; /* The following exprs can be assignment targets. */ @@ -1638,21 +1284,10 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.Subscript.value); VISIT(st, slice, e->v.Subscript.slice); break; - case Starred_kind: - VISIT(st, expr, e->v.Starred.value); - break; case Name_kind: if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) - VISIT_QUIT(st, 0); - /* Special-case super: it counts as a use of __class__ */ - if (e->v.Name.ctx == Load && - st->st_cur->ste_type == FunctionBlock && - _PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) { - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) - VISIT_QUIT(st, 0); - } + return 0; break; /* child nodes of List and Tuple will have expr_context set */ case List_kind: @@ -1662,13 +1297,13 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_SEQ(st, expr, e->v.Tuple.elts); break; } - VISIT_QUIT(st, 1); + return 1; } static int symtable_implicit_arg(struct symtable *st, int pos) { - PyObject *id = PyUnicode_FromFormat(".%d", pos); + PyObject *id = PyString_FromFormat(".%d", pos); if (id == NULL) return 0; if (!symtable_add_def(st, id, DEF_PARAM)) { @@ -1680,16 +1315,37 @@ symtable_implicit_arg(struct symtable *st, int pos) } static int -symtable_visit_params(struct symtable *st, asdl_seq *args) +symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel) { int i; - if (!args) - return -1; - + /* go through all the toplevel arguments first */ for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (!symtable_add_def(st, arg->arg, DEF_PARAM)) + expr_ty arg = (expr_ty)asdl_seq_GET(args, i); + if (arg->kind == Name_kind) { + assert(arg->v.Name.ctx == Param || + (arg->v.Name.ctx == Store && !toplevel)); + if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM)) + return 0; + } + else if (arg->kind == Tuple_kind) { + assert(arg->v.Tuple.ctx == Store); + if (toplevel) { + if (!symtable_implicit_arg(st, i)) + return 0; + } + } + else { + PyErr_SetString(PyExc_SyntaxError, + "invalid expression in parameter list"); + PyErr_SyntaxLocation(st->st_filename, + st->st_cur->ste_lineno); + return 0; + } + } + + if (!toplevel) { + if (!symtable_visit_params_nested(st, args)) return 0; } @@ -1697,61 +1353,39 @@ symtable_visit_params(struct symtable *st, asdl_seq *args) } static int -symtable_visit_argannotations(struct symtable *st, asdl_seq *args) +symtable_visit_params_nested(struct symtable *st, asdl_seq *args) { int i; - - if (!args) - return -1; - for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (arg->annotation) - VISIT(st, expr, arg->annotation); + expr_ty arg = (expr_ty)asdl_seq_GET(args, i); + if (arg->kind == Tuple_kind && + !symtable_visit_params(st, arg->v.Tuple.elts, 0)) + return 0; } return 1; } static int -symtable_visit_annotations(struct symtable *st, stmt_ty s, - arguments_ty a, expr_ty returns) -{ - if (a->args && !symtable_visit_argannotations(st, a->args)) - return 0; - if (a->vararg && a->vararg->annotation) - VISIT(st, expr, a->vararg->annotation); - if (a->kwarg && a->kwarg->annotation) - VISIT(st, expr, a->kwarg->annotation); - if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs)) - return 0; - if (returns) - VISIT(st, expr, returns); - return 1; -} - -static int symtable_visit_arguments(struct symtable *st, arguments_ty a) { /* skip default arguments inside function block XXX should ast be different? */ - if (a->posonlyargs && !symtable_visit_params(st, a->posonlyargs)) - return 0; - if (a->args && !symtable_visit_params(st, a->args)) - return 0; - if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) + if (a->args && !symtable_visit_params(st, a->args, 1)) return 0; if (a->vararg) { - if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->vararg, DEF_PARAM)) return 0; st->st_cur->ste_varargs = 1; } if (a->kwarg) { - if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->kwarg, DEF_PARAM)) return 0; st->st_cur->ste_varkeywords = 1; } + if (a->args && !symtable_visit_params_nested(st, a->args)) + return 0; return 1; } @@ -1762,22 +1396,11 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) if (eh->v.ExceptHandler.type) VISIT(st, expr, eh->v.ExceptHandler.type); if (eh->v.ExceptHandler.name) - if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) - return 0; + VISIT(st, expr, eh->v.ExceptHandler.name); VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); return 1; } -static int -symtable_visit_withitem(struct symtable *st, withitem_ty item) -{ - VISIT(st, expr, item->context_expr); - if (item->optional_vars) { - VISIT(st, expr, item->optional_vars); - } - return 1; -} - static int symtable_visit_alias(struct symtable *st, alias_ty a) @@ -1788,10 +1411,10 @@ symtable_visit_alias(struct symtable *st, alias_ty a) */ PyObject *store_name; PyObject *name = (a->asname == NULL) ? a->name : a->asname; - Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, - PyUnicode_GET_LENGTH(name), 1); - if (dot != -1) { - store_name = PyUnicode_Substring(name, 0, dot); + const char *base = PyString_AS_STRING(name); + char *dot = strchr(base, '.'); + if (dot) { + store_name = PyString_FromStringAndSize(base, dot - base); if (!store_name) return 0; } @@ -1799,20 +1422,19 @@ symtable_visit_alias(struct symtable *st, alias_ty a) store_name = name; Py_INCREF(store_name); } - if (!_PyUnicode_EqualToASCIIString(name, "*")) { + if (strcmp(PyString_AS_STRING(name), "*")) { int r = symtable_add_def(st, store_name, DEF_IMPORT); Py_DECREF(store_name); return r; } else { - if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - int col_offset = st->st_cur->ste_col_offset; - PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); - PyErr_SyntaxLocationObject(st->st_filename, lineno, col_offset + 1); + if (st->st_cur->ste_type != ModuleBlock && + !symtable_warn(st, PyExc_SyntaxWarning, IMPORT_STAR_WARNING, -1)) + { Py_DECREF(store_name); return 0; } + st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; Py_DECREF(store_name); return 1; } @@ -1822,16 +1444,9 @@ symtable_visit_alias(struct symtable *st, alias_ty a) static int symtable_visit_comprehension(struct symtable *st, comprehension_ty lc) { - st->st_cur->ste_comp_iter_target = 1; VISIT(st, expr, lc->target); - st->st_cur->ste_comp_iter_target = 0; - st->st_cur->ste_comp_iter_expr++; VISIT(st, expr, lc->iter); - st->st_cur->ste_comp_iter_expr--; VISIT_SEQ(st, expr, lc->ifs); - if (lc->is_async) { - st->st_cur->ste_coroutine = 1; - } return 1; } @@ -1862,78 +1477,121 @@ symtable_visit_slice(struct symtable *st, slice_ty s) case Index_kind: VISIT(st, expr, s->v.Index.value) break; + case Ellipsis_kind: + break; } return 1; } static int +symtable_new_tmpname(struct symtable *st) +{ + char tmpname[256]; + identifier tmp; + + PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", + ++st->st_cur->ste_tmpname); + tmp = PyString_InternFromString(tmpname); + if (!tmp) + return 0; + if (!symtable_add_def(st, tmp, DEF_LOCAL)) + return 0; + Py_DECREF(tmp); + return 1; +} + +static int symtable_handle_comprehension(struct symtable *st, expr_ty e, identifier scope_name, asdl_seq *generators, expr_ty elt, expr_ty value) { int is_generator = (e->kind == GeneratorExp_kind); + int needs_tmp = !is_generator; comprehension_ty outermost = ((comprehension_ty) asdl_seq_GET(generators, 0)); /* Outermost iterator is evaluated in current scope */ - st->st_cur->ste_comp_iter_expr++; VISIT(st, expr, outermost->iter); - st->st_cur->ste_comp_iter_expr--; /* Create comprehension scope for the rest */ if (!scope_name || - !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, - e->lineno, e->col_offset)) { + !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, 0)) { return 0; } - if (outermost->is_async) { - st->st_cur->ste_coroutine = 1; - } - st->st_cur->ste_comprehension = 1; - + /* In order to check for yield expressions under '-3', we clear + the generator flag, and restore it at the end */ + is_generator |= st->st_cur->ste_generator; + st->st_cur->ste_generator = 0; /* Outermost iter is received as an argument */ if (!symtable_implicit_arg(st, 0)) { symtable_exit_block(st, (void *)e); return 0; } - /* Visit iteration variable target, and mark them as such */ - st->st_cur->ste_comp_iter_target = 1; - VISIT(st, expr, outermost->target); - st->st_cur->ste_comp_iter_target = 0; - /* Visit the rest of the comprehension body */ - VISIT_SEQ(st, expr, outermost->ifs); - VISIT_SEQ_TAIL(st, comprehension, generators, 1); + /* Allocate temporary name if needed */ + if (needs_tmp && !symtable_new_tmpname(st)) { + symtable_exit_block(st, (void *)e); + return 0; + } + VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e); + VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e); + VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension, + generators, 1, (void*)e); if (value) - VISIT(st, expr, value); - VISIT(st, expr, elt); - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - (e->kind == ListComp_kind) ? "'yield' inside list comprehension" : + VISIT_IN_BLOCK(st, expr, value, (void*)e); + VISIT_IN_BLOCK(st, expr, elt, (void*)e); + if (Py_Py3kWarningFlag && st->st_cur->ste_generator) { + const char *msg = ( (e->kind == SetComp_kind) ? "'yield' inside set comprehension" : (e->kind == DictComp_kind) ? "'yield' inside dict comprehension" : "'yield' inside generator expression"); - PyErr_SyntaxLocationObject(st->st_filename, - st->st_cur->ste_lineno, - st->st_cur->ste_col_offset + 1); - symtable_exit_block(st, (void *)e); - return 0; + if (!symtable_warn(st, PyExc_DeprecationWarning, msg, -1)) { + symtable_exit_block(st, (void *)e); + return 0; + } } - st->st_cur->ste_generator = is_generator; + st->st_cur->ste_generator |= is_generator; return symtable_exit_block(st, (void *)e); } static int -symtable_visit_genexp(struct symtable *st, expr_ty e) +symtable_visit_listcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr), - e->v.GeneratorExp.generators, - e->v.GeneratorExp.elt, NULL); + asdl_seq *generators = e->v.ListComp.generators; + int i, is_generator; + /* In order to check for yield expressions under '-3', we clear + the generator flag, and restore it at the end */ + is_generator = st->st_cur->ste_generator; + st->st_cur->ste_generator = 0; + VISIT(st, expr, e->v.ListComp.elt); + for (i = 0; i < asdl_seq_LEN(generators); i++) { + comprehension_ty lc = (comprehension_ty)asdl_seq_GET(generators, i); + VISIT(st, expr, lc->target); + if (i == 0 && !st->st_cur->ste_generator) { + /* 'yield' in the outermost iterator doesn't cause a warning */ + VISIT(st, expr, lc->iter); + is_generator |= st->st_cur->ste_generator; + st->st_cur->ste_generator = 0; + } + else { + VISIT(st, expr, lc->iter); + } + VISIT_SEQ(st, expr, lc->ifs); + } + + if (Py_Py3kWarningFlag && st->st_cur->ste_generator) { + const char *msg = "'yield' inside list comprehension"; + if (!symtable_warn(st, PyExc_DeprecationWarning, msg, -1)) { + return 0; + } + } + st->st_cur->ste_generator |= is_generator; + return 1; } static int -symtable_visit_listcomp(struct symtable *st, expr_ty e) +symtable_visit_genexp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, GET_IDENTIFIER(listcomp), - e->v.ListComp.generators, - e->v.ListComp.elt, NULL); + return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr), + e->v.GeneratorExp.generators, + e->v.GeneratorExp.elt, NULL); } static int |