mirror of
https://github.com/python/cpython.git
synced 2024-11-24 10:24:35 +08:00
4d508adae3
The compiler was reseting the list comprehension tmpname counter for each function, but the symtable was using the same counter for the entire module. Repair by move tmpname into the symtable entry. Bugfix candidate.
181 lines
4.4 KiB
C
181 lines
4.4 KiB
C
#include "Python.h"
|
|
#include "compile.h"
|
|
#include "symtable.h"
|
|
#include "graminit.h"
|
|
#include "structmember.h"
|
|
|
|
/* The compiler uses this function to load a PySymtableEntry object
|
|
for a code block. Each block is loaded twice, once during the
|
|
symbol table pass and once during the code gen pass. Entries
|
|
created during the first pass are cached for the second pass, using
|
|
the st_symbols dictionary.
|
|
|
|
The cache is keyed by st_nscopes. Each code block node in a
|
|
module's parse tree can be assigned a unique id based on the order
|
|
in which the nodes are visited by the compiler. This strategy
|
|
works so long as the symbol table and codegen passes visit the same
|
|
nodes in the same order.
|
|
*/
|
|
|
|
|
|
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) {
|
|
Py_DECREF(k);
|
|
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_opt_lineno = 0;
|
|
ste->ste_tmpname = 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;
|
|
ste->ste_generator = 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];
|
|
|
|
PyOS_snprintf(buf, sizeof(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 PyMemberDef 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}
|
|
};
|
|
|
|
PyTypeObject PySymtableEntry_Type = {
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
|
0,
|
|
"symtable entry",
|
|
sizeof(PySymtableEntryObject),
|
|
0,
|
|
(destructor)ste_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* 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 */
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
0, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
0, /* tp_methods */
|
|
ste_memberlist, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0, /* tp_alloc */
|
|
0, /* tp_new */
|
|
};
|