summaryrefslogtreecommitdiffstats
path: root/Python/symtable.c
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-05-09 15:52:27 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-05-09 15:52:27 (GMT)
commitf95a1b3c53bdd678b64aa608d4375660033460c3 (patch)
treea8bee40b1b14e28ff5978ea519f3035a3c399912 /Python/symtable.c
parentbd250300191133d276a71b395b6428081bf825b8 (diff)
downloadcpython-f95a1b3c53bdd678b64aa608d4375660033460c3.zip
cpython-f95a1b3c53bdd678b64aa608d4375660033460c3.tar.gz
cpython-f95a1b3c53bdd678b64aa608d4375660033460c3.tar.bz2
Recorded merge of revisions 81029 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines Untabify C files. Will watch buildbots. ........
Diffstat (limited to 'Python/symtable.c')
-rw-r--r--Python/symtable.c2614
1 files changed, 1307 insertions, 1307 deletions
diff --git a/Python/symtable.c b/Python/symtable.c
index 7fa01b8..83f0231 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -25,145 +25,145 @@
static PySTEntryObject *
ste_new(struct symtable *st, identifier name, _Py_block_ty block,
- void *key, int lineno)
+ void *key, int lineno)
{
- PySTEntryObject *ste = NULL;
- PyObject *k;
-
- k = PyLong_FromVoidPtr(key);
- if (k == NULL)
- goto fail;
- ste = PyObject_New(PySTEntryObject, &PySTEntry_Type);
- if (ste == NULL)
- goto fail;
- ste->ste_table = st;
- ste->ste_id = k;
-
- ste->ste_name = name;
- Py_INCREF(name);
-
- ste->ste_symbols = NULL;
- ste->ste_varnames = NULL;
- ste->ste_children = 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_lineno = lineno;
-
- if (st->st_cur != NULL &&
- (st->st_cur->ste_nested ||
- st->st_cur->ste_type == FunctionBlock))
- ste->ste_nested = 1;
- ste->ste_child_free = 0;
- ste->ste_generator = 0;
- ste->ste_returns_value = 0;
-
- if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0)
- goto fail;
-
- return ste;
+ PySTEntryObject *ste = NULL;
+ PyObject *k;
+
+ k = PyLong_FromVoidPtr(key);
+ if (k == NULL)
+ goto fail;
+ ste = PyObject_New(PySTEntryObject, &PySTEntry_Type);
+ if (ste == NULL)
+ goto fail;
+ ste->ste_table = st;
+ ste->ste_id = k;
+
+ ste->ste_name = name;
+ Py_INCREF(name);
+
+ ste->ste_symbols = NULL;
+ ste->ste_varnames = NULL;
+ ste->ste_children = 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_lineno = lineno;
+
+ if (st->st_cur != NULL &&
+ (st->st_cur->ste_nested ||
+ st->st_cur->ste_type == FunctionBlock))
+ ste->ste_nested = 1;
+ ste->ste_child_free = 0;
+ ste->ste_generator = 0;
+ ste->ste_returns_value = 0;
+
+ if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0)
+ goto fail;
+
+ return ste;
fail:
- Py_XDECREF(ste);
- return NULL;
+ Py_XDECREF(ste);
+ return NULL;
}
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);
+ return PyUnicode_FromFormat("<symtable entry %U(%ld), line %d>",
+ ste->ste_name,
+ PyLong_AS_LONG(ste->ste_id), ste->ste_lineno);
}
static void
ste_dealloc(PySTEntryObject *ste)
{
- ste->ste_table = NULL;
- Py_XDECREF(ste->ste_id);
- Py_XDECREF(ste->ste_name);
- Py_XDECREF(ste->ste_symbols);
- Py_XDECREF(ste->ste_varnames);
- Py_XDECREF(ste->ste_children);
- PyObject_Del(ste);
+ ste->ste_table = NULL;
+ Py_XDECREF(ste->ste_id);
+ Py_XDECREF(ste->ste_name);
+ Py_XDECREF(ste->ste_symbols);
+ Py_XDECREF(ste->ste_varnames);
+ Py_XDECREF(ste->ste_children);
+ PyObject_Del(ste);
}
#define OFF(x) offsetof(PySTEntryObject, x)
static PyMemberDef ste_memberlist[] = {
- {"id", T_OBJECT, OFF(ste_id), READONLY},
- {"name", T_OBJECT, OFF(ste_name), READONLY},
- {"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},
- {NULL}
+ {"id", T_OBJECT, OFF(ste_id), READONLY},
+ {"name", T_OBJECT, OFF(ste_name), READONLY},
+ {"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},
+ {NULL}
};
PyTypeObject PySTEntry_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "symtable entry",
- sizeof(PySTEntryObject),
- 0,
- (destructor)ste_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- (reprfunc)ste_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- ste_memberlist, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "symtable entry",
+ sizeof(PySTEntryObject),
+ 0,
+ (destructor)ste_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ste_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ ste_memberlist, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
};
static int symtable_analyze(struct symtable *st);
static int symtable_warn(struct symtable *st, char *msg, int lineno);
-static int symtable_enter_block(struct symtable *st, identifier name,
- _Py_block_ty block, void *ast, int lineno);
+static int symtable_enter_block(struct symtable *st, identifier name,
+ _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);
@@ -184,11 +184,11 @@ static int symtable_visit_annotations(struct symtable *st, stmt_ty s);
static identifier top = NULL, lambda = NULL, genexpr = NULL,
- listcomp = NULL, setcomp = NULL, dictcomp = NULL,
- __class__ = NULL, __locals__ = NULL;
+ listcomp = NULL, setcomp = NULL, dictcomp = NULL,
+ __class__ = NULL, __locals__ = NULL;
#define GET_IDENTIFIER(VAR) \
- ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR)))
+ ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR)))
#define DUPLICATE_ARGUMENT \
"duplicate argument '%U' in function definition"
@@ -196,135 +196,135 @@ static identifier top = NULL, lambda = NULL, genexpr = NULL,
static struct symtable *
symtable_new(void)
{
- struct symtable *st;
-
- st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable));
- if (st == NULL)
- return NULL;
-
- st->st_filename = NULL;
- st->st_blocks = NULL;
-
- if ((st->st_stack = PyList_New(0)) == NULL)
- goto fail;
- if ((st->st_blocks = PyDict_New()) == NULL)
- goto fail;
- st->st_cur = NULL;
- st->st_private = NULL;
- return st;
+ struct symtable *st;
+
+ st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable));
+ if (st == NULL)
+ return NULL;
+
+ st->st_filename = NULL;
+ st->st_blocks = NULL;
+
+ if ((st->st_stack = PyList_New(0)) == NULL)
+ goto fail;
+ if ((st->st_blocks = PyDict_New()) == NULL)
+ goto fail;
+ st->st_cur = NULL;
+ st->st_private = NULL;
+ return st;
fail:
- PySymtable_Free(st);
- return NULL;
+ PySymtable_Free(st);
+ return NULL;
}
struct symtable *
PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
{
- struct symtable *st = symtable_new();
- asdl_seq *seq;
- int i;
-
- if (st == NULL)
- return st;
- st->st_filename = filename;
- st->st_future = future;
- /* Make the initial symbol information gathering pass */
- if (!GET_IDENTIFIER(top) ||
- !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;
- switch (mod->kind) {
- case Module_kind:
- seq = mod->v.Module.body;
- for (i = 0; i < asdl_seq_LEN(seq); i++)
- if (!symtable_visit_stmt(st,
- (stmt_ty)asdl_seq_GET(seq, i)))
- goto error;
- break;
- case Expression_kind:
- if (!symtable_visit_expr(st, mod->v.Expression.body))
- goto error;
- break;
- case Interactive_kind:
- seq = mod->v.Interactive.body;
- for (i = 0; i < asdl_seq_LEN(seq); i++)
- if (!symtable_visit_stmt(st,
- (stmt_ty)asdl_seq_GET(seq, i)))
- goto error;
- break;
- case Suite_kind:
- PyErr_SetString(PyExc_RuntimeError,
- "this compiler does not handle Suites");
- goto error;
- }
- if (!symtable_exit_block(st, (void *)mod)) {
- PySymtable_Free(st);
- return NULL;
- }
- /* Make the second symbol analysis pass */
- if (symtable_analyze(st))
- return st;
- PySymtable_Free(st);
- return NULL;
+ struct symtable *st = symtable_new();
+ asdl_seq *seq;
+ int i;
+
+ if (st == NULL)
+ return st;
+ st->st_filename = filename;
+ st->st_future = future;
+ /* Make the initial symbol information gathering pass */
+ if (!GET_IDENTIFIER(top) ||
+ !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;
+ switch (mod->kind) {
+ case Module_kind:
+ seq = mod->v.Module.body;
+ for (i = 0; i < asdl_seq_LEN(seq); i++)
+ if (!symtable_visit_stmt(st,
+ (stmt_ty)asdl_seq_GET(seq, i)))
+ goto error;
+ break;
+ case Expression_kind:
+ if (!symtable_visit_expr(st, mod->v.Expression.body))
+ goto error;
+ break;
+ case Interactive_kind:
+ seq = mod->v.Interactive.body;
+ for (i = 0; i < asdl_seq_LEN(seq); i++)
+ if (!symtable_visit_stmt(st,
+ (stmt_ty)asdl_seq_GET(seq, i)))
+ goto error;
+ break;
+ case Suite_kind:
+ PyErr_SetString(PyExc_RuntimeError,
+ "this compiler does not handle Suites");
+ goto error;
+ }
+ if (!symtable_exit_block(st, (void *)mod)) {
+ PySymtable_Free(st);
+ return NULL;
+ }
+ /* Make the second symbol analysis pass */
+ if (symtable_analyze(st))
+ return st;
+ PySymtable_Free(st);
+ return NULL;
error:
- (void) symtable_exit_block(st, (void *)mod);
- PySymtable_Free(st);
- return NULL;
+ (void) symtable_exit_block(st, (void *)mod);
+ PySymtable_Free(st);
+ return NULL;
}
void
PySymtable_Free(struct symtable *st)
{
- Py_XDECREF(st->st_blocks);
- Py_XDECREF(st->st_stack);
- PyMem_Free((void *)st);
+ Py_XDECREF(st->st_blocks);
+ Py_XDECREF(st->st_stack);
+ PyMem_Free((void *)st);
}
PySTEntryObject *
PySymtable_Lookup(struct symtable *st, void *key)
{
- PyObject *k, *v;
-
- k = PyLong_FromVoidPtr(key);
- if (k == NULL)
- return NULL;
- v = PyDict_GetItem(st->st_blocks, k);
- if (v) {
- assert(PySTEntry_Check(v));
- Py_INCREF(v);
- }
- else {
- PyErr_SetString(PyExc_KeyError,
- "unknown symbol table entry");
- }
-
- Py_DECREF(k);
- return (PySTEntryObject *)v;
+ PyObject *k, *v;
+
+ k = PyLong_FromVoidPtr(key);
+ if (k == NULL)
+ return NULL;
+ v = PyDict_GetItem(st->st_blocks, k);
+ if (v) {
+ assert(PySTEntry_Check(v));
+ Py_INCREF(v);
+ }
+ else {
+ PyErr_SetString(PyExc_KeyError,
+ "unknown symbol table entry");
+ }
+
+ Py_DECREF(k);
+ return (PySTEntryObject *)v;
}
-int
+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) >> SCOPE_OFFSET) & SCOPE_MASK;
+ PyObject *v = PyDict_GetItem(ste->ste_symbols, name);
+ if (!v)
+ return 0;
+ assert(PyLong_Check(v));
+ return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
}
/* Analyze raw symbol information to determine scope of each name.
The next several functions are helpers for symtable_analyze(),
- which determines whether a name is local, global, or free. In addition,
+ 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.
+ 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 global 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
@@ -340,7 +340,7 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
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
+ 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
@@ -363,14 +363,14 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
*/
#define SET_SCOPE(DICT, NAME, I) { \
- PyObject *o = PyLong_FromLong(I); \
- if (!o) \
- return 0; \
- if (PyDict_SetItem((DICT), (NAME), o) < 0) { \
- Py_DECREF(o); \
- return 0; \
- } \
- Py_DECREF(o); \
+ PyObject *o = PyLong_FromLong(I); \
+ if (!o) \
+ return 0; \
+ if (PyDict_SetItem((DICT), (NAME), o) < 0) { \
+ Py_DECREF(o); \
+ return 0; \
+ } \
+ Py_DECREF(o); \
}
/* Decide on scope of name, given flags.
@@ -380,86 +380,86 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
global. A name that was global can be changed to local.
*/
-static int
+static int
analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
- PyObject *bound, PyObject *local, PyObject *free,
- PyObject *global)
+ PyObject *bound, PyObject *local, PyObject *free,
+ PyObject *global)
{
- if (flags & DEF_GLOBAL) {
- if (flags & DEF_PARAM) {
- PyErr_Format(PyExc_SyntaxError,
- "name '%U' is parameter and global",
- name);
- PyErr_SyntaxLocation(ste->ste_table->st_filename,
- ste->ste_lineno);
-
- return 0;
- }
- if (flags & DEF_NONLOCAL) {
- PyErr_Format(PyExc_SyntaxError,
- "name '%U' is nonlocal and global",
- name);
- return 0;
- }
- SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
- if (PySet_Add(global, name) < 0)
- return 0;
- if (bound && (PySet_Discard(bound, name) < 0))
- return 0;
- return 1;
- }
+ if (flags & DEF_GLOBAL) {
+ if (flags & DEF_PARAM) {
+ PyErr_Format(PyExc_SyntaxError,
+ "name '%U' is parameter and global",
+ name);
+ PyErr_SyntaxLocation(ste->ste_table->st_filename,
+ ste->ste_lineno);
+
+ return 0;
+ }
if (flags & DEF_NONLOCAL) {
- if (flags & DEF_PARAM) {
- PyErr_Format(PyExc_SyntaxError,
- "name '%U' is parameter and nonlocal",
- name);
- return 0;
- }
- if (!bound) {
- PyErr_Format(PyExc_SyntaxError,
- "nonlocal declaration not allowed at module level");
- return 0;
- }
- if (!PySet_Contains(bound, name)) {
- PyErr_Format(PyExc_SyntaxError,
- "no binding for nonlocal '%U' found",
- name);
-
- return 0;
- }
- SET_SCOPE(scopes, name, FREE);
- ste->ste_free = 1;
- return PySet_Add(free, name) >= 0;
+ PyErr_Format(PyExc_SyntaxError,
+ "name '%U' is nonlocal and global",
+ name);
+ return 0;
+ }
+ SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
+ if (PySet_Add(global, name) < 0)
+ return 0;
+ if (bound && (PySet_Discard(bound, name) < 0))
+ return 0;
+ return 1;
+ }
+ if (flags & DEF_NONLOCAL) {
+ if (flags & DEF_PARAM) {
+ PyErr_Format(PyExc_SyntaxError,
+ "name '%U' is parameter and nonlocal",
+ name);
+ return 0;
}
- if (flags & DEF_BOUND) {
- SET_SCOPE(scopes, name, LOCAL);
- if (PySet_Add(local, name) < 0)
- return 0;
- if (PySet_Discard(global, name) < 0)
- return 0;
- return 1;
- }
- /* If an enclosing block has a binding for this name, it
- is a free variable rather than a global variable.
- Note that having a non-NULL bound implies that the block
- is nested.
- */
- if (bound && PySet_Contains(bound, name)) {
- SET_SCOPE(scopes, name, FREE);
- ste->ste_free = 1;
- return PySet_Add(free, name) >= 0;
- }
- /* 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);
- return 1;
- }
- if (ste->ste_nested)
- ste->ste_free = 1;
- SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
- return 1;
+ if (!bound) {
+ PyErr_Format(PyExc_SyntaxError,
+ "nonlocal declaration not allowed at module level");
+ return 0;
+ }
+ if (!PySet_Contains(bound, name)) {
+ PyErr_Format(PyExc_SyntaxError,
+ "no binding for nonlocal '%U' found",
+ name);
+
+ return 0;
+ }
+ SET_SCOPE(scopes, name, FREE);
+ ste->ste_free = 1;
+ return PySet_Add(free, name) >= 0;
+ }
+ if (flags & DEF_BOUND) {
+ SET_SCOPE(scopes, name, LOCAL);
+ if (PySet_Add(local, name) < 0)
+ return 0;
+ if (PySet_Discard(global, name) < 0)
+ return 0;
+ return 1;
+ }
+ /* If an enclosing block has a binding for this name, it
+ is a free variable rather than a global variable.
+ Note that having a non-NULL bound implies that the block
+ is nested.
+ */
+ if (bound && PySet_Contains(bound, name)) {
+ SET_SCOPE(scopes, name, FREE);
+ ste->ste_free = 1;
+ return PySet_Add(free, name) >= 0;
+ }
+ /* 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);
+ return 1;
+ }
+ if (ste->ste_nested)
+ ste->ste_free = 1;
+ SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
+ return 1;
}
#undef SET_SCOPE
@@ -478,153 +478,153 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
static int
analyze_cells(PyObject *scopes, PyObject *free, const char *restricted)
{
- PyObject *name, *v, *v_cell;
- int success = 0;
- Py_ssize_t pos = 0;
-
- v_cell = PyLong_FromLong(CELL);
- if (!v_cell)
- return 0;
- while (PyDict_Next(scopes, &pos, &name, &v)) {
- long scope;
- assert(PyLong_Check(v));
- scope = PyLong_AS_LONG(v);
- if (scope != LOCAL)
- continue;
- if (!PySet_Contains(free, name))
- continue;
- if (restricted != NULL &&
- PyUnicode_CompareWithASCIIString(name, restricted))
- 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)
- goto error;
- if (PySet_Discard(free, name) < 0)
- goto error;
- }
- success = 1;
+ PyObject *name, *v, *v_cell;
+ int success = 0;
+ Py_ssize_t pos = 0;
+
+ v_cell = PyLong_FromLong(CELL);
+ if (!v_cell)
+ return 0;
+ while (PyDict_Next(scopes, &pos, &name, &v)) {
+ long scope;
+ assert(PyLong_Check(v));
+ scope = PyLong_AS_LONG(v);
+ if (scope != LOCAL)
+ continue;
+ if (!PySet_Contains(free, name))
+ continue;
+ if (restricted != NULL &&
+ PyUnicode_CompareWithASCIIString(name, restricted))
+ 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)
+ goto error;
+ if (PySet_Discard(free, name) < 0)
+ goto error;
+ }
+ success = 1;
error:
- Py_DECREF(v_cell);
- return success;
+ Py_DECREF(v_cell);
+ return success;
}
/* Check for illegal statements in unoptimized namespaces */
static int
check_unoptimized(const PySTEntryObject* ste) {
- 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: /* import * at top-level is fine */
- return 1;
- case OPT_IMPORT_STAR:
- PyErr_Format(PyExc_SyntaxError,
- "import * is not allowed in function '%U' because it %s",
- ste->ste_name, trailer);
- break;
- }
-
- PyErr_SyntaxLocation(ste->ste_table->st_filename,
- ste->ste_opt_lineno);
- return 0;
+ 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: /* import * at top-level is fine */
+ return 1;
+ case OPT_IMPORT_STAR:
+ PyErr_Format(PyExc_SyntaxError,
+ "import * is not allowed in function '%U' because it %s",
+ ste->ste_name, trailer);
+ break;
+ }
+
+ 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 ste_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 *scopes,
PyObject *bound, PyObject *free, int classflag)
{
- PyObject *name = NULL, *itr = NULL;
- PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = 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)
- return 0;
- if (PyDict_SetItem(symbols, name, v_new) < 0) {
- Py_DECREF(v_new);
- return 0;
- }
- Py_DECREF(v_new);
- }
-
- /* 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)
- goto error;
-
- while ((name = PyIter_Next(itr))) {
- v = PyDict_GetItem(symbols, name);
-
- /* Handle symbol that already exists in this scope */
- if (v) {
- /* Handle 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;
- }
- if (PyDict_SetItem(symbols, name, v_new) < 0) {
- Py_DECREF(v_new);
- goto error;
- }
- Py_DECREF(v_new);
- }
- /* It's a cell, or already free in this scope */
- Py_DECREF(name);
- continue;
- }
- /* Handle global symbol */
- if (!PySet_Contains(bound, name)) {
- Py_DECREF(name);
- continue; /* it's a global */
- }
- /* Propagate new free symbol up the lexical stack */
- if (PyDict_SetItem(symbols, name, v_free) < 0) {
- goto error;
- }
- Py_DECREF(name);
+ PyObject *name = NULL, *itr = NULL;
+ PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = 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)
+ return 0;
+ if (PyDict_SetItem(symbols, name, v_new) < 0) {
+ Py_DECREF(v_new);
+ return 0;
}
- Py_DECREF(itr);
- Py_DECREF(v_free);
- return 1;
+ Py_DECREF(v_new);
+ }
+
+ /* 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)
+ goto error;
+
+ while ((name = PyIter_Next(itr))) {
+ v = PyDict_GetItem(symbols, name);
+
+ /* Handle symbol that already exists in this scope */
+ if (v) {
+ /* Handle 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;
+ }
+ if (PyDict_SetItem(symbols, name, v_new) < 0) {
+ Py_DECREF(v_new);
+ goto error;
+ }
+ Py_DECREF(v_new);
+ }
+ /* It's a cell, or already free in this scope */
+ Py_DECREF(name);
+ continue;
+ }
+ /* Handle global symbol */
+ if (!PySet_Contains(bound, name)) {
+ Py_DECREF(name);
+ continue; /* it's a global */
+ }
+ /* 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);
+ return 1;
error:
- Py_XDECREF(v_free);
- Py_XDECREF(itr);
- Py_XDECREF(name);
- return 0;
-}
+ Py_XDECREF(v_free);
+ Py_XDECREF(itr);
+ Py_XDECREF(name);
+ return 0;
+}
/* Make final symbol table decisions for block of ste.
@@ -647,238 +647,238 @@ error:
*/
static int
-analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
- PyObject *global, PyObject* child_free);
+analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
+ PyObject *global, PyObject* child_free);
static int
-analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
- PyObject *global)
+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;
- int i, success = 0;
- Py_ssize_t pos = 0;
-
- local = PySet_New(NULL); /* collect new names bound in block */
- if (!local)
- goto error;
- scopes = PyDict_New(); /* collect scopes defined for each name */
- if (!scopes)
- goto error;
-
- /* Allocate new global and bound variable dictionaries. These
- dictionaries hold the names visible in nested blocks. For
- ClassBlocks, the bound and global names are initialized
- before analyzing names, because class bindings aren't
- visible in methods. For other blocks, they are initialized
- after names are analyzed.
- */
-
- /* TODO(jhylton): Package these dicts in a struct so that we
- can write reasonable helper functions?
- */
- newglobal = PySet_New(NULL);
- if (!newglobal)
- goto error;
- newfree = PySet_New(NULL);
- if (!newfree)
- goto error;
- newbound = PySet_New(NULL);
- if (!newbound)
- 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)
- goto error;
- Py_DECREF(temp);
- /* Pass down previously bound symbols */
- if (bound) {
- temp = PyNumber_InPlaceOr(newbound, bound);
- if (!temp)
- 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,
- 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)
- goto error;
- Py_DECREF(temp);
- }
- /* Pass down previously bound symbols */
- if (bound) {
- temp = PyNumber_InPlaceOr(newbound, bound);
- if (!temp)
- 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;
- assert(PySet_Contains(local, __class__) == 1);
- if (PySet_Add(newbound, __class__) < 0)
- goto error;
- }
-
- /* 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);
- if (!allfree)
- goto error;
- for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
- PyObject *c = PyList_GET_ITEM(ste->ste_children, i);
- PySTEntryObject* entry;
- assert(c && PySTEntry_Check(c));
- entry = (PySTEntryObject*)c;
- 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,
- NULL))
- goto error;
- else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
- "__class__"))
- goto error;
- /* Records the results of the analysis in the symbol table entry */
- if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
- ste->ste_type == ClassBlock))
- goto error;
- if (!check_unoptimized(ste))
- goto error;
-
- temp = PyNumber_InPlaceOr(free, newfree);
- if (!temp)
- goto error;
- Py_DECREF(temp);
- success = 1;
+ PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL;
+ PyObject *newglobal = NULL, *newfree = NULL, *allfree = NULL;
+ PyObject *temp;
+ int i, success = 0;
+ Py_ssize_t pos = 0;
+
+ local = PySet_New(NULL); /* collect new names bound in block */
+ if (!local)
+ goto error;
+ scopes = PyDict_New(); /* collect scopes defined for each name */
+ if (!scopes)
+ goto error;
+
+ /* Allocate new global and bound variable dictionaries. These
+ dictionaries hold the names visible in nested blocks. For
+ ClassBlocks, the bound and global names are initialized
+ before analyzing names, because class bindings aren't
+ visible in methods. For other blocks, they are initialized
+ after names are analyzed.
+ */
+
+ /* TODO(jhylton): Package these dicts in a struct so that we
+ can write reasonable helper functions?
+ */
+ newglobal = PySet_New(NULL);
+ if (!newglobal)
+ goto error;
+ newfree = PySet_New(NULL);
+ if (!newfree)
+ goto error;
+ newbound = PySet_New(NULL);
+ if (!newbound)
+ 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)
+ goto error;
+ Py_DECREF(temp);
+ /* Pass down previously bound symbols */
+ if (bound) {
+ temp = PyNumber_InPlaceOr(newbound, bound);
+ if (!temp)
+ 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,
+ 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)
+ goto error;
+ Py_DECREF(temp);
+ }
+ /* Pass down previously bound symbols */
+ if (bound) {
+ temp = PyNumber_InPlaceOr(newbound, bound);
+ if (!temp)
+ 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;
+ assert(PySet_Contains(local, __class__) == 1);
+ if (PySet_Add(newbound, __class__) < 0)
+ goto error;
+ }
+
+ /* 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);
+ if (!allfree)
+ goto error;
+ for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
+ PyObject *c = PyList_GET_ITEM(ste->ste_children, i);
+ PySTEntryObject* entry;
+ assert(c && PySTEntry_Check(c));
+ entry = (PySTEntryObject*)c;
+ 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,
+ NULL))
+ goto error;
+ else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
+ "__class__"))
+ goto error;
+ /* Records the results of the analysis in the symbol table entry */
+ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
+ ste->ste_type == ClassBlock))
+ goto error;
+ if (!check_unoptimized(ste))
+ goto error;
+
+ temp = PyNumber_InPlaceOr(free, newfree);
+ if (!temp)
+ goto error;
+ Py_DECREF(temp);
+ success = 1;
error:
- Py_XDECREF(scopes);
- Py_XDECREF(local);
- Py_XDECREF(newbound);
- Py_XDECREF(newglobal);
- Py_XDECREF(newfree);
- Py_XDECREF(allfree);
- if (!success)
- assert(PyErr_Occurred());
- return success;
+ Py_XDECREF(scopes);
+ Py_XDECREF(local);
+ Py_XDECREF(newbound);
+ Py_XDECREF(newglobal);
+ Py_XDECREF(newfree);
+ Py_XDECREF(allfree);
+ if (!success)
+ assert(PyErr_Occurred());
+ return success;
}
static int
-analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
- PyObject *global, PyObject* child_free)
+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.
-
- These dictionary are used by all blocks enclosed by the
- current block. The analyze_block() call modifies these
- dictionaries.
-
- */
- temp_bound = PySet_New(bound);
- if (!temp_bound)
- goto error;
- temp_free = PySet_New(free);
- if (!temp_free)
- goto error;
- temp_global = PySet_New(global);
- if (!temp_global)
- goto error;
-
- if (!analyze_block(entry, temp_bound, temp_free, temp_global))
- goto error;
- temp = PyNumber_InPlaceOr(child_free, temp_free);
- if (!temp)
- goto error;
- Py_DECREF(temp);
- Py_DECREF(temp_bound);
- Py_DECREF(temp_free);
- Py_DECREF(temp_global);
- return 1;
+ PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL;
+ PyObject *temp;
+
+ /* Copy the bound and global dictionaries.
+
+ These dictionary are used by all blocks enclosed by the
+ current block. The analyze_block() call modifies these
+ dictionaries.
+
+ */
+ temp_bound = PySet_New(bound);
+ if (!temp_bound)
+ goto error;
+ temp_free = PySet_New(free);
+ if (!temp_free)
+ goto error;
+ temp_global = PySet_New(global);
+ if (!temp_global)
+ goto error;
+
+ if (!analyze_block(entry, temp_bound, temp_free, temp_global))
+ goto error;
+ temp = PyNumber_InPlaceOr(child_free, temp_free);
+ if (!temp)
+ goto error;
+ Py_DECREF(temp);
+ Py_DECREF(temp_bound);
+ Py_DECREF(temp_free);
+ Py_DECREF(temp_global);
+ return 1;
error:
- Py_XDECREF(temp_bound);
- Py_XDECREF(temp_free);
- Py_XDECREF(temp_global);
- return 0;
+ Py_XDECREF(temp_bound);
+ Py_XDECREF(temp_free);
+ Py_XDECREF(temp_global);
+ return 0;
}
static int
symtable_analyze(struct symtable *st)
{
- PyObject *free, *global;
- int r;
-
- free = PySet_New(NULL);
- if (!free)
- return 0;
- global = PySet_New(NULL);
- if (!global) {
- Py_DECREF(free);
- return 0;
- }
- r = analyze_block(st->st_top, NULL, free, global);
- Py_DECREF(free);
- Py_DECREF(global);
- return r;
+ PyObject *free, *global;
+ int r;
+
+ free = PySet_New(NULL);
+ if (!free)
+ return 0;
+ global = PySet_New(NULL);
+ if (!global) {
+ Py_DECREF(free);
+ return 0;
+ }
+ r = analyze_block(st->st_top, NULL, free, global);
+ Py_DECREF(free);
+ Py_DECREF(global);
+ return r;
}
static int
symtable_warn(struct symtable *st, char *msg, int lineno)
{
- if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename,
- lineno, NULL, NULL) < 0) {
- if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
- PyErr_SetString(PyExc_SyntaxError, msg);
- PyErr_SyntaxLocation(st->st_filename,
- st->st_cur->ste_lineno);
- }
- return 0;
- }
- return 1;
+ if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename,
+ lineno, NULL, NULL) < 0) {
+ if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
+ PyErr_SetString(PyExc_SyntaxError, msg);
+ PyErr_SyntaxLocation(st->st_filename,
+ st->st_cur->ste_lineno);
+ }
+ return 0;
+ }
+ return 1;
}
/* symtable_enter_block() gets a reference via ste_new.
@@ -889,792 +889,792 @@ symtable_warn(struct symtable *st, char *msg, int lineno)
static int
symtable_exit_block(struct symtable *st, void *ast)
{
- 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;
- }
- return 1;
+ 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;
+ }
+ return 1;
}
static int
-symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
- void *ast, int lineno)
+symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
+ void *ast, int lineno)
{
- PySTEntryObject *prev = NULL;
-
- 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);
- }
- st->st_cur = ste_new(st, name, block, ast, lineno);
- if (st->st_cur == NULL)
- return 0;
- if (name == GET_IDENTIFIER(top))
- st->st_global = st->st_cur->ste_symbols;
- if (prev) {
- if (PyList_Append(prev->ste_children,
- (PyObject *)st->st_cur) < 0) {
- return 0;
- }
- }
- return 1;
+ PySTEntryObject *prev = NULL;
+
+ 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);
+ }
+ st->st_cur = ste_new(st, name, block, ast, lineno);
+ if (st->st_cur == NULL)
+ return 0;
+ if (name == GET_IDENTIFIER(top))
+ st->st_global = st->st_cur->ste_symbols;
+ if (prev) {
+ if (PyList_Append(prev->ste_children,
+ (PyObject *)st->st_cur) < 0) {
+ return 0;
+ }
+ }
+ return 1;
}
static long
symtable_lookup(struct symtable *st, PyObject *name)
{
- PyObject *o;
- PyObject *mangled = _Py_Mangle(st->st_private, name);
- if (!mangled)
- return 0;
- o = PyDict_GetItem(st->st_cur->ste_symbols, mangled);
- Py_DECREF(mangled);
- if (!o)
- return 0;
- return PyLong_AsLong(o);
+ PyObject *o;
+ PyObject *mangled = _Py_Mangle(st->st_private, name);
+ if (!mangled)
+ return 0;
+ o = PyDict_GetItem(st->st_cur->ste_symbols, mangled);
+ Py_DECREF(mangled);
+ if (!o)
+ return 0;
+ return PyLong_AsLong(o);
}
static int
-symtable_add_def(struct symtable *st, PyObject *name, int flag)
+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 = st->st_cur->ste_symbols;
- if ((o = PyDict_GetItem(dict, mangled))) {
- val = PyLong_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_SyntaxLocation(st->st_filename,
- st->st_cur->ste_lineno);
- goto error;
- }
- val |= flag;
- } else
- val = flag;
- o = PyLong_FromLong(val);
+ PyObject *o;
+ PyObject *dict;
+ long val;
+ PyObject *mangled = _Py_Mangle(st->st_private, name);
+
+
+ if (!mangled)
+ return 0;
+ dict = st->st_cur->ste_symbols;
+ if ((o = PyDict_GetItem(dict, mangled))) {
+ val = PyLong_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_SyntaxLocation(st->st_filename,
+ st->st_cur->ste_lineno);
+ goto error;
+ }
+ val |= flag;
+ } else
+ val = flag;
+ o = PyLong_FromLong(val);
+ if (o == NULL)
+ goto error;
+ if (PyDict_SetItem(dict, mangled, o) < 0) {
+ Py_DECREF(o);
+ goto error;
+ }
+ Py_DECREF(o);
+
+ if (flag & DEF_PARAM) {
+ 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);
+ }
+ o = PyLong_FromLong(val);
if (o == NULL)
- goto error;
- if (PyDict_SetItem(dict, mangled, o) < 0) {
- Py_DECREF(o);
- goto error;
- }
- Py_DECREF(o);
-
- if (flag & DEF_PARAM) {
- 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);
- }
- o = PyLong_FromLong(val);
- if (o == NULL)
- goto error;
- if (PyDict_SetItem(st->st_global, mangled, o) < 0) {
- Py_DECREF(o);
- goto error;
- }
- Py_DECREF(o);
- }
- Py_DECREF(mangled);
- return 1;
+ goto error;
+ if (PyDict_SetItem(st->st_global, mangled, o) < 0) {
+ Py_DECREF(o);
+ goto error;
+ }
+ Py_DECREF(o);
+ }
+ Py_DECREF(mangled);
+ return 1;
error:
- Py_DECREF(mangled);
- return 0;
+ Py_DECREF(mangled);
+ return 0;
}
/* 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.
-
+ 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.
*/
#define VISIT(ST, TYPE, V) \
- if (!symtable_visit_ ## TYPE((ST), (V))) \
- return 0;
+ if (!symtable_visit_ ## TYPE((ST), (V))) \
+ return 0;
#define VISIT_IN_BLOCK(ST, TYPE, V, S) \
- if (!symtable_visit_ ## TYPE((ST), (V))) { \
- symtable_exit_block((ST), (S)); \
- return 0; \
- }
+ if (!symtable_visit_ ## TYPE((ST), (V))) { \
+ symtable_exit_block((ST), (S)); \
+ return 0; \
+ }
#define VISIT_SEQ(ST, TYPE, SEQ) { \
- int i; \
- asdl_seq *seq = (SEQ); /* avoid variable capture */ \
- 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)) \
- return 0; \
- } \
+ int i; \
+ asdl_seq *seq = (SEQ); /* avoid variable capture */ \
+ 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)) \
+ return 0; \
+ } \
}
#define VISIT_SEQ_IN_BLOCK(ST, TYPE, SEQ, S) { \
- int i; \
- asdl_seq *seq = (SEQ); /* avoid variable capture */ \
- 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)) { \
- symtable_exit_block((ST), (S)); \
- return 0; \
- } \
- } \
+ int i; \
+ asdl_seq *seq = (SEQ); /* avoid variable capture */ \
+ 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)) { \
+ symtable_exit_block((ST), (S)); \
+ return 0; \
+ } \
+ } \
}
#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \
- 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)) \
- return 0; \
- } \
+ 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)) \
+ return 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; \
- } \
- } \
+ 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; \
+ } \
+ } \
}
#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; \
- } \
+ 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)
{
- char tmpname[256];
- identifier tmp;
-
- PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]",
- ++st->st_cur->ste_tmpname);
- tmp = PyUnicode_InternFromString(tmpname);
- if (!tmp)
- return 0;
- if (!symtable_add_def(st, tmp, DEF_LOCAL))
- return 0;
- Py_DECREF(tmp);
- return 1;
+ char tmpname[256];
+ identifier tmp;
+
+ PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]",
+ ++st->st_cur->ste_tmpname);
+ tmp = PyUnicode_InternFromString(tmpname);
+ if (!tmp)
+ return 0;
+ if (!symtable_add_def(st, tmp, DEF_LOCAL))
+ return 0;
+ Py_DECREF(tmp);
+ return 1;
}
static int
symtable_visit_stmt(struct symtable *st, stmt_ty s)
{
- switch (s->kind) {
- case FunctionDef_kind:
- if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL))
- 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 (!symtable_visit_annotations(st, s))
- return 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))
- 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))
- return 0;
- break;
- case ClassDef_kind: {
- PyObject *tmp;
- if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL))
- return 0;
- VISIT_SEQ(st, expr, s->v.ClassDef.bases);
- VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
- if (s->v.ClassDef.starargs)
- VISIT(st, expr, s->v.ClassDef.starargs);
- if (s->v.ClassDef.kwargs)
- VISIT(st, expr, s->v.ClassDef.kwargs);
- 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))
- return 0;
- if (!GET_IDENTIFIER(__class__) ||
- !symtable_add_def(st, __class__, DEF_LOCAL) ||
- !GET_IDENTIFIER(__locals__) ||
- !symtable_add_def(st, __locals__, DEF_PARAM)) {
- symtable_exit_block(st, s);
- return 0;
- }
- tmp = st->st_private;
- st->st_private = s->v.ClassDef.name;
- VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);
- st->st_private = tmp;
- if (!symtable_exit_block(st, s))
- 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:
- VISIT_SEQ(st, expr, s->v.Delete.targets);
- break;
- case Assign_kind:
- VISIT_SEQ(st, expr, s->v.Assign.targets);
- VISIT(st, expr, s->v.Assign.value);
- break;
- case AugAssign_kind:
- VISIT(st, expr, s->v.AugAssign.target);
- VISIT(st, expr, s->v.AugAssign.value);
- break;
- case For_kind:
- VISIT(st, expr, s->v.For.target);
- VISIT(st, expr, s->v.For.iter);
- VISIT_SEQ(st, stmt, s->v.For.body);
- if (s->v.For.orelse)
- VISIT_SEQ(st, stmt, s->v.For.orelse);
- break;
- case While_kind:
- VISIT(st, expr, s->v.While.test);
- VISIT_SEQ(st, stmt, s->v.While.body);
- if (s->v.While.orelse)
- VISIT_SEQ(st, stmt, s->v.While.orelse);
- break;
- case If_kind:
- /* XXX if 0: and lookup_yield() hacks */
- VISIT(st, expr, s->v.If.test);
- VISIT_SEQ(st, stmt, s->v.If.body);
- if (s->v.If.orelse)
- 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);
+ switch (s->kind) {
+ case FunctionDef_kind:
+ if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL))
+ 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 (!symtable_visit_annotations(st, s))
+ return 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))
+ 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))
+ return 0;
+ break;
+ case ClassDef_kind: {
+ PyObject *tmp;
+ if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL))
+ return 0;
+ VISIT_SEQ(st, expr, s->v.ClassDef.bases);
+ VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
+ if (s->v.ClassDef.starargs)
+ VISIT(st, expr, s->v.ClassDef.starargs);
+ if (s->v.ClassDef.kwargs)
+ VISIT(st, expr, s->v.ClassDef.kwargs);
+ 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))
+ return 0;
+ if (!GET_IDENTIFIER(__class__) ||
+ !symtable_add_def(st, __class__, DEF_LOCAL) ||
+ !GET_IDENTIFIER(__locals__) ||
+ !symtable_add_def(st, __locals__, DEF_PARAM)) {
+ symtable_exit_block(st, s);
+ return 0;
+ }
+ tmp = st->st_private;
+ st->st_private = s->v.ClassDef.name;
+ VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);
+ st->st_private = tmp;
+ if (!symtable_exit_block(st, s))
+ 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 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);
- if (s->v.Assert.msg)
- VISIT(st, expr, s->v.Assert.msg);
- 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 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 = _PyUnicode_AsString(name);
- long cur = symtable_lookup(st, name);
- if (cur < 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, buf, s->lineno))
- return 0;
- }
- if (!symtable_add_def(st, name, DEF_GLOBAL))
- return 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);
- char *c_name = _PyUnicode_AsString(name);
- long cur = symtable_lookup(st, name);
- if (cur < 0)
- return 0;
- if (cur & (DEF_LOCAL | USE)) {
- char buf[256];
- if (cur & DEF_LOCAL)
- PyOS_snprintf(buf, sizeof(buf),
- NONLOCAL_AFTER_ASSIGN,
- c_name);
- else
- PyOS_snprintf(buf, sizeof(buf),
- NONLOCAL_AFTER_USE,
- c_name);
- if (!symtable_warn(st, buf, s->lineno))
- return 0;
- }
- if (!symtable_add_def(st, name, DEF_NONLOCAL))
- return 0;
- }
- break;
- }
- case Expr_kind:
- VISIT(st, expr, s->v.Expr.value);
- break;
- case Pass_kind:
- case Break_kind:
- case Continue_kind:
- /* nothing to do here */
- break;
- case With_kind:
- 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;
- }
- return 1;
+ }
+ break;
+ case Delete_kind:
+ VISIT_SEQ(st, expr, s->v.Delete.targets);
+ break;
+ case Assign_kind:
+ VISIT_SEQ(st, expr, s->v.Assign.targets);
+ VISIT(st, expr, s->v.Assign.value);
+ break;
+ case AugAssign_kind:
+ VISIT(st, expr, s->v.AugAssign.target);
+ VISIT(st, expr, s->v.AugAssign.value);
+ break;
+ case For_kind:
+ VISIT(st, expr, s->v.For.target);
+ VISIT(st, expr, s->v.For.iter);
+ VISIT_SEQ(st, stmt, s->v.For.body);
+ if (s->v.For.orelse)
+ VISIT_SEQ(st, stmt, s->v.For.orelse);
+ break;
+ case While_kind:
+ VISIT(st, expr, s->v.While.test);
+ VISIT_SEQ(st, stmt, s->v.While.body);
+ if (s->v.While.orelse)
+ VISIT_SEQ(st, stmt, s->v.While.orelse);
+ break;
+ case If_kind:
+ /* XXX if 0: and lookup_yield() hacks */
+ VISIT(st, expr, s->v.If.test);
+ VISIT_SEQ(st, stmt, s->v.If.body);
+ if (s->v.If.orelse)
+ 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);
+ }
+ }
+ break;
+ 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);
+ if (s->v.Assert.msg)
+ VISIT(st, expr, s->v.Assert.msg);
+ 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 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 = _PyUnicode_AsString(name);
+ long cur = symtable_lookup(st, name);
+ if (cur < 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, buf, s->lineno))
+ return 0;
+ }
+ if (!symtable_add_def(st, name, DEF_GLOBAL))
+ return 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);
+ char *c_name = _PyUnicode_AsString(name);
+ long cur = symtable_lookup(st, name);
+ if (cur < 0)
+ return 0;
+ if (cur & (DEF_LOCAL | USE)) {
+ char buf[256];
+ if (cur & DEF_LOCAL)
+ PyOS_snprintf(buf, sizeof(buf),
+ NONLOCAL_AFTER_ASSIGN,
+ c_name);
+ else
+ PyOS_snprintf(buf, sizeof(buf),
+ NONLOCAL_AFTER_USE,
+ c_name);
+ if (!symtable_warn(st, buf, s->lineno))
+ return 0;
+ }
+ if (!symtable_add_def(st, name, DEF_NONLOCAL))
+ return 0;
+ }
+ break;
+ }
+ case Expr_kind:
+ VISIT(st, expr, s->v.Expr.value);
+ break;
+ case Pass_kind:
+ case Break_kind:
+ case Continue_kind:
+ /* nothing to do here */
+ break;
+ case With_kind:
+ 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;
+ }
+ return 1;
}
-static int
+static int
symtable_visit_expr(struct symtable *st, expr_ty e)
{
- switch (e->kind) {
- case BoolOp_kind:
- VISIT_SEQ(st, expr, e->v.BoolOp.values);
- break;
- case BinOp_kind:
- VISIT(st, expr, e->v.BinOp.left);
- VISIT(st, expr, e->v.BinOp.right);
- break;
- case UnaryOp_kind:
- VISIT(st, expr, e->v.UnaryOp.operand);
- break;
- case Lambda_kind: {
- if (!GET_IDENTIFIER(lambda))
- return 0;
- if (e->v.Lambda.args->defaults)
- VISIT_SEQ(st, expr, e->v.Lambda.args->defaults);
- if (!symtable_enter_block(st, lambda,
- 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))
- return 0;
- break;
- }
- case IfExp_kind:
- VISIT(st, expr, e->v.IfExp.test);
- VISIT(st, expr, e->v.IfExp.body);
- VISIT(st, expr, e->v.IfExp.orelse);
- break;
- case Dict_kind:
- 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))
- return 0;
- break;
- case ListComp_kind:
- if (!symtable_visit_listcomp(st, e))
- return 0;
- break;
- case SetComp_kind:
- if (!symtable_visit_setcomp(st, e))
- return 0;
- break;
- case DictComp_kind:
- if (!symtable_visit_dictcomp(st, e))
- return 0;
- break;
- case Yield_kind:
- if (e->v.Yield.value)
- VISIT(st, expr, e->v.Yield.value);
- st->st_cur->ste_generator = 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);
- VISIT_SEQ(st, expr, e->v.Compare.comparators);
- break;
- case Call_kind:
- VISIT(st, expr, e->v.Call.func);
- VISIT_SEQ(st, expr, e->v.Call.args);
- 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 Num_kind:
- case Str_kind:
- case Bytes_kind:
- case Ellipsis_kind:
- /* Nothing to do here. */
- break;
- /* The following exprs can be assignment targets. */
- case Attribute_kind:
- VISIT(st, expr, e->v.Attribute.value);
- break;
- case Subscript_kind:
- 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))
- return 0;
- /* Special-case super: it counts as a use of __class__ */
- if (e->v.Name.ctx == Load &&
- st->st_cur->ste_type == FunctionBlock &&
- !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) {
- if (!GET_IDENTIFIER(__class__) ||
- !symtable_add_def(st, __class__, USE))
- return 0;
- }
- break;
- /* child nodes of List and Tuple will have expr_context set */
- case List_kind:
- VISIT_SEQ(st, expr, e->v.List.elts);
- break;
- case Tuple_kind:
- VISIT_SEQ(st, expr, e->v.Tuple.elts);
- break;
- }
- return 1;
+ switch (e->kind) {
+ case BoolOp_kind:
+ VISIT_SEQ(st, expr, e->v.BoolOp.values);
+ break;
+ case BinOp_kind:
+ VISIT(st, expr, e->v.BinOp.left);
+ VISIT(st, expr, e->v.BinOp.right);
+ break;
+ case UnaryOp_kind:
+ VISIT(st, expr, e->v.UnaryOp.operand);
+ break;
+ case Lambda_kind: {
+ if (!GET_IDENTIFIER(lambda))
+ return 0;
+ if (e->v.Lambda.args->defaults)
+ VISIT_SEQ(st, expr, e->v.Lambda.args->defaults);
+ if (!symtable_enter_block(st, lambda,
+ 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))
+ return 0;
+ break;
+ }
+ case IfExp_kind:
+ VISIT(st, expr, e->v.IfExp.test);
+ VISIT(st, expr, e->v.IfExp.body);
+ VISIT(st, expr, e->v.IfExp.orelse);
+ break;
+ case Dict_kind:
+ 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))
+ return 0;
+ break;
+ case ListComp_kind:
+ if (!symtable_visit_listcomp(st, e))
+ return 0;
+ break;
+ case SetComp_kind:
+ if (!symtable_visit_setcomp(st, e))
+ return 0;
+ break;
+ case DictComp_kind:
+ if (!symtable_visit_dictcomp(st, e))
+ return 0;
+ break;
+ case Yield_kind:
+ if (e->v.Yield.value)
+ VISIT(st, expr, e->v.Yield.value);
+ st->st_cur->ste_generator = 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);
+ VISIT_SEQ(st, expr, e->v.Compare.comparators);
+ break;
+ case Call_kind:
+ VISIT(st, expr, e->v.Call.func);
+ VISIT_SEQ(st, expr, e->v.Call.args);
+ 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 Num_kind:
+ case Str_kind:
+ case Bytes_kind:
+ case Ellipsis_kind:
+ /* Nothing to do here. */
+ break;
+ /* The following exprs can be assignment targets. */
+ case Attribute_kind:
+ VISIT(st, expr, e->v.Attribute.value);
+ break;
+ case Subscript_kind:
+ 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))
+ return 0;
+ /* Special-case super: it counts as a use of __class__ */
+ if (e->v.Name.ctx == Load &&
+ st->st_cur->ste_type == FunctionBlock &&
+ !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) {
+ if (!GET_IDENTIFIER(__class__) ||
+ !symtable_add_def(st, __class__, USE))
+ return 0;
+ }
+ break;
+ /* child nodes of List and Tuple will have expr_context set */
+ case List_kind:
+ VISIT_SEQ(st, expr, e->v.List.elts);
+ break;
+ case Tuple_kind:
+ VISIT_SEQ(st, expr, e->v.Tuple.elts);
+ break;
+ }
+ return 1;
}
static int
symtable_implicit_arg(struct symtable *st, int pos)
{
- PyObject *id = PyUnicode_FromFormat(".%d", pos);
- if (id == NULL)
- return 0;
- if (!symtable_add_def(st, id, DEF_PARAM)) {
- Py_DECREF(id);
- return 0;
- }
- Py_DECREF(id);
- return 1;
+ PyObject *id = PyUnicode_FromFormat(".%d", pos);
+ if (id == NULL)
+ return 0;
+ if (!symtable_add_def(st, id, DEF_PARAM)) {
+ Py_DECREF(id);
+ return 0;
+ }
+ Py_DECREF(id);
+ return 1;
}
-static int
+static int
symtable_visit_params(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 (!symtable_add_def(st, arg->arg, DEF_PARAM))
- return 0;
- }
-
- return 1;
+ 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 (!symtable_add_def(st, arg->arg, DEF_PARAM))
+ return 0;
+ }
+
+ return 1;
}
-static int
+static int
symtable_visit_argannotations(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);
- }
-
- return 1;
+ 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);
+ }
+
+ return 1;
}
static int
symtable_visit_annotations(struct symtable *st, stmt_ty s)
{
- arguments_ty a = s->v.FunctionDef.args;
-
- if (a->args && !symtable_visit_argannotations(st, a->args))
- return 0;
- if (a->varargannotation)
- VISIT(st, expr, a->varargannotation);
- if (a->kwargannotation)
- VISIT(st, expr, a->kwargannotation);
- if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))
- return 0;
- if (s->v.FunctionDef.returns)
- VISIT(st, expr, s->v.FunctionDef.returns);
- return 1;
+ arguments_ty a = s->v.FunctionDef.args;
+
+ if (a->args && !symtable_visit_argannotations(st, a->args))
+ return 0;
+ if (a->varargannotation)
+ VISIT(st, expr, a->varargannotation);
+ if (a->kwargannotation)
+ VISIT(st, expr, a->kwargannotation);
+ if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))
+ return 0;
+ if (s->v.FunctionDef.returns)
+ VISIT(st, expr, s->v.FunctionDef.returns);
+ return 1;
}
-static int
+static int
symtable_visit_arguments(struct symtable *st, arguments_ty a)
{
- /* skip default arguments inside function block
- XXX should ast be different?
- */
- if (a->args && !symtable_visit_params(st, a->args))
- return 0;
- if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs))
- return 0;
- if (a->vararg) {
- 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, DEF_PARAM))
- return 0;
- st->st_cur->ste_varkeywords = 1;
- }
- return 1;
+ /* skip default arguments inside function block
+ XXX should ast be different?
+ */
+ if (a->args && !symtable_visit_params(st, a->args))
+ return 0;
+ if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs))
+ return 0;
+ if (a->vararg) {
+ 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, DEF_PARAM))
+ return 0;
+ st->st_cur->ste_varkeywords = 1;
+ }
+ return 1;
}
-static int
+static int
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_SEQ(st, stmt, eh->v.ExceptHandler.body);
- return 1;
+ 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_SEQ(st, stmt, eh->v.ExceptHandler.body);
+ return 1;
}
-static int
+static int
symtable_visit_alias(struct symtable *st, alias_ty a)
{
- /* Compute store_name, the name actually bound by the import
- operation. It is diferent than a->name when a->name is a
- dotted package name (e.g. spam.eggs)
- */
- PyObject *store_name;
- PyObject *name = (a->asname == NULL) ? a->name : a->asname;
- const Py_UNICODE *base = PyUnicode_AS_UNICODE(name);
- Py_UNICODE *dot = Py_UNICODE_strchr(base, '.');
- if (dot) {
- store_name = PyUnicode_FromUnicode(base, dot - base);
- if (!store_name)
- return 0;
- }
- else {
- store_name = name;
- Py_INCREF(store_name);
- }
- if (PyUnicode_CompareWithASCIIString(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;
- PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING);
- PyErr_SyntaxLocation(st->st_filename, lineno);
- Py_DECREF(store_name);
- return 0;
- }
- st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR;
- Py_DECREF(store_name);
- return 1;
- }
+ /* Compute store_name, the name actually bound by the import
+ operation. It is diferent than a->name when a->name is a
+ dotted package name (e.g. spam.eggs)
+ */
+ PyObject *store_name;
+ PyObject *name = (a->asname == NULL) ? a->name : a->asname;
+ const Py_UNICODE *base = PyUnicode_AS_UNICODE(name);
+ Py_UNICODE *dot = Py_UNICODE_strchr(base, '.');
+ if (dot) {
+ store_name = PyUnicode_FromUnicode(base, dot - base);
+ if (!store_name)
+ return 0;
+ }
+ else {
+ store_name = name;
+ Py_INCREF(store_name);
+ }
+ if (PyUnicode_CompareWithASCIIString(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;
+ PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING);
+ PyErr_SyntaxLocation(st->st_filename, lineno);
+ Py_DECREF(store_name);
+ return 0;
+ }
+ st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR;
+ Py_DECREF(store_name);
+ return 1;
+ }
}
-static int
+static int
symtable_visit_comprehension(struct symtable *st, comprehension_ty lc)
{
- VISIT(st, expr, lc->target);
- VISIT(st, expr, lc->iter);
- VISIT_SEQ(st, expr, lc->ifs);
- return 1;
+ VISIT(st, expr, lc->target);
+ VISIT(st, expr, lc->iter);
+ VISIT_SEQ(st, expr, lc->ifs);
+ return 1;
}
-static int
+static int
symtable_visit_keyword(struct symtable *st, keyword_ty k)
{
- VISIT(st, expr, k->value);
- return 1;
+ VISIT(st, expr, k->value);
+ return 1;
}
-static int
+static int
symtable_visit_slice(struct symtable *st, slice_ty s)
{
- switch (s->kind) {
- case Slice_kind:
- if (s->v.Slice.lower)
- VISIT(st, expr, s->v.Slice.lower)
- if (s->v.Slice.upper)
- VISIT(st, expr, s->v.Slice.upper)
- if (s->v.Slice.step)
- VISIT(st, expr, s->v.Slice.step)
- break;
- case ExtSlice_kind:
- VISIT_SEQ(st, slice, s->v.ExtSlice.dims)
- break;
- case Index_kind:
- VISIT(st, expr, s->v.Index.value)
- break;
- }
- return 1;
+ switch (s->kind) {
+ case Slice_kind:
+ if (s->v.Slice.lower)
+ VISIT(st, expr, s->v.Slice.lower)
+ if (s->v.Slice.upper)
+ VISIT(st, expr, s->v.Slice.upper)
+ if (s->v.Slice.step)
+ VISIT(st, expr, s->v.Slice.step)
+ break;
+ case ExtSlice_kind:
+ VISIT_SEQ(st, slice, s->v.ExtSlice.dims)
+ break;
+ case Index_kind:
+ VISIT(st, expr, s->v.Index.value)
+ break;
+ }
+ return 1;
}
-static int
+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 */
- VISIT(st, expr, outermost->iter);
- /* Create comprehension scope for the rest */
- if (!scope_name ||
- !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, e->lineno)) {
- return 0;
- }
- st->st_cur->ste_generator = is_generator;
- /* Outermost iter is received as an argument */
- if (!symtable_implicit_arg(st, 0)) {
- symtable_exit_block(st, (void *)e);
- return 0;
- }
- /* 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_IN_BLOCK(st, expr, value, (void*)e);
- VISIT_IN_BLOCK(st, expr, elt, (void*)e);
- return symtable_exit_block(st, (void *)e);
+ 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 */
+ VISIT(st, expr, outermost->iter);
+ /* Create comprehension scope for the rest */
+ if (!scope_name ||
+ !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, e->lineno)) {
+ return 0;
+ }
+ st->st_cur->ste_generator = is_generator;
+ /* Outermost iter is received as an argument */
+ if (!symtable_implicit_arg(st, 0)) {
+ symtable_exit_block(st, (void *)e);
+ return 0;
+ }
+ /* 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_IN_BLOCK(st, expr, value, (void*)e);
+ VISIT_IN_BLOCK(st, expr, elt, (void*)e);
+ return symtable_exit_block(st, (void *)e);
}
-static int
+static int
symtable_visit_genexp(struct symtable *st, expr_ty e)
{
- return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr),
- e->v.GeneratorExp.generators,
- e->v.GeneratorExp.elt, NULL);
+ return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr),
+ e->v.GeneratorExp.generators,
+ e->v.GeneratorExp.elt, NULL);
}
-static int
+static int
symtable_visit_listcomp(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(listcomp),
+ e->v.ListComp.generators,
+ e->v.ListComp.elt, NULL);
}
static int
symtable_visit_setcomp(struct symtable *st, expr_ty e)
{
- return symtable_handle_comprehension(st, e, GET_IDENTIFIER(setcomp),
- e->v.SetComp.generators,
- e->v.SetComp.elt, NULL);
+ return symtable_handle_comprehension(st, e, GET_IDENTIFIER(setcomp),
+ e->v.SetComp.generators,
+ e->v.SetComp.elt, NULL);
}
static int
symtable_visit_dictcomp(struct symtable *st, expr_ty e)
{
- return symtable_handle_comprehension(st, e, GET_IDENTIFIER(dictcomp),
- e->v.DictComp.generators,
- e->v.DictComp.key,
- e->v.DictComp.value);
+ return symtable_handle_comprehension(st, e, GET_IDENTIFIER(dictcomp),
+ e->v.DictComp.generators,
+ e->v.DictComp.key,
+ e->v.DictComp.value);
}