diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-02-09 22:22:18 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-02-09 22:22:18 (GMT) |
commit | cb17ae8b19c35cc63e7daec871c025d903c49105 (patch) | |
tree | 763b5b42fc1a889f7445f77263aab2c5c3dd13a3 /Python/symtable.c | |
parent | 670fa52698e90b5025dc2434310eada42fcfdd4a (diff) | |
download | cpython-cb17ae8b19c35cc63e7daec871c025d903c49105.zip cpython-cb17ae8b19c35cc63e7daec871c025d903c49105.tar.gz cpython-cb17ae8b19c35cc63e7daec871c025d903c49105.tar.bz2 |
Relax the rules for using 'from ... import *' and exec in the presence
of nested functions. Either is allowed in a function if it contains
no defs or lambdas or the defs and lambdas it contains have no free
variables. If a function is itself nested and has free variables,
either is illegal.
Revise the symtable to use a PySymtableEntryObject, which holds all
the revelent information for a scope, rather than using a bunch of
st_cur_XXX pointers in the symtable struct. The changes simplify the
internal management of the current symtable scope and of the stack.
Added new C source file: Python/symtable.c. (Does the Windows build
process need to be updated?)
As part of these changes, the initial _symtable module interface
introduced in 2.1a2 is replaced. A dictionary of
PySymtableEntryObjects are returned.
Diffstat (limited to 'Python/symtable.c')
-rw-r--r-- | Python/symtable.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/Python/symtable.c b/Python/symtable.c new file mode 100644 index 0000000..5dc0272 --- /dev/null +++ b/Python/symtable.c @@ -0,0 +1,147 @@ +#include "Python.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 */ + 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 = 1; + 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 */ +}; |