mirror of
https://github.com/python/cpython.git
synced 2025-09-14 04:37:29 +00:00
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.
This commit is contained in:
parent
670fa52698
commit
cb17ae8b19
5 changed files with 289 additions and 336 deletions
147
Python/symtable.c
Normal file
147
Python/symtable.c
Normal file
|
@ -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 */
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue