mirror of https://github.com/python/cpython
bpo-38113: Update the Python-ast.c generator to PEP384 (gh-15957)
Summary: This mostly migrates Python-ast.c to PEP384 and removes all statics from the whole file. This modifies the generator itself that generates the Python-ast.c. It leaves in the usage of _PyObject_LookupAttr even though it's not fully PEP384 compatible (this could always be shimmed in by anyone who needs it).
This commit is contained in:
parent
8d120f75fb
commit
ac46eb4ad6
|
@ -0,0 +1 @@
|
|||
ast module updated to PEP-384 and all statics removed
|
300
Parser/asdl_c.py
300
Parser/asdl_c.py
|
@ -78,14 +78,18 @@ class EmitVisitor(asdl.VisitorBase):
|
|||
def __init__(self, file):
|
||||
self.file = file
|
||||
self.identifiers = set()
|
||||
self.singletons = set()
|
||||
self.types = set()
|
||||
super(EmitVisitor, self).__init__()
|
||||
|
||||
def emit_identifier(self, name):
|
||||
name = str(name)
|
||||
if name in self.identifiers:
|
||||
return
|
||||
self.emit("_Py_IDENTIFIER(%s);" % name, 0)
|
||||
self.identifiers.add(name)
|
||||
self.identifiers.add(str(name))
|
||||
|
||||
def emit_singleton(self, name):
|
||||
self.singletons.add(str(name))
|
||||
|
||||
def emit_type(self, name):
|
||||
self.types.add(str(name))
|
||||
|
||||
def emit(self, s, depth, reflow=True):
|
||||
# XXX reflow long lines?
|
||||
|
@ -392,7 +396,7 @@ class Obj2ModVisitor(PickleVisitor):
|
|||
self.funcHeader(name)
|
||||
for t in sum.types:
|
||||
line = ("isinstance = PyObject_IsInstance(obj, "
|
||||
"(PyObject *)%s_type);")
|
||||
"astmodulestate_global->%s_type);")
|
||||
self.emit(line % (t.name,), 1)
|
||||
self.emit("if (isinstance == -1) {", 1)
|
||||
self.emit("return 1;", 2)
|
||||
|
@ -409,6 +413,7 @@ class Obj2ModVisitor(PickleVisitor):
|
|||
def complexSum(self, sum, name):
|
||||
self.funcHeader(name)
|
||||
self.emit("PyObject *tmp = NULL;", 1)
|
||||
self.emit("PyObject *tp;", 1)
|
||||
for a in sum.attributes:
|
||||
self.visitAttributeDeclaration(a, name, sum=sum)
|
||||
self.emit("", 0)
|
||||
|
@ -420,8 +425,8 @@ class Obj2ModVisitor(PickleVisitor):
|
|||
for a in sum.attributes:
|
||||
self.visitField(a, name, sum=sum, depth=1)
|
||||
for t in sum.types:
|
||||
line = "isinstance = PyObject_IsInstance(obj, (PyObject*)%s_type);"
|
||||
self.emit(line % (t.name,), 1)
|
||||
self.emit("tp = astmodulestate_global->%s_type;" % (t.name,), 1)
|
||||
self.emit("isinstance = PyObject_IsInstance(obj, tp);", 1)
|
||||
self.emit("if (isinstance == -1) {", 1)
|
||||
self.emit("return 1;", 2)
|
||||
self.emit("}", 1)
|
||||
|
@ -497,7 +502,8 @@ class Obj2ModVisitor(PickleVisitor):
|
|||
|
||||
def visitField(self, field, name, sum=None, prod=None, depth=0):
|
||||
ctype = get_c_type(field.type)
|
||||
self.emit("if (_PyObject_LookupAttrId(obj, &PyId_%s, &tmp) < 0) {" % field.name, depth)
|
||||
line = "if (_PyObject_LookupAttr(obj, astmodulestate_global->%s, &tmp) < 0) {"
|
||||
self.emit(line % field.name, depth)
|
||||
self.emit("return 1;", depth+1)
|
||||
self.emit("}", depth)
|
||||
if not field.opt:
|
||||
|
@ -524,7 +530,7 @@ class Obj2ModVisitor(PickleVisitor):
|
|||
self.emit("Py_ssize_t i;", depth+1)
|
||||
self.emit("if (!PyList_Check(tmp)) {", depth+1)
|
||||
self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must "
|
||||
"be a list, not a %%.200s\", tmp->ob_type->tp_name);" %
|
||||
"be a list, not a %%.200s\", _PyType_Name(Py_TYPE(tmp)));" %
|
||||
(name, field.name),
|
||||
depth+2, reflow=False)
|
||||
self.emit("goto failed;", depth+2)
|
||||
|
@ -574,7 +580,7 @@ class MarshalPrototypeVisitor(PickleVisitor):
|
|||
class PyTypesDeclareVisitor(PickleVisitor):
|
||||
|
||||
def visitProduct(self, prod, name):
|
||||
self.emit("static PyTypeObject *%s_type;" % name, 0)
|
||||
self.emit_type("%s_type" % name)
|
||||
self.emit("static PyObject* ast2obj_%s(void*);" % name, 0)
|
||||
if prod.attributes:
|
||||
for a in prod.attributes:
|
||||
|
@ -592,7 +598,7 @@ class PyTypesDeclareVisitor(PickleVisitor):
|
|||
self.emit("};", 0)
|
||||
|
||||
def visitSum(self, sum, name):
|
||||
self.emit("static PyTypeObject *%s_type;" % name, 0)
|
||||
self.emit_type("%s_type" % name)
|
||||
if sum.attributes:
|
||||
for a in sum.attributes:
|
||||
self.emit_identifier(a.name)
|
||||
|
@ -603,17 +609,13 @@ class PyTypesDeclareVisitor(PickleVisitor):
|
|||
ptype = "void*"
|
||||
if is_simple(sum):
|
||||
ptype = get_c_type(name)
|
||||
tnames = []
|
||||
for t in sum.types:
|
||||
tnames.append(str(t.name)+"_singleton")
|
||||
tnames = ", *".join(tnames)
|
||||
self.emit("static PyObject *%s;" % tnames, 0)
|
||||
self.emit_singleton("%s_singleton" % t.name)
|
||||
self.emit("static PyObject* ast2obj_%s(%s);" % (name, ptype), 0)
|
||||
for t in sum.types:
|
||||
self.visitConstructor(t, name)
|
||||
|
||||
def visitConstructor(self, cons, name):
|
||||
self.emit("static PyTypeObject *%s_type;" % cons.name, 0)
|
||||
if cons.fields:
|
||||
for t in cons.fields:
|
||||
self.emit_identifier(t.name)
|
||||
|
@ -626,8 +628,6 @@ class PyTypesVisitor(PickleVisitor):
|
|||
|
||||
def visitModule(self, mod):
|
||||
self.emit("""
|
||||
_Py_IDENTIFIER(_fields);
|
||||
_Py_IDENTIFIER(_attributes);
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
@ -663,7 +663,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
|
|||
Py_ssize_t i, numfields = 0;
|
||||
int res = -1;
|
||||
PyObject *key, *value, *fields;
|
||||
if (_PyObject_LookupAttrId((PyObject*)Py_TYPE(self), &PyId__fields, &fields) < 0) {
|
||||
if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), astmodulestate_global->_fields, &fields) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (fields) {
|
||||
|
@ -676,7 +676,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
|
|||
if (numfields < PyTuple_GET_SIZE(args)) {
|
||||
PyErr_Format(PyExc_TypeError, "%.400s constructor takes at most "
|
||||
"%zd positional argument%s",
|
||||
Py_TYPE(self)->tp_name,
|
||||
_PyType_Name(Py_TYPE(self)),
|
||||
numfields, numfields == 1 ? "" : "s");
|
||||
res = -1;
|
||||
goto cleanup;
|
||||
|
@ -710,9 +710,8 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
|
|||
static PyObject *
|
||||
ast_type_reduce(PyObject *self, PyObject *unused)
|
||||
{
|
||||
_Py_IDENTIFIER(__dict__);
|
||||
PyObject *dict;
|
||||
if (_PyObject_LookupAttrId(self, &PyId___dict__, &dict) < 0) {
|
||||
if (_PyObject_LookupAttr(self, astmodulestate_global->__dict__, &dict) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (dict) {
|
||||
|
@ -731,54 +730,33 @@ static PyGetSetDef ast_type_getsets[] = {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
static PyTypeObject AST_type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
static PyType_Slot AST_type_slots[] = {
|
||||
{Py_tp_dealloc, ast_dealloc},
|
||||
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||
{Py_tp_setattro, PyObject_GenericSetAttr},
|
||||
{Py_tp_traverse, ast_traverse},
|
||||
{Py_tp_clear, ast_clear},
|
||||
{Py_tp_methods, ast_type_methods},
|
||||
{Py_tp_getset, ast_type_getsets},
|
||||
{Py_tp_init, ast_type_init},
|
||||
{Py_tp_alloc, PyType_GenericAlloc},
|
||||
{Py_tp_new, PyType_GenericNew},
|
||||
{Py_tp_free, PyType_GenericNew},
|
||||
{Py_tp_free, PyObject_GC_Del},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static PyType_Spec AST_type_spec = {
|
||||
"_ast.AST",
|
||||
sizeof(AST_object),
|
||||
0,
|
||||
(destructor)ast_dealloc, /* tp_dealloc */
|
||||
0, /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
0, /* 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 */
|
||||
PyObject_GenericSetAttr, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
(traverseproc)ast_traverse, /* tp_traverse */
|
||||
(inquiry)ast_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
ast_type_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
ast_type_getsets, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
offsetof(AST_object, dict),/* tp_dictoffset */
|
||||
(initproc)ast_type_init, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
|
||||
AST_type_slots
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject *
|
||||
make_type(const char *type, PyTypeObject *base, const char * const *fields, int num_fields)
|
||||
static PyObject *
|
||||
make_type(const char *type, PyObject* base, const char* const* fields, int num_fields)
|
||||
{
|
||||
_Py_IDENTIFIER(__module__);
|
||||
_Py_IDENTIFIER(_ast);
|
||||
PyObject *fnames, *result;
|
||||
int i;
|
||||
fnames = PyTuple_New(num_fields);
|
||||
|
@ -793,15 +771,15 @@ make_type(const char *type, PyTypeObject *base, const char * const *fields, int
|
|||
}
|
||||
result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){OOOO}",
|
||||
type, base,
|
||||
_PyUnicode_FromId(&PyId__fields), fnames,
|
||||
_PyUnicode_FromId(&PyId___module__),
|
||||
_PyUnicode_FromId(&PyId__ast));
|
||||
astmodulestate_global->_fields, fnames,
|
||||
astmodulestate_global->__module__,
|
||||
astmodulestate_global->_ast);
|
||||
Py_DECREF(fnames);
|
||||
return (PyTypeObject*)result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
add_attributes(PyTypeObject *type, const char * const *attrs, int num_fields)
|
||||
add_attributes(PyObject *type, const char * const *attrs, int num_fields)
|
||||
{
|
||||
int i, result;
|
||||
PyObject *s, *l = PyTuple_New(num_fields);
|
||||
|
@ -815,7 +793,7 @@ add_attributes(PyTypeObject *type, const char * const *attrs, int num_fields)
|
|||
}
|
||||
PyTuple_SET_ITEM(l, i, s);
|
||||
}
|
||||
result = _PyObject_SetAttrId((PyObject*)type, &PyId__attributes, l) >= 0;
|
||||
result = PyObject_SetAttr(type, astmodulestate_global->_attributes, l) >= 0;
|
||||
Py_DECREF(l);
|
||||
return result;
|
||||
}
|
||||
|
@ -921,14 +899,11 @@ static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
|
|||
|
||||
static int add_ast_fields(void)
|
||||
{
|
||||
PyObject *empty_tuple, *d;
|
||||
if (PyType_Ready(&AST_type) < 0)
|
||||
return -1;
|
||||
d = AST_type.tp_dict;
|
||||
PyObject *empty_tuple;
|
||||
empty_tuple = PyTuple_New(0);
|
||||
if (!empty_tuple ||
|
||||
_PyDict_SetItemId(d, &PyId__fields, empty_tuple) < 0 ||
|
||||
_PyDict_SetItemId(d, &PyId__attributes, empty_tuple) < 0) {
|
||||
PyObject_SetAttrString(astmodulestate_global->AST_type, "_fields", empty_tuple) < 0 ||
|
||||
PyObject_SetAttrString(astmodulestate_global->AST_type, "_attributes", empty_tuple) < 0) {
|
||||
Py_XDECREF(empty_tuple);
|
||||
return -1;
|
||||
}
|
||||
|
@ -940,12 +915,22 @@ static int add_ast_fields(void)
|
|||
|
||||
self.emit("static int init_types(void)",0)
|
||||
self.emit("{", 0)
|
||||
self.emit("static int initialized;", 1)
|
||||
self.emit("if (initialized) return 1;", 1)
|
||||
self.emit("PyObject *m;", 1)
|
||||
self.emit("if (PyState_FindModule(&_astmodule) == NULL) {", 1)
|
||||
self.emit("m = PyModule_Create(&_astmodule);", 2)
|
||||
self.emit("if (!m) return 0;", 2)
|
||||
self.emit("PyState_AddModule(m, &_astmodule);", 2)
|
||||
self.emit("}", 1)
|
||||
self.emit("astmodulestate *state = astmodulestate_global;", 1)
|
||||
self.emit("if (state->initialized) return 1;", 1)
|
||||
self.emit("if (init_identifiers() < 0) return 0;", 1)
|
||||
self.emit("state->AST_type = PyType_FromSpec(&AST_type_spec);", 1)
|
||||
self.emit("if (!state->AST_type) return 0;", 1)
|
||||
self.emit("((PyTypeObject*)state->AST_type)->tp_dictoffset = offsetof(AST_object, dict);", 1)
|
||||
self.emit("if (add_ast_fields() < 0) return 0;", 1)
|
||||
for dfn in mod.dfns:
|
||||
self.visit(dfn)
|
||||
self.emit("initialized = 1;", 1)
|
||||
self.emit("state->initialized = 1;", 1)
|
||||
self.emit("return 1;", 1);
|
||||
self.emit("}", 0)
|
||||
|
||||
|
@ -954,24 +939,27 @@ static int add_ast_fields(void)
|
|||
fields = name+"_fields"
|
||||
else:
|
||||
fields = "NULL"
|
||||
self.emit('%s_type = make_type("%s", &AST_type, %s, %d);' %
|
||||
self.emit('state->%s_type = make_type("%s", state->AST_type, %s, %d);' %
|
||||
(name, name, fields, len(prod.fields)), 1)
|
||||
self.emit("if (!%s_type) return 0;" % name, 1)
|
||||
self.emit("if (!state->%s_type) return 0;" % name, 1)
|
||||
self.emit_type("AST_type")
|
||||
self.emit_type("%s_type" % name)
|
||||
if prod.attributes:
|
||||
self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" %
|
||||
self.emit("if (!add_attributes(state->%s_type, %s_attributes, %d)) return 0;" %
|
||||
(name, name, len(prod.attributes)), 1)
|
||||
else:
|
||||
self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1)
|
||||
self.emit("if (!add_attributes(state->%s_type, NULL, 0)) return 0;" % name, 1)
|
||||
|
||||
def visitSum(self, sum, name):
|
||||
self.emit('%s_type = make_type("%s", &AST_type, NULL, 0);' %
|
||||
self.emit('state->%s_type = make_type("%s", state->AST_type, NULL, 0);' %
|
||||
(name, name), 1)
|
||||
self.emit("if (!%s_type) return 0;" % name, 1)
|
||||
self.emit_type("%s_type" % name)
|
||||
self.emit("if (!state->%s_type) return 0;" % name, 1)
|
||||
if sum.attributes:
|
||||
self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" %
|
||||
self.emit("if (!add_attributes(state->%s_type, %s_attributes, %d)) return 0;" %
|
||||
(name, name, len(sum.attributes)), 1)
|
||||
else:
|
||||
self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1)
|
||||
self.emit("if (!add_attributes(state->%s_type, NULL, 0)) return 0;" % name, 1)
|
||||
simple = is_simple(sum)
|
||||
for t in sum.types:
|
||||
self.visitConstructor(t, name, simple)
|
||||
|
@ -981,30 +969,29 @@ static int add_ast_fields(void)
|
|||
fields = cons.name+"_fields"
|
||||
else:
|
||||
fields = "NULL"
|
||||
self.emit('%s_type = make_type("%s", %s_type, %s, %d);' %
|
||||
self.emit('state->%s_type = make_type("%s", state->%s_type, %s, %d);' %
|
||||
(cons.name, cons.name, name, fields, len(cons.fields)), 1)
|
||||
self.emit("if (!%s_type) return 0;" % cons.name, 1)
|
||||
self.emit("if (!state->%s_type) return 0;" % cons.name, 1)
|
||||
self.emit_type("%s_type" % cons.name)
|
||||
if simple:
|
||||
self.emit("%s_singleton = PyType_GenericNew(%s_type, NULL, NULL);" %
|
||||
self.emit("state->%s_singleton = PyType_GenericNew((PyTypeObject *)"
|
||||
"state->%s_type, NULL, NULL);" %
|
||||
(cons.name, cons.name), 1)
|
||||
self.emit("if (!%s_singleton) return 0;" % cons.name, 1)
|
||||
self.emit("if (!state->%s_singleton) return 0;" % cons.name, 1)
|
||||
|
||||
|
||||
class ASTModuleVisitor(PickleVisitor):
|
||||
|
||||
def visitModule(self, mod):
|
||||
self.emit("static struct PyModuleDef _astmodule = {", 0)
|
||||
self.emit(' PyModuleDef_HEAD_INIT, "_ast"', 0)
|
||||
self.emit("};", 0)
|
||||
self.emit("PyMODINIT_FUNC", 0)
|
||||
self.emit("PyInit__ast(void)", 0)
|
||||
self.emit("{", 0)
|
||||
self.emit("PyObject *m, *d;", 1)
|
||||
self.emit("PyObject *m;", 1)
|
||||
self.emit("if (!init_types()) return NULL;", 1)
|
||||
self.emit('m = PyModule_Create(&_astmodule);', 1)
|
||||
self.emit('m = PyState_FindModule(&_astmodule);', 1)
|
||||
self.emit("if (!m) return NULL;", 1)
|
||||
self.emit("d = PyModule_GetDict(m);", 1)
|
||||
self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;', 1)
|
||||
self.emit('Py_INCREF(astmodulestate(m)->AST_type);', 1)
|
||||
self.emit('if (PyModule_AddObject(m, "AST", astmodulestate_global->AST_type) < 0) return NULL;', 1)
|
||||
self.emit('if (PyModule_AddIntMacro(m, PyCF_ALLOW_TOP_LEVEL_AWAIT) < 0)', 1)
|
||||
self.emit("return NULL;", 2)
|
||||
self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)', 1)
|
||||
|
@ -1028,7 +1015,9 @@ class ASTModuleVisitor(PickleVisitor):
|
|||
self.addObj(cons.name)
|
||||
|
||||
def addObj(self, name):
|
||||
self.emit('if (PyDict_SetItemString(d, "%s", (PyObject*)%s_type) < 0) return NULL;' % (name, name), 1)
|
||||
self.emit("if (PyModule_AddObject(m, \"%s\", "
|
||||
"astmodulestate_global->%s_type) < 0) return NULL;" % (name, name), 1)
|
||||
self.emit("Py_INCREF(astmodulestate(m)->%s_type);" % name, 1)
|
||||
|
||||
|
||||
_SPECIALIZED_SEQUENCES = ('stmt', 'expr')
|
||||
|
@ -1066,6 +1055,7 @@ class ObjVisitor(PickleVisitor):
|
|||
self.emit("{", 0)
|
||||
self.emit("%s o = (%s)_o;" % (ctype, ctype), 1)
|
||||
self.emit("PyObject *result = NULL, *value = NULL;", 1)
|
||||
self.emit("PyTypeObject *tp;", 1)
|
||||
self.emit('if (!o) {', 1)
|
||||
self.emit("Py_RETURN_NONE;", 2)
|
||||
self.emit("}", 1)
|
||||
|
@ -1093,7 +1083,7 @@ class ObjVisitor(PickleVisitor):
|
|||
for a in sum.attributes:
|
||||
self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1)
|
||||
self.emit("if (!value) goto failed;", 1)
|
||||
self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1)
|
||||
self.emit('if (PyObject_SetAttr(result, astmodulestate_global->%s, value) < 0)' % a.name, 1)
|
||||
self.emit('goto failed;', 2)
|
||||
self.emit('Py_DECREF(value);', 1)
|
||||
self.func_end()
|
||||
|
@ -1104,8 +1094,8 @@ class ObjVisitor(PickleVisitor):
|
|||
self.emit("switch(o) {", 1)
|
||||
for t in sum.types:
|
||||
self.emit("case %s:" % t.name, 2)
|
||||
self.emit("Py_INCREF(%s_singleton);" % t.name, 3)
|
||||
self.emit("return %s_singleton;" % t.name, 3)
|
||||
self.emit("Py_INCREF(astmodulestate_global->%s_singleton);" % t.name, 3)
|
||||
self.emit("return astmodulestate_global->%s_singleton;" % t.name, 3)
|
||||
self.emit("default:", 2)
|
||||
self.emit('/* should never happen, but just in case ... */', 3)
|
||||
code = "PyErr_Format(PyExc_SystemError, \"unknown %s found\");" % name
|
||||
|
@ -1116,21 +1106,23 @@ class ObjVisitor(PickleVisitor):
|
|||
|
||||
def visitProduct(self, prod, name):
|
||||
self.func_begin(name)
|
||||
self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % name, 1);
|
||||
self.emit("tp = (PyTypeObject *)astmodulestate_global->%s_type;" % name, 1)
|
||||
self.emit("result = PyType_GenericNew(tp, NULL, NULL);", 1);
|
||||
self.emit("if (!result) return NULL;", 1)
|
||||
for field in prod.fields:
|
||||
self.visitField(field, name, 1, True)
|
||||
for a in prod.attributes:
|
||||
self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1)
|
||||
self.emit("if (!value) goto failed;", 1)
|
||||
self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1)
|
||||
self.emit("if (PyObject_SetAttr(result, astmodulestate_global->%s, value) < 0)" % a.name, 1)
|
||||
self.emit('goto failed;', 2)
|
||||
self.emit('Py_DECREF(value);', 1)
|
||||
self.func_end()
|
||||
|
||||
def visitConstructor(self, cons, enum, name):
|
||||
self.emit("case %s_kind:" % cons.name, 1)
|
||||
self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % cons.name, 2);
|
||||
self.emit("tp = (PyTypeObject *)astmodulestate_global->%s_type;" % cons.name, 2)
|
||||
self.emit("result = PyType_GenericNew(tp, NULL, NULL);", 2);
|
||||
self.emit("if (!result) goto failed;", 2)
|
||||
for f in cons.fields:
|
||||
self.visitField(f, cons.name, 2, False)
|
||||
|
@ -1145,7 +1137,7 @@ class ObjVisitor(PickleVisitor):
|
|||
value = "o->v.%s.%s" % (name, field.name)
|
||||
self.set(field, value, depth)
|
||||
emit("if (!value) goto failed;", 0)
|
||||
emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) == -1)' % field.name, 0)
|
||||
emit("if (PyObject_SetAttr(result, astmodulestate_global->%s, value) == -1)" % field.name, 0)
|
||||
emit("goto failed;", 1)
|
||||
emit("Py_DECREF(value);", 0)
|
||||
|
||||
|
@ -1205,9 +1197,9 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
req_type[0] = (PyObject*)Module_type;
|
||||
req_type[1] = (PyObject*)Expression_type;
|
||||
req_type[2] = (PyObject*)Interactive_type;
|
||||
req_type[0] = astmodulestate_global->Module_type;
|
||||
req_type[1] = astmodulestate_global->Expression_type;
|
||||
req_type[2] = astmodulestate_global->Interactive_type;
|
||||
|
||||
assert(0 <= mode && mode <= 2);
|
||||
|
||||
|
@ -1219,7 +1211,7 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode)
|
|||
return NULL;
|
||||
if (!isinstance) {
|
||||
PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
|
||||
req_name[mode], Py_TYPE(ast)->tp_name);
|
||||
req_name[mode], _PyType_Name(Py_TYPE(ast)));
|
||||
return NULL;
|
||||
}
|
||||
if (obj2ast_mod(ast, &res, arena) != 0)
|
||||
|
@ -1232,7 +1224,7 @@ int PyAST_Check(PyObject* obj)
|
|||
{
|
||||
if (!init_types())
|
||||
return -1;
|
||||
return PyObject_IsInstance(obj, (PyObject*)&AST_type);
|
||||
return PyObject_IsInstance(obj, astmodulestate_global->AST_type);
|
||||
}
|
||||
"""
|
||||
|
||||
|
@ -1245,6 +1237,86 @@ class ChainOfVisitors:
|
|||
v.visit(object)
|
||||
v.emit("", 0)
|
||||
|
||||
|
||||
def generate_module_def(f, mod):
|
||||
# Gather all the data needed for ModuleSpec
|
||||
visitor_list = set()
|
||||
with open(os.devnull, "w") as devnull:
|
||||
visitor = PyTypesDeclareVisitor(devnull)
|
||||
visitor.visit(mod)
|
||||
visitor_list.add(visitor)
|
||||
visitor = PyTypesVisitor(devnull)
|
||||
visitor.visit(mod)
|
||||
visitor_list.add(visitor)
|
||||
|
||||
state_strings = set(["__dict__", "_attributes", "_fields", "__module__", "_ast"])
|
||||
module_state = set(["__dict__", "_attributes", "_fields", "__module__", "_ast"])
|
||||
for visitor in visitor_list:
|
||||
for identifier in visitor.identifiers:
|
||||
module_state.add(identifier)
|
||||
state_strings.add(identifier)
|
||||
for singleton in visitor.singletons:
|
||||
module_state.add(singleton)
|
||||
for tp in visitor.types:
|
||||
module_state.add(tp)
|
||||
state_strings = sorted(state_strings)
|
||||
module_state = sorted(module_state)
|
||||
f.write('typedef struct {\n')
|
||||
f.write(' int initialized;\n')
|
||||
for s in module_state:
|
||||
f.write(' PyObject *' + s + ';\n')
|
||||
f.write('} astmodulestate;\n\n')
|
||||
f.write("""
|
||||
#define astmodulestate(o) ((astmodulestate *)PyModule_GetState(o))
|
||||
|
||||
static int astmodule_clear(PyObject *module)
|
||||
{
|
||||
""")
|
||||
for s in module_state:
|
||||
f.write(" Py_CLEAR(astmodulestate(module)->" + s + ');\n')
|
||||
f.write("""
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int astmodule_traverse(PyObject *module, visitproc visit, void* arg)
|
||||
{
|
||||
""")
|
||||
for s in module_state:
|
||||
f.write(" Py_VISIT(astmodulestate(module)->" + s + ');\n')
|
||||
f.write("""
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void astmodule_free(void* module) {
|
||||
astmodule_clear((PyObject*)module);
|
||||
}
|
||||
|
||||
static struct PyModuleDef _astmodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_ast",
|
||||
NULL,
|
||||
sizeof(astmodulestate),
|
||||
NULL,
|
||||
NULL,
|
||||
astmodule_traverse,
|
||||
astmodule_clear,
|
||||
astmodule_free,
|
||||
};
|
||||
|
||||
#define astmodulestate_global ((astmodulestate *)PyModule_GetState(PyState_FindModule(&_astmodule)))
|
||||
|
||||
""")
|
||||
f.write('static int init_identifiers(void)\n')
|
||||
f.write('{\n')
|
||||
f.write(' astmodulestate *state = astmodulestate_global;\n')
|
||||
for identifier in state_strings:
|
||||
f.write(' if ((state->' + identifier)
|
||||
f.write(' = PyUnicode_InternFromString("')
|
||||
f.write(identifier + '")) == NULL) return 0;\n')
|
||||
f.write(' return 1;\n')
|
||||
f.write('};\n\n')
|
||||
|
||||
|
||||
common_msg = "/* File automatically generated by %s. */\n\n"
|
||||
|
||||
def main(srcfile, dump_module=False):
|
||||
|
@ -1295,7 +1367,9 @@ def main(srcfile, dump_module=False):
|
|||
f.write('#include "Python.h"\n')
|
||||
f.write('#include "%s-ast.h"\n' % mod.name)
|
||||
f.write('\n')
|
||||
f.write("static PyTypeObject AST_type;\n")
|
||||
|
||||
generate_module_def(f, mod)
|
||||
|
||||
v = ChainOfVisitors(
|
||||
PyTypesDeclareVisitor(f),
|
||||
PyTypesVisitor(f),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue