diff options
author | Dino Viehland <dinoviehland@fb.com> | 2019-09-11 17:16:34 (GMT) |
---|---|---|
committer | Eric Snow <ericsnowcurrently@gmail.com> | 2019-09-11 17:16:34 (GMT) |
commit | ac46eb4ad6662cf6d771b20d8963658b2186c48c (patch) | |
tree | da2d53570c816bf85cd66013961a0a5fde44709d /Parser | |
parent | 8d120f75fb8c8731464b5f7531d74cdbb897d924 (diff) | |
download | cpython-ac46eb4ad6662cf6d771b20d8963658b2186c48c.zip cpython-ac46eb4ad6662cf6d771b20d8963658b2186c48c.tar.gz cpython-ac46eb4ad6662cf6d771b20d8963658b2186c48c.tar.bz2 |
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).
Diffstat (limited to 'Parser')
-rwxr-xr-x | Parser/asdl_c.py | 300 |
1 files changed, 187 insertions, 113 deletions
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 9b18bb4..85d96a3 100755 --- a/Parser/asdl_c.py +++ b/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), |