You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.4 KiB
180 lines
4.4 KiB
#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 */ |
|
};
|
|
|