mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +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
|
@ -14,61 +14,51 @@ extern "C" {
|
||||||
block; the integer values are used to store several flags,
|
block; the integer values are used to store several flags,
|
||||||
e.g. DEF_PARAM indicates that a variable is a parameter to a
|
e.g. DEF_PARAM indicates that a variable is a parameter to a
|
||||||
function.
|
function.
|
||||||
|
|
||||||
The slots st_cur_XXX pointers always refer to the current code
|
|
||||||
block. The st_cur slot is the symbol dictionary. The st_cur_id
|
|
||||||
slot is the id is the key in st_symbols. The st_cur_name slot is
|
|
||||||
the name of the current scope. The st_cur_type slot is one of
|
|
||||||
TYPE_FUNCTION, TYPE_CLASS, or TYPE_MODULE. The st_cur_children is
|
|
||||||
a list of the ids of the current node's children.
|
|
||||||
|
|
||||||
The st_symbols slot is a dictionary that maps code block ids to
|
|
||||||
symbol dictionaries. The keys are generated by a counter that is
|
|
||||||
incremented each time a new code block is found. The counter is
|
|
||||||
identifies a specific scope, because both passes walk the parse
|
|
||||||
tree in the same order.
|
|
||||||
|
|
||||||
The st_varnames slot is a dictionary that maps code block ids to
|
|
||||||
parameter lists. The st_global slot always refers to the symbol
|
|
||||||
dictionary for the module.
|
|
||||||
|
|
||||||
The st_children slot is a dictionary that maps ids to a list
|
|
||||||
containing the ids of its children.
|
|
||||||
|
|
||||||
If st_keep is true then the namespace info pushed on st_stack will
|
|
||||||
also be stored in st_scopes. This is useful if the symbol table is
|
|
||||||
being passed to something other than the compiler.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct _symtable_entry;
|
||||||
|
|
||||||
struct symtable {
|
struct symtable {
|
||||||
int st_pass; /* pass == 1 or 2 */
|
int st_pass; /* pass == 1 or 2 */
|
||||||
int st_keep; /* true if symtable will be returned */
|
|
||||||
char *st_filename; /* name of file being compiled */
|
char *st_filename; /* name of file being compiled */
|
||||||
PyObject *st_symbols; /* dictionary of symbol tables */
|
struct _symtable_entry *st_cur; /* current symbol table entry */
|
||||||
PyObject *st_varnames; /* dictionary of parameter lists */
|
PyObject *st_symbols; /* dictionary of symbol table entries */
|
||||||
PyObject *st_stack; /* stack of namespace info */
|
PyObject *st_stack; /* stack of namespace info */
|
||||||
PyObject *st_scopes; /* dictionary of namespace info */
|
|
||||||
PyObject *st_children; /* dictionary (id=[ids]) */
|
|
||||||
PyObject *st_cur; /* borrowed ref to dict in st_symbols */
|
|
||||||
PyObject *st_cur_name; /* string, name of current scope */
|
|
||||||
PyObject *st_cur_id; /* int id of current code block */
|
|
||||||
PyObject *st_cur_children; /* ref to current children list */
|
|
||||||
int st_cur_type; /* type of current scope */
|
|
||||||
int st_cur_lineno; /* line number where current scope begins */
|
|
||||||
PyObject *st_global; /* borrowed ref to MODULE in st_symbols */
|
PyObject *st_global; /* borrowed ref to MODULE in st_symbols */
|
||||||
int st_nscopes; /* number of scopes */
|
int st_nscopes; /* number of scopes */
|
||||||
int st_errors; /* number of errors */
|
int st_errors; /* number of errors */
|
||||||
char *st_private; /* name of current class or NULL */
|
char *st_private; /* name of current class or NULL */
|
||||||
int st_tmpname; /* temporary name counter */
|
int st_tmpname; /* temporary name counter */
|
||||||
int st_nested; /* bool (true if nested scope) */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _symtable_entry {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject *ste_id; /* int: key in st_symbols) */
|
||||||
|
PyObject *ste_symbols; /* dict: name to flags) */
|
||||||
|
PyObject *ste_name; /* string: name of scope */
|
||||||
|
PyObject *ste_varnames; /* list of variable names */
|
||||||
|
PyObject *ste_children; /* list of child ids */
|
||||||
|
int ste_type; /* module, class, or function */
|
||||||
|
int ste_lineno; /* first line of scope */
|
||||||
|
int ste_optimized; /* true if namespace is optimized */
|
||||||
|
int ste_nested; /* true if scope is nested */
|
||||||
|
int ste_child_free; /* true if a child scope has free variables,
|
||||||
|
including free refs to globals */
|
||||||
|
struct symtable *ste_table;
|
||||||
|
} PySymtableEntryObject;
|
||||||
|
|
||||||
|
extern DL_IMPORT(PyTypeObject) PySymtableEntry_Type;
|
||||||
|
|
||||||
|
#define PySymtableEntry_Check(op) ((op)->ob_type == &PySymtableEntry_Type)
|
||||||
|
|
||||||
|
extern DL_IMPORT(PyObject *) PySymtableEntry_New(struct symtable *,
|
||||||
|
char *, int, int);
|
||||||
|
|
||||||
DL_IMPORT(struct symtable *) PyNode_CompileSymtable(struct _node *, char *);
|
DL_IMPORT(struct symtable *) PyNode_CompileSymtable(struct _node *, char *);
|
||||||
DL_IMPORT(void) PySymtable_Free(struct symtable *);
|
DL_IMPORT(void) PySymtable_Free(struct symtable *);
|
||||||
|
|
||||||
|
|
||||||
#define TOP "global"
|
#define TOP "global"
|
||||||
#define NOOPT ".noopt"
|
|
||||||
|
|
||||||
/* Flags for def-use information */
|
/* Flags for def-use information */
|
||||||
|
|
||||||
|
|
|
@ -228,6 +228,7 @@ PYTHON_OBJS= \
|
||||||
Python/pystate.o \
|
Python/pystate.o \
|
||||||
Python/pythonrun.o \
|
Python/pythonrun.o \
|
||||||
Python/structmember.o \
|
Python/structmember.o \
|
||||||
|
Python/symtable.o \
|
||||||
Python/sysmodule.o \
|
Python/sysmodule.o \
|
||||||
Python/traceback.o \
|
Python/traceback.o \
|
||||||
Python/getopt.o \
|
Python/getopt.o \
|
||||||
|
|
|
@ -31,7 +31,7 @@ symtable_symtable(PyObject *self, PyObject *args)
|
||||||
st = Py_SymtableString(str, filename, start);
|
st = Py_SymtableString(str, filename, start);
|
||||||
if (st == NULL)
|
if (st == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
t = Py_BuildValue("OO", st->st_symbols, st->st_scopes);
|
t = Py_BuildValue("O", st->st_symbols);
|
||||||
PySymtable_Free(st);
|
PySymtable_Free(st);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
411
Python/compile.c
411
Python/compile.c
|
@ -52,8 +52,8 @@ int Py_OptimizeFlag = 0;
|
||||||
#define DUPLICATE_ARGUMENT \
|
#define DUPLICATE_ARGUMENT \
|
||||||
"duplicate argument '%s' in function definition"
|
"duplicate argument '%s' in function definition"
|
||||||
|
|
||||||
#define ILLEGAL_IMPORT_STAR \
|
#define ILLEGAL_DYNAMIC_SCOPE \
|
||||||
"'from ... import *' may only occur in a module scope"
|
"%.100s: exec or 'import *' makes names ambiguous in nested scope"
|
||||||
|
|
||||||
#define MANGLE_LEN 256
|
#define MANGLE_LEN 256
|
||||||
|
|
||||||
|
@ -484,10 +484,9 @@ static int get_ref_type(struct compiling *, char *);
|
||||||
/* symtable operations */
|
/* symtable operations */
|
||||||
static int symtable_build(struct compiling *, node *);
|
static int symtable_build(struct compiling *, node *);
|
||||||
static int symtable_load_symbols(struct compiling *);
|
static int symtable_load_symbols(struct compiling *);
|
||||||
static struct symtable *symtable_init(int);
|
static struct symtable *symtable_init(void);
|
||||||
static void symtable_enter_scope(struct symtable *, char *, int, int);
|
static void symtable_enter_scope(struct symtable *, char *, int, int);
|
||||||
static int symtable_exit_scope(struct symtable *);
|
static int symtable_exit_scope(struct symtable *);
|
||||||
static int symtable_update_cur(struct symtable *);
|
|
||||||
static int symtable_add_def(struct symtable *, char *, int);
|
static int symtable_add_def(struct symtable *, char *, int);
|
||||||
static int symtable_add_def_o(struct symtable *, PyObject *, PyObject *, int);
|
static int symtable_add_def_o(struct symtable *, PyObject *, PyObject *, int);
|
||||||
|
|
||||||
|
@ -638,10 +637,6 @@ com_addbyte(struct compiling *c, int byte)
|
||||||
/*fprintf(stderr, "%3d: %3d\n", c->c_nexti, byte);*/
|
/*fprintf(stderr, "%3d: %3d\n", c->c_nexti, byte);*/
|
||||||
assert(byte >= 0 && byte <= 255);
|
assert(byte >= 0 && byte <= 255);
|
||||||
if (byte < 0 || byte > 255) {
|
if (byte < 0 || byte > 255) {
|
||||||
/*
|
|
||||||
fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
|
|
||||||
fatal("com_addbyte: byte out of range");
|
|
||||||
*/
|
|
||||||
com_error(c, PyExc_SystemError,
|
com_error(c, PyExc_SystemError,
|
||||||
"com_addbyte: byte out of range");
|
"com_addbyte: byte out of range");
|
||||||
}
|
}
|
||||||
|
@ -838,7 +833,6 @@ mangle(char *p, char *name, char *buffer, size_t maxlen)
|
||||||
buffer[0] = '_';
|
buffer[0] = '_';
|
||||||
strncpy(buffer+1, p, plen);
|
strncpy(buffer+1, p, plen);
|
||||||
strcpy(buffer+1+plen, name);
|
strcpy(buffer+1+plen, name);
|
||||||
/* fprintf(stderr, "mangle %s -> %s\n", name, buffer); */
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +891,7 @@ com_addop_varname(struct compiling *c, int kind, char *name)
|
||||||
reftype = get_ref_type(c, name);
|
reftype = get_ref_type(c, name);
|
||||||
switch (reftype) {
|
switch (reftype) {
|
||||||
case LOCAL:
|
case LOCAL:
|
||||||
if (c->c_symtable->st_cur_type == TYPE_FUNCTION)
|
if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION)
|
||||||
scope = NAME_LOCAL;
|
scope = NAME_LOCAL;
|
||||||
break;
|
break;
|
||||||
case GLOBAL_EXPLICIT:
|
case GLOBAL_EXPLICIT:
|
||||||
|
@ -982,7 +976,6 @@ com_addop_varname(struct compiling *c, int kind, char *name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
/* fprintf(stderr, " addoparg(op=%d, arg=%d)\n", op, i);*/
|
|
||||||
com_addoparg(c, op, i);
|
com_addoparg(c, op, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1426,7 +1419,6 @@ com_atom(struct compiling *c, node *n)
|
||||||
com_push(c, 1);
|
com_push(c, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(ch)); */
|
|
||||||
com_error(c, PyExc_SystemError,
|
com_error(c, PyExc_SystemError,
|
||||||
"com_atom: unexpected node type");
|
"com_atom: unexpected node type");
|
||||||
}
|
}
|
||||||
|
@ -2150,6 +2142,10 @@ com_test(struct compiling *c, node *n)
|
||||||
symtable_enter_scope(c->c_symtable, "lambda", lambdef,
|
symtable_enter_scope(c->c_symtable, "lambda", lambdef,
|
||||||
n->n_lineno);
|
n->n_lineno);
|
||||||
co = (PyObject *) icompile(CHILD(n, 0), c);
|
co = (PyObject *) icompile(CHILD(n, 0), c);
|
||||||
|
if (co == NULL) {
|
||||||
|
c->c_errors++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
symtable_exit_scope(c->c_symtable);
|
symtable_exit_scope(c->c_symtable);
|
||||||
if (co == NULL) {
|
if (co == NULL) {
|
||||||
c->c_errors++;
|
c->c_errors++;
|
||||||
|
@ -2326,8 +2322,8 @@ com_assign(struct compiling *c, node *n, int assigning, node *augn)
|
||||||
n = CHILD(n, 0);
|
n = CHILD(n, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case power: /* atom trailer* ('**' power)* */
|
case power: /* atom trailer* ('**' power)*
|
||||||
/* ('+'|'-'|'~') factor | atom trailer* */
|
('+'|'-'|'~') factor | atom trailer* */
|
||||||
if (TYPE(CHILD(n, 0)) != atom) {
|
if (TYPE(CHILD(n, 0)) != atom) {
|
||||||
com_error(c, PyExc_SyntaxError,
|
com_error(c, PyExc_SyntaxError,
|
||||||
"can't assign to operator");
|
"can't assign to operator");
|
||||||
|
@ -2408,7 +2404,6 @@ com_assign(struct compiling *c, node *n, int assigning, node *augn)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(n)); */
|
|
||||||
com_error(c, PyExc_SystemError,
|
com_error(c, PyExc_SystemError,
|
||||||
"com_assign: bad node");
|
"com_assign: bad node");
|
||||||
return;
|
return;
|
||||||
|
@ -3155,7 +3150,7 @@ com_suite(struct compiling *c, node *n)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < NCH(n); i++) {
|
for (i = 0; i < NCH(n) && c->c_errors == 0; i++) {
|
||||||
node *ch = CHILD(n, i);
|
node *ch = CHILD(n, i);
|
||||||
if (TYPE(ch) == stmt)
|
if (TYPE(ch) == stmt)
|
||||||
com_node(c, ch);
|
com_node(c, ch);
|
||||||
|
@ -3353,6 +3348,8 @@ static void
|
||||||
com_node(struct compiling *c, node *n)
|
com_node(struct compiling *c, node *n)
|
||||||
{
|
{
|
||||||
loop:
|
loop:
|
||||||
|
if (c->c_errors)
|
||||||
|
return;
|
||||||
switch (TYPE(n)) {
|
switch (TYPE(n)) {
|
||||||
|
|
||||||
/* Definition nodes */
|
/* Definition nodes */
|
||||||
|
@ -3492,7 +3489,6 @@ com_node(struct compiling *c, node *n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(n)); */
|
|
||||||
com_error(c, PyExc_SystemError,
|
com_error(c, PyExc_SystemError,
|
||||||
"com_node: unexpected node type");
|
"com_node: unexpected node type");
|
||||||
}
|
}
|
||||||
|
@ -3775,7 +3771,6 @@ compile_node(struct compiling *c, node *n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(n)); */
|
|
||||||
com_error(c, PyExc_SystemError,
|
com_error(c, PyExc_SystemError,
|
||||||
"compile_node: unexpected node type");
|
"compile_node: unexpected node type");
|
||||||
}
|
}
|
||||||
|
@ -3809,7 +3804,7 @@ PyNode_CompileSymtable(node *n, char *filename)
|
||||||
{
|
{
|
||||||
struct symtable *st;
|
struct symtable *st;
|
||||||
|
|
||||||
st = symtable_init(1);
|
st = symtable_init();
|
||||||
if (st == NULL)
|
if (st == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
assert(st->st_symbols != NULL);
|
assert(st->st_symbols != NULL);
|
||||||
|
@ -3844,7 +3839,7 @@ jcompile(node *n, char *filename, struct compiling *base)
|
||||||
sc.c_symtable = base->c_symtable;
|
sc.c_symtable = base->c_symtable;
|
||||||
/* c_symtable still points to parent's symbols */
|
/* c_symtable still points to parent's symbols */
|
||||||
if (base->c_nested
|
if (base->c_nested
|
||||||
|| (sc.c_symtable->st_cur_type == TYPE_FUNCTION))
|
|| (sc.c_symtable->st_cur->ste_type == TYPE_FUNCTION))
|
||||||
sc.c_nested = 1;
|
sc.c_nested = 1;
|
||||||
} else {
|
} else {
|
||||||
sc.c_private = NULL;
|
sc.c_private = NULL;
|
||||||
|
@ -3854,8 +3849,10 @@ jcompile(node *n, char *filename, struct compiling *base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
co = NULL;
|
co = NULL;
|
||||||
if (symtable_load_symbols(&sc) < 0)
|
if (symtable_load_symbols(&sc) < 0) {
|
||||||
|
sc.c_errors++;
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
compile_node(&sc, n);
|
compile_node(&sc, n);
|
||||||
com_done(&sc);
|
com_done(&sc);
|
||||||
if (sc.c_errors == 0) {
|
if (sc.c_errors == 0) {
|
||||||
|
@ -3947,10 +3944,12 @@ get_ref_type(struct compiling *c, char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char buf[250];
|
char buf[350];
|
||||||
sprintf(buf, "unknown scope for %.100s in %.100s (%s)",
|
sprintf(buf,
|
||||||
|
"unknown scope for %.100s in %.100s(%s) in %s",
|
||||||
name, c->c_name,
|
name, c->c_name,
|
||||||
PyObject_REPR(c->c_symtable->st_cur_id));
|
PyObject_REPR(c->c_symtable->st_cur->ste_id),
|
||||||
|
c->c_filename);
|
||||||
Py_FatalError(buf);
|
Py_FatalError(buf);
|
||||||
}
|
}
|
||||||
return -1; /* can't get here */
|
return -1; /* can't get here */
|
||||||
|
@ -3959,7 +3958,7 @@ get_ref_type(struct compiling *c, char *name)
|
||||||
static int
|
static int
|
||||||
symtable_build(struct compiling *c, node *n)
|
symtable_build(struct compiling *c, node *n)
|
||||||
{
|
{
|
||||||
if ((c->c_symtable = symtable_init(0)) == NULL)
|
if ((c->c_symtable = symtable_init()) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
c->c_symtable->st_filename = c->c_filename;
|
c->c_symtable->st_filename = c->c_filename;
|
||||||
symtable_enter_scope(c->c_symtable, TOP, TYPE(n), n->n_lineno);
|
symtable_enter_scope(c->c_symtable, TOP, TYPE(n), n->n_lineno);
|
||||||
|
@ -3979,9 +3978,10 @@ symtable_load_symbols(struct compiling *c)
|
||||||
{
|
{
|
||||||
static PyObject *implicit = NULL;
|
static PyObject *implicit = NULL;
|
||||||
PyObject *name, *varnames, *v;
|
PyObject *name, *varnames, *v;
|
||||||
int i, info, pos;
|
int i, flags, pos;
|
||||||
int nlocals, nfrees, ncells;
|
int nlocals, nfrees, ncells, nimplicit;
|
||||||
struct symtable *st = c->c_symtable;
|
struct symtable *st = c->c_symtable;
|
||||||
|
PySymtableEntryObject *ste = st->st_cur;
|
||||||
|
|
||||||
if (implicit == NULL) {
|
if (implicit == NULL) {
|
||||||
implicit = PyInt_FromLong(1);
|
implicit = PyInt_FromLong(1);
|
||||||
|
@ -3990,11 +3990,13 @@ symtable_load_symbols(struct compiling *c)
|
||||||
}
|
}
|
||||||
v = NULL;
|
v = NULL;
|
||||||
|
|
||||||
varnames = PyDict_GetItem(st->st_varnames, st->st_cur_id);
|
varnames = st->st_cur->ste_varnames;
|
||||||
if (varnames == NULL) {
|
if (varnames == NULL) {
|
||||||
varnames = PyList_New(0);
|
varnames = PyList_New(0);
|
||||||
if (varnames == NULL)
|
if (varnames == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
ste->ste_varnames = varnames;
|
||||||
|
Py_INCREF(varnames);
|
||||||
} else
|
} else
|
||||||
Py_INCREF(varnames);
|
Py_INCREF(varnames);
|
||||||
c->c_varnames = varnames;
|
c->c_varnames = varnames;
|
||||||
|
@ -4013,6 +4015,7 @@ symtable_load_symbols(struct compiling *c)
|
||||||
c->c_argcount = nlocals;
|
c->c_argcount = nlocals;
|
||||||
nfrees = 0;
|
nfrees = 0;
|
||||||
ncells = 0;
|
ncells = 0;
|
||||||
|
nimplicit = 0;
|
||||||
for (i = 0; i < nlocals; ++i) {
|
for (i = 0; i < nlocals; ++i) {
|
||||||
v = PyInt_FromLong(i);
|
v = PyInt_FromLong(i);
|
||||||
if (PyDict_SetItem(c->c_locals,
|
if (PyDict_SetItem(c->c_locals,
|
||||||
|
@ -4024,13 +4027,12 @@ symtable_load_symbols(struct compiling *c)
|
||||||
/* XXX The cases below define the rules for whether a name is
|
/* XXX The cases below define the rules for whether a name is
|
||||||
local or global. The logic could probably be clearer. */
|
local or global. The logic could probably be clearer. */
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (PyDict_Next(st->st_cur, &pos, &name, &v)) {
|
while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {
|
||||||
info = PyInt_AS_LONG(v);
|
flags = PyInt_AS_LONG(v);
|
||||||
|
|
||||||
if (info & DEF_FREE_GLOBAL)
|
if (flags & DEF_FREE_GLOBAL)
|
||||||
/* undo the original DEF_FREE */
|
/* undo the original DEF_FREE */
|
||||||
info &= ~(DEF_FREE | DEF_FREE_CLASS);
|
flags &= ~(DEF_FREE | DEF_FREE_CLASS);
|
||||||
|
|
||||||
|
|
||||||
/* Seperate logic for DEF_FREE. If it occurs in a
|
/* Seperate logic for DEF_FREE. If it occurs in a
|
||||||
function, it indicates a local that we must
|
function, it indicates a local that we must
|
||||||
|
@ -4039,10 +4041,10 @@ symtable_load_symbols(struct compiling *c)
|
||||||
variable with the same name.
|
variable with the same name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((info & (DEF_FREE | DEF_FREE_CLASS))
|
if ((flags & (DEF_FREE | DEF_FREE_CLASS))
|
||||||
&& (info & (DEF_LOCAL | DEF_PARAM))) {
|
&& (flags & (DEF_LOCAL | DEF_PARAM))) {
|
||||||
PyObject *dict;
|
PyObject *dict;
|
||||||
if (st->st_cur_type == TYPE_FUNCTION) {
|
if (ste->ste_type == TYPE_FUNCTION) {
|
||||||
v = PyInt_FromLong(ncells++);
|
v = PyInt_FromLong(ncells++);
|
||||||
dict = c->c_cellvars;
|
dict = c->c_cellvars;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4056,49 +4058,50 @@ symtable_load_symbols(struct compiling *c)
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info & DEF_STAR) {
|
if (flags & DEF_STAR) {
|
||||||
c->c_argcount--;
|
c->c_argcount--;
|
||||||
c->c_flags |= CO_VARARGS;
|
c->c_flags |= CO_VARARGS;
|
||||||
} else if (info & DEF_DOUBLESTAR) {
|
} else if (flags & DEF_DOUBLESTAR) {
|
||||||
c->c_argcount--;
|
c->c_argcount--;
|
||||||
c->c_flags |= CO_VARKEYWORDS;
|
c->c_flags |= CO_VARKEYWORDS;
|
||||||
} else if (info & DEF_INTUPLE)
|
} else if (flags & DEF_INTUPLE)
|
||||||
c->c_argcount--;
|
c->c_argcount--;
|
||||||
else if (info & DEF_GLOBAL) {
|
else if (flags & DEF_GLOBAL) {
|
||||||
if ((info & DEF_PARAM)
|
if ((flags & DEF_PARAM)
|
||||||
&& (PyString_AS_STRING(name)[0] != '.')){
|
&& (PyString_AS_STRING(name)[0] != '.')){
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"name '%.400s' is local and global",
|
"name '%.400s' is local and global",
|
||||||
PyString_AS_STRING(name));
|
PyString_AS_STRING(name));
|
||||||
set_error_location(st->st_filename,
|
set_error_location(st->st_filename,
|
||||||
st->st_cur_lineno);
|
ste->ste_lineno);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (PyDict_SetItem(c->c_globals, name, Py_None) < 0)
|
if (PyDict_SetItem(c->c_globals, name, Py_None) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (info & DEF_FREE_GLOBAL) {
|
} else if (flags & DEF_FREE_GLOBAL) {
|
||||||
|
nimplicit++;
|
||||||
if (PyDict_SetItem(c->c_globals, name, implicit) < 0)
|
if (PyDict_SetItem(c->c_globals, name, implicit) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if ((info & DEF_LOCAL) && !(info & DEF_PARAM)) {
|
} else if ((flags & DEF_LOCAL) && !(flags & DEF_PARAM)) {
|
||||||
v = PyInt_FromLong(nlocals++);
|
v = PyInt_FromLong(nlocals++);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (PyDict_SetItem(c->c_locals, name, v) < 0)
|
if (PyDict_SetItem(c->c_locals, name, v) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
if (st->st_cur_type != TYPE_CLASS)
|
if (ste->ste_type != TYPE_CLASS)
|
||||||
if (PyList_Append(c->c_varnames, name) < 0)
|
if (PyList_Append(c->c_varnames, name) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (is_free(info)) {
|
} else if (is_free(flags)) {
|
||||||
if (st->st_nested) {
|
if (ste->ste_nested) {
|
||||||
v = PyInt_FromLong(nfrees++);
|
v = PyInt_FromLong(nfrees++);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (PyDict_SetItem(c->c_freevars,
|
if (PyDict_SetItem(c->c_freevars, name, v) < 0)
|
||||||
name, v) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
} else {
|
} else {
|
||||||
|
nimplicit++;
|
||||||
if (PyDict_SetItem(c->c_globals, name,
|
if (PyDict_SetItem(c->c_globals, name,
|
||||||
implicit) < 0)
|
implicit) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -4120,24 +4123,24 @@ symtable_load_symbols(struct compiling *c)
|
||||||
Py_DECREF(o);
|
Py_DECREF(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st->st_cur_type == TYPE_FUNCTION)
|
if (ste->ste_type == TYPE_FUNCTION)
|
||||||
c->c_nlocals = nlocals;
|
c->c_nlocals = nlocals;
|
||||||
|
|
||||||
if (st->st_cur_type != TYPE_MODULE)
|
if (ste->ste_type != TYPE_MODULE)
|
||||||
c->c_flags |= CO_NEWLOCALS;
|
c->c_flags |= CO_NEWLOCALS;
|
||||||
if (st->st_cur_type == TYPE_FUNCTION) {
|
if (ste->ste_type == TYPE_FUNCTION) {
|
||||||
if (PyDict_GetItemString(st->st_cur, NOOPT) == NULL)
|
if (ste->ste_optimized)
|
||||||
c->c_flags |= CO_OPTIMIZED;
|
c->c_flags |= CO_OPTIMIZED;
|
||||||
else if (ncells || nfrees) {
|
else if (ncells || nfrees
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
|| (ste->ste_nested && nimplicit)
|
||||||
"function %.100s: may not use lexical scoping"
|
|| ste->ste_child_free) {
|
||||||
" and 'import *' or exec in same function",
|
PyErr_Format(PyExc_SyntaxError, ILLEGAL_DYNAMIC_SCOPE,
|
||||||
PyString_AS_STRING(st->st_cur_name));
|
PyString_AS_STRING(ste->ste_name));
|
||||||
set_error_location(st->st_filename,
|
set_error_location(st->st_filename, ste->ste_lineno);
|
||||||
st->st_cur_lineno);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -4147,43 +4150,20 @@ symtable_load_symbols(struct compiling *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct symtable *
|
static struct symtable *
|
||||||
symtable_init(int keep)
|
symtable_init()
|
||||||
{
|
{
|
||||||
struct symtable *st;
|
struct symtable *st;
|
||||||
PyObject *d;
|
|
||||||
|
|
||||||
st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable));
|
st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable));
|
||||||
if (st == NULL)
|
if (st == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
st->st_pass = 1;
|
st->st_pass = 1;
|
||||||
st->st_keep = keep;
|
|
||||||
st->st_filename = NULL;
|
st->st_filename = NULL;
|
||||||
if ((st->st_stack = PyList_New(0)) == NULL)
|
if ((st->st_stack = PyList_New(0)) == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((st->st_symbols = PyDict_New()) == NULL)
|
if ((st->st_symbols = PyDict_New()) == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((st->st_children = PyDict_New()) == NULL)
|
|
||||||
goto fail;
|
|
||||||
if ((st->st_varnames = PyDict_New()) == NULL)
|
|
||||||
goto fail;
|
|
||||||
if ((d = PyDict_New()) == NULL)
|
|
||||||
goto fail;
|
|
||||||
if (PyDict_SetItemString(st->st_symbols, TOP, d) < 0)
|
|
||||||
goto fail;
|
|
||||||
st->st_global = d;
|
|
||||||
Py_DECREF(d);
|
|
||||||
if (keep) {
|
|
||||||
if ((d = PyDict_New()) == NULL)
|
|
||||||
goto fail;
|
|
||||||
st->st_scopes = d;
|
|
||||||
} else
|
|
||||||
st->st_scopes = NULL;
|
|
||||||
st->st_cur = NULL;
|
st->st_cur = NULL;
|
||||||
st->st_cur_id = NULL;
|
|
||||||
st->st_cur_name = NULL;
|
|
||||||
st->st_cur_children = NULL;
|
|
||||||
st->st_cur_type = 0;
|
|
||||||
st->st_nested = 0;
|
|
||||||
st->st_nscopes = 0;
|
st->st_nscopes = 0;
|
||||||
st->st_errors = 0;
|
st->st_errors = 0;
|
||||||
st->st_tmpname = 0;
|
st->st_tmpname = 0;
|
||||||
|
@ -4198,51 +4178,10 @@ void
|
||||||
PySymtable_Free(struct symtable *st)
|
PySymtable_Free(struct symtable *st)
|
||||||
{
|
{
|
||||||
Py_XDECREF(st->st_symbols);
|
Py_XDECREF(st->st_symbols);
|
||||||
Py_XDECREF(st->st_varnames);
|
|
||||||
Py_XDECREF(st->st_children);
|
|
||||||
Py_XDECREF(st->st_stack);
|
Py_XDECREF(st->st_stack);
|
||||||
Py_XDECREF(st->st_scopes);
|
|
||||||
Py_XDECREF(st->st_cur_id);
|
|
||||||
Py_XDECREF(st->st_cur_name);
|
|
||||||
PyMem_Free((void *)st);
|
PyMem_Free((void *)st);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
make_scope_info(PyObject *id, PyObject *name, int nested, int type,
|
|
||||||
int lineno)
|
|
||||||
{
|
|
||||||
PyObject *t, *i1 = NULL, *i2 = NULL, *i3 = NULL;
|
|
||||||
|
|
||||||
t = PyTuple_New(5);
|
|
||||||
if (t == NULL)
|
|
||||||
return NULL;
|
|
||||||
i1 = PyInt_FromLong(nested);
|
|
||||||
if (i1 == NULL)
|
|
||||||
goto fail;
|
|
||||||
i2 = PyInt_FromLong(type);
|
|
||||||
if (i2 == NULL)
|
|
||||||
goto fail;
|
|
||||||
i3 = PyInt_FromLong(lineno);
|
|
||||||
if (i3 == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
Py_INCREF(name);
|
|
||||||
Py_INCREF(id);
|
|
||||||
PyTuple_SET_ITEM(t, 0, name);
|
|
||||||
PyTuple_SET_ITEM(t, 1, id);
|
|
||||||
/* i1 & i2 alloced here; don't need incref */
|
|
||||||
PyTuple_SET_ITEM(t, 2, i1);
|
|
||||||
PyTuple_SET_ITEM(t, 3, i2);
|
|
||||||
PyTuple_SET_ITEM(t, 4, i3);
|
|
||||||
return t;
|
|
||||||
fail:
|
|
||||||
Py_XDECREF(t);
|
|
||||||
Py_XDECREF(i1);
|
|
||||||
Py_XDECREF(i2);
|
|
||||||
Py_XDECREF(i3);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When the compiler exits a scope, it must should update the scope's
|
/* When the compiler exits a scope, it must should update the scope's
|
||||||
free variable information with the list of free variables in its
|
free variable information with the list of free variables in its
|
||||||
children.
|
children.
|
||||||
|
@ -4250,7 +4189,7 @@ make_scope_info(PyObject *id, PyObject *name, int nested, int type,
|
||||||
Variables that are free in children and defined in the current
|
Variables that are free in children and defined in the current
|
||||||
scope are cellvars.
|
scope are cellvars.
|
||||||
|
|
||||||
If the scope being exited is defined at the top-level (st_nested is
|
If the scope being exited is defined at the top-level (ste_nested is
|
||||||
false), free variables in children that are not defined here are
|
false), free variables in children that are not defined here are
|
||||||
implicit globals.
|
implicit globals.
|
||||||
|
|
||||||
|
@ -4259,30 +4198,30 @@ make_scope_info(PyObject *id, PyObject *name, int nested, int type,
|
||||||
static int
|
static int
|
||||||
symtable_update_free_vars(struct symtable *st)
|
symtable_update_free_vars(struct symtable *st)
|
||||||
{
|
{
|
||||||
PyObject *dict, *o, *child, *name;
|
PyObject *o, *name;
|
||||||
int i, def;
|
int i, def;
|
||||||
|
PySymtableEntryObject *child, *ste = st->st_cur;
|
||||||
|
|
||||||
if (st->st_cur_type == TYPE_CLASS)
|
if (ste->ste_type == TYPE_CLASS)
|
||||||
def = DEF_FREE_CLASS;
|
def = DEF_FREE_CLASS;
|
||||||
else
|
else
|
||||||
def = DEF_FREE;
|
def = DEF_FREE;
|
||||||
for (i = 0; i < PyList_GET_SIZE(st->st_cur_children); ++i) {
|
for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
child = PyList_GET_ITEM(st->st_cur_children, i);
|
child = (PySymtableEntryObject *)\
|
||||||
dict = PyDict_GetItem(st->st_symbols, child);
|
PyList_GET_ITEM(ste->ste_children, i);
|
||||||
if (dict == NULL)
|
while (PyDict_Next(child->ste_symbols, &pos, &name, &o)) {
|
||||||
return -1;
|
|
||||||
while (PyDict_Next(dict, &pos, &name, &o)) {
|
|
||||||
int v = PyInt_AS_LONG(o);
|
int v = PyInt_AS_LONG(o);
|
||||||
if (!(is_free(v)))
|
if (!(is_free(v)))
|
||||||
continue; /* avoids indentation */
|
continue; /* avoids indentation */
|
||||||
if (st->st_nested) {
|
ste->ste_child_free = 1;
|
||||||
if (symtable_add_def_o(st, st->st_cur,
|
if (ste->ste_nested) {
|
||||||
|
if (symtable_add_def_o(st, ste->ste_symbols,
|
||||||
name, def) < 0)
|
name, def) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
if (symtable_check_global(st, child,
|
if (symtable_check_global(st, child->ste_id,
|
||||||
name) < 0)
|
name) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -4302,17 +4241,19 @@ symtable_check_global(struct symtable *st, PyObject *child, PyObject *name)
|
||||||
{
|
{
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
int v;
|
int v;
|
||||||
|
PySymtableEntryObject *ste = st->st_cur;
|
||||||
|
|
||||||
if (st->st_cur_type == TYPE_CLASS)
|
if (ste->ste_type == TYPE_CLASS)
|
||||||
return symtable_undo_free(st, child, name);
|
return symtable_undo_free(st, child, name);
|
||||||
o = PyDict_GetItem(st->st_cur, name);
|
o = PyDict_GetItem(ste->ste_symbols, name);
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
return symtable_undo_free(st, child, name);
|
return symtable_undo_free(st, child, name);
|
||||||
v = PyInt_AS_LONG(o);
|
v = PyInt_AS_LONG(o);
|
||||||
if (is_free(v) || (v & DEF_GLOBAL))
|
if (is_free(v) || (v & DEF_GLOBAL))
|
||||||
return symtable_undo_free(st, child, name);
|
return symtable_undo_free(st, child, name);
|
||||||
else
|
else
|
||||||
return symtable_add_def_o(st, st->st_cur, name, DEF_FREE);
|
return symtable_add_def_o(st, ste->ste_symbols,
|
||||||
|
name, DEF_FREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -4320,17 +4261,18 @@ symtable_undo_free(struct symtable *st, PyObject *id,
|
||||||
PyObject *name)
|
PyObject *name)
|
||||||
{
|
{
|
||||||
int i, v, x;
|
int i, v, x;
|
||||||
PyObject *dict, *children, *info;
|
PyObject *info;
|
||||||
|
PySymtableEntryObject *ste;
|
||||||
|
|
||||||
dict = PyDict_GetItem(st->st_symbols, id);
|
ste = (PySymtableEntryObject *)PyDict_GetItem(st->st_symbols, id);
|
||||||
if (dict == NULL)
|
if (ste == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
info = PyDict_GetItem(dict, name);
|
info = PyDict_GetItem(ste->ste_symbols, name);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
v = PyInt_AS_LONG(info);
|
v = PyInt_AS_LONG(info);
|
||||||
if (is_free(v)) {
|
if (is_free(v)) {
|
||||||
if (symtable_add_def_o(st, dict, name,
|
if (symtable_add_def_o(st, ste->ste_symbols, name,
|
||||||
DEF_FREE_GLOBAL) < 0)
|
DEF_FREE_GLOBAL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else
|
} else
|
||||||
|
@ -4338,10 +4280,11 @@ symtable_undo_free(struct symtable *st, PyObject *id,
|
||||||
then the recursion stops. */
|
then the recursion stops. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
children = PyDict_GetItem(st->st_children, id);
|
for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
|
||||||
for (i = 0; i < PyList_GET_SIZE(children); ++i) {
|
PySymtableEntryObject *child;
|
||||||
x = symtable_undo_free(st, PyList_GET_ITEM(children, i),
|
child = (PySymtableEntryObject *) \
|
||||||
name);
|
PyList_GET_ITEM(ste->ste_children, i);
|
||||||
|
x = symtable_undo_free(st, child->ste_id, name);
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -4351,141 +4294,41 @@ symtable_undo_free(struct symtable *st, PyObject *id,
|
||||||
static int
|
static int
|
||||||
symtable_exit_scope(struct symtable *st)
|
symtable_exit_scope(struct symtable *st)
|
||||||
{
|
{
|
||||||
PyObject *o;
|
|
||||||
int end;
|
int end;
|
||||||
|
|
||||||
if (st->st_pass == 1)
|
if (st->st_pass == 1)
|
||||||
symtable_update_free_vars(st);
|
symtable_update_free_vars(st);
|
||||||
if (st->st_cur_name) {
|
Py_DECREF(st->st_cur);
|
||||||
Py_XDECREF(st->st_cur_name);
|
|
||||||
Py_XDECREF(st->st_cur_id);
|
|
||||||
}
|
|
||||||
end = PyList_GET_SIZE(st->st_stack) - 1;
|
end = PyList_GET_SIZE(st->st_stack) - 1;
|
||||||
o = PyList_GET_ITEM(st->st_stack, end);
|
st->st_cur = (PySymtableEntryObject *)PyList_GET_ITEM(st->st_stack,
|
||||||
st->st_cur_name = PyTuple_GET_ITEM(o, 0);
|
end);
|
||||||
st->st_cur_id = PyTuple_GET_ITEM(o, 1);
|
|
||||||
st->st_nested = PyInt_AS_LONG(PyTuple_GET_ITEM(o, 2));
|
|
||||||
st->st_cur_type = PyInt_AS_LONG(PyTuple_GET_ITEM(o, 3));
|
|
||||||
if (PySequence_DelItem(st->st_stack, end) < 0)
|
if (PySequence_DelItem(st->st_stack, end) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return symtable_update_cur(st);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
symtable_enter_scope(struct symtable *st, char *name, int type,
|
symtable_enter_scope(struct symtable *st, char *name, int type,
|
||||||
int lineno)
|
int lineno)
|
||||||
{
|
{
|
||||||
PyObject *o;
|
PySymtableEntryObject *prev = NULL;
|
||||||
|
|
||||||
if (st->st_cur) {
|
if (st->st_cur) {
|
||||||
/* push current scope info on stack */
|
prev = st->st_cur;
|
||||||
o = make_scope_info(st->st_cur_id, st->st_cur_name,
|
if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) {
|
||||||
st->st_nested, st->st_cur_type,
|
Py_DECREF(st->st_cur);
|
||||||
st->st_cur_lineno);
|
|
||||||
if (o == NULL) {
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (PyList_Append(st->st_stack, o) < 0) {
|
|
||||||
Py_DECREF(o);
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (st->st_keep) {
|
|
||||||
if (PyDict_SetItem(st->st_scopes,
|
|
||||||
st->st_cur_id, o) < 0) {
|
|
||||||
Py_DECREF(o);
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_DECREF(o);
|
|
||||||
}
|
|
||||||
st->st_cur_name = PyString_FromString(name);
|
|
||||||
if (st->st_nested || st->st_cur_type == TYPE_FUNCTION)
|
|
||||||
st->st_nested = 1;
|
|
||||||
st->st_cur_lineno = lineno;
|
|
||||||
switch (type) {
|
|
||||||
case funcdef:
|
|
||||||
case lambdef:
|
|
||||||
st->st_cur_type = TYPE_FUNCTION;
|
|
||||||
break;
|
|
||||||
case classdef:
|
|
||||||
st->st_cur_type = TYPE_CLASS;
|
|
||||||
break;
|
|
||||||
case single_input:
|
|
||||||
case eval_input:
|
|
||||||
case file_input:
|
|
||||||
st->st_cur_type = TYPE_MODULE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "invalid symtable scope: %d\n", type);
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* update st_cur_id and parent's st_cur_children */
|
|
||||||
o = PyInt_FromLong(st->st_nscopes++);
|
|
||||||
if (o == NULL) {
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (st->st_cur_children) {
|
|
||||||
if (PyList_Append(st->st_cur_children, o) < 0) {
|
|
||||||
Py_DECREF(o);
|
|
||||||
st->st_errors++;
|
st->st_errors++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st->st_cur_id = o;
|
st->st_cur = (PySymtableEntryObject *)\
|
||||||
/* create st_cur_children list */
|
PySymtableEntry_New(st, name, type, lineno);
|
||||||
o = PyList_New(0);
|
if (strcmp(name, TOP) == 0)
|
||||||
if (o == NULL) {
|
st->st_global = st->st_cur->ste_symbols;
|
||||||
st->st_errors++;
|
if (prev)
|
||||||
return;
|
if (PyList_Append(prev->ste_children,
|
||||||
}
|
(PyObject *)st->st_cur) < 0)
|
||||||
if (PyDict_SetItem(st->st_children, st->st_cur_id, o) < 0) {
|
st->st_errors++;
|
||||||
Py_DECREF(o);
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Py_DECREF(o);
|
|
||||||
|
|
||||||
symtable_update_cur(st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
symtable_update_cur(struct symtable *st)
|
|
||||||
{
|
|
||||||
PyObject *s, *d, *l;
|
|
||||||
|
|
||||||
s = st->st_cur_id;
|
|
||||||
d = PyDict_GetItem(st->st_symbols, s);
|
|
||||||
if (d == NULL) {
|
|
||||||
if ((d = PyDict_New()) == NULL)
|
|
||||||
return -1;
|
|
||||||
if (PyObject_SetItem(st->st_symbols, s, d) < 0) {
|
|
||||||
Py_DECREF(d);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(d);
|
|
||||||
if (st->st_cur_type == TYPE_FUNCTION) {
|
|
||||||
if ((l = PyList_New(0)) == NULL)
|
|
||||||
return -1;
|
|
||||||
if (PyDict_SetItem(st->st_varnames, s, l) < 0) {
|
|
||||||
Py_DECREF(l);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
st->st_cur = d;
|
|
||||||
|
|
||||||
d = PyDict_GetItem(st->st_children, s);
|
|
||||||
if (d == NULL)
|
|
||||||
return -1;
|
|
||||||
st->st_cur_children = d;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -4498,7 +4341,7 @@ symtable_add_def(struct symtable *st, char *name, int flag)
|
||||||
name = buffer;
|
name = buffer;
|
||||||
if ((s = PyString_InternFromString(name)) == NULL)
|
if ((s = PyString_InternFromString(name)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return symtable_add_def_o(st, st->st_cur, s, flag);
|
return symtable_add_def_o(st, st->st_cur->ste_symbols, s, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must only be called with mangled names */
|
/* Must only be called with mangled names */
|
||||||
|
@ -4516,7 +4359,7 @@ symtable_add_def_o(struct symtable *st, PyObject *dict,
|
||||||
PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
|
PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
|
||||||
PyString_AsString(name));
|
PyString_AsString(name));
|
||||||
set_error_location(st->st_filename,
|
set_error_location(st->st_filename,
|
||||||
st->st_cur_lineno);
|
st->st_cur->ste_lineno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
val |= flag;
|
val |= flag;
|
||||||
|
@ -4530,11 +4373,7 @@ symtable_add_def_o(struct symtable *st, PyObject *dict,
|
||||||
Py_DECREF(o);
|
Py_DECREF(o);
|
||||||
|
|
||||||
if (flag & DEF_PARAM) {
|
if (flag & DEF_PARAM) {
|
||||||
PyObject *l = PyDict_GetItem(st->st_varnames,
|
if (PyList_Append(st->st_cur->ste_varnames, name) < 0)
|
||||||
st->st_cur_id);
|
|
||||||
if (l == NULL)
|
|
||||||
return -1;
|
|
||||||
if (PyList_Append(l, name) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (flag & DEF_GLOBAL) {
|
} else if (flag & DEF_GLOBAL) {
|
||||||
/* XXX need to update DEF_GLOBAL for other flags too;
|
/* XXX need to update DEF_GLOBAL for other flags too;
|
||||||
|
@ -4614,15 +4453,7 @@ symtable_node(struct symtable *st, node *n)
|
||||||
symtable_import(st, n);
|
symtable_import(st, n);
|
||||||
break;
|
break;
|
||||||
case exec_stmt: {
|
case exec_stmt: {
|
||||||
PyObject *zero = PyInt_FromLong(0);
|
st->st_cur->ste_optimized = 0;
|
||||||
if (zero == NULL)
|
|
||||||
st->st_errors++;
|
|
||||||
else {
|
|
||||||
if (PyDict_SetItemString(st->st_cur, NOOPT,
|
|
||||||
zero) < 0)
|
|
||||||
st->st_errors++;
|
|
||||||
Py_DECREF(zero);
|
|
||||||
}
|
|
||||||
symtable_node(st, CHILD(n, 1));
|
symtable_node(st, CHILD(n, 1));
|
||||||
if (NCH(n) > 2)
|
if (NCH(n) > 2)
|
||||||
symtable_node(st, CHILD(n, 3));
|
symtable_node(st, CHILD(n, 3));
|
||||||
|
@ -4852,23 +4683,7 @@ symtable_import(struct symtable *st, node *n)
|
||||||
|
|
||||||
if (STR(CHILD(n, 0))[0] == 'f') { /* from */
|
if (STR(CHILD(n, 0))[0] == 'f') { /* from */
|
||||||
if (TYPE(CHILD(n, 3)) == STAR) {
|
if (TYPE(CHILD(n, 3)) == STAR) {
|
||||||
PyObject *zero = PyInt_FromLong(0);
|
st->st_cur->ste_optimized = 0;
|
||||||
if (st->st_cur_type != TYPE_MODULE) {
|
|
||||||
PyErr_SetString(PyExc_SyntaxError,
|
|
||||||
ILLEGAL_IMPORT_STAR);
|
|
||||||
set_error_location(st->st_filename,
|
|
||||||
n->n_lineno);
|
|
||||||
st->st_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (zero == NULL)
|
|
||||||
st->st_errors++;
|
|
||||||
else {
|
|
||||||
if (PyDict_SetItemString(st->st_cur, NOOPT,
|
|
||||||
zero) < 0)
|
|
||||||
st->st_errors++;
|
|
||||||
Py_DECREF(zero);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 3; i < NCH(n); i += 2) {
|
for (i = 3; i < NCH(n); i += 2) {
|
||||||
node *c = CHILD(n, i);
|
node *c = CHILD(n, i);
|
||||||
|
|
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