Mercurial > cpython-lru_cache-weakref
view Python/symtable.c @ 16862:77a5470299db legacy-trunk
Add warning/error handlin for problematic nested scopes cases as
described in PEP 227.
symtable_check_unoptimized() warns about import * and exec with "in"
when it is used in a function that contains a nested function with
free variables. Warnings are issued unless nested scopes are in
effect, in which case these are SyntaxErrors.
symtable_check_shadow() warns about assignments in a function scope
that shadow free variables defined in a nested scope. This will
always generate a warning -- and will behave differently with nested
scopes than without.
Restore full checking for free vars in children, even when nested
scopes are not enabled. This is needed to support warnings for
shadowing.
Change symtable_warn() to return an int-- the return value of
PyErr_WarnExplicit.
Sundry cleanup: Remove commented out code. Break long lines.
| author | Jeremy Hylton <jeremy@alum.mit.edu> |
|---|---|
| date | Wed, 28 Feb 2001 22:54:51 +0000 |
| parents | 08d937107fe6 |
| children | 568c75dd5078 7bc473b2c654 |
line wrap: on
line source
#include "Python.h" #include "compile.h" #include "symtable.h" #include "graminit.h" #include "structmember.h" PyObject * PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno) { PySymtableEntryObject *ste = NULL; PyObject *k, *v; k = PyInt_FromLong(st->st_nscopes++); if (k == NULL) goto fail; v = PyDict_GetItem(st->st_symbols, k); if (v) /* XXX could check that name, type, lineno match */ { Py_INCREF(v); return v; } ste = (PySymtableEntryObject *)PyObject_New(PySymtableEntryObject, &PySymtableEntry_Type); ste->ste_table = st; ste->ste_id = k; v = PyString_FromString(name); if (v == NULL) goto fail; ste->ste_name = v; v = PyDict_New(); if (v == NULL) goto fail; ste->ste_symbols = v; v = PyList_New(0); if (v == NULL) goto fail; ste->ste_varnames = v; v = PyList_New(0); if (v == NULL) goto fail; ste->ste_children = v; ste->ste_optimized = 0; ste->ste_lineno = lineno; switch (type) { case funcdef: case lambdef: ste->ste_type = TYPE_FUNCTION; break; case classdef: ste->ste_type = TYPE_CLASS; break; case single_input: case eval_input: case file_input: ste->ste_type = TYPE_MODULE; break; } if (st->st_cur == NULL) ste->ste_nested = 0; else if (st->st_cur->ste_nested || st->st_cur->ste_type == TYPE_FUNCTION) ste->ste_nested = 1; else ste->ste_nested = 0; ste->ste_child_free = 0; if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) goto fail; return (PyObject *)ste; fail: Py_XDECREF(ste); return NULL; } static PyObject * ste_repr(PySymtableEntryObject *ste) { char buf[256]; sprintf(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 ste_dealloc(PySymtableEntryObject *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(PySymtableEntryObject, x) static struct memberlist 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}, {"type", T_INT, OFF(ste_type), READONLY}, {"lineno", T_INT, OFF(ste_lineno), READONLY}, {"optimized",T_INT, OFF(ste_optimized), READONLY}, {"nested", T_INT, OFF(ste_nested), READONLY}, {NULL} }; static PyObject * ste_getattr(PySymtableEntryObject *ste, char *name) { return PyMember_Get((char *)ste, ste_memberlist, name); } PyTypeObject PySymtableEntry_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "symtable entry", sizeof(PySymtableEntryObject), 0, (destructor)ste_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc)ste_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (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 */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ };
