summaryrefslogtreecommitdiffstats
path: root/Python/symtable.c
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2001-02-09 22:22:18 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2001-02-09 22:22:18 (GMT)
commitcb17ae8b19c35cc63e7daec871c025d903c49105 (patch)
tree763b5b42fc1a889f7445f77263aab2c5c3dd13a3 /Python/symtable.c
parent670fa52698e90b5025dc2434310eada42fcfdd4a (diff)
downloadcpython-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.c147
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 */
+};