diff options
Diffstat (limited to 'Parser/asdl_c.py')
-rwxr-xr-x | Parser/asdl_c.py | 110 |
1 files changed, 76 insertions, 34 deletions
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 7f613db..a9e6626 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -84,8 +84,16 @@ class EmitVisitor(asdl.VisitorBase): def __init__(self, file): self.file = file + self.identifiers = 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) + def emit(self, s, depth, reflow=True): # XXX reflow long lines? if reflow: @@ -485,12 +493,12 @@ class Obj2ModVisitor(PickleVisitor): def visitField(self, field, name, sum=None, prod=None, depth=0): ctype = get_c_type(field.type) - self.emit("if (PyObject_HasAttrString(obj, \"%s\")) {" % field.name, depth) + self.emit("if (_PyObject_HasAttrId(obj, &PyId_%s)) {" % field.name, depth) self.emit("int res;", depth+1) if field.seq: self.emit("Py_ssize_t len;", depth+1) self.emit("Py_ssize_t i;", depth+1) - self.emit("tmp = PyObject_GetAttrString(obj, \"%s\");" % field.name, depth+1) + self.emit("tmp = _PyObject_GetAttrId(obj, &PyId_%s);" % field.name, depth+1) self.emit("if (tmp == NULL) goto failed;", depth+1) if field.seq: self.emit("if (!PyList_Check(tmp)) {", depth+1) @@ -552,6 +560,8 @@ class PyTypesDeclareVisitor(PickleVisitor): self.emit("static PyTypeObject *%s_type;" % name, 0) self.emit("static PyObject* ast2obj_%s(void*);" % name, 0) if prod.fields: + for f in prod.fields: + self.emit_identifier(f.name) self.emit("static char *%s_fields[]={" % name,0) for f in prod.fields: self.emit('"%s",' % f.name, 1) @@ -560,6 +570,8 @@ class PyTypesDeclareVisitor(PickleVisitor): def visitSum(self, sum, name): self.emit("static PyTypeObject *%s_type;" % name, 0) if sum.attributes: + for a in sum.attributes: + self.emit_identifier(a.name) self.emit("static char *%s_attributes[] = {" % name, 0) for a in sum.attributes: self.emit('"%s",' % a.name, 1) @@ -579,6 +591,8 @@ class PyTypesDeclareVisitor(PickleVisitor): 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) self.emit("static char *%s_fields[]={" % cons.name, 0) for t in cons.fields: self.emit('"%s",' % t.name, 1) @@ -588,13 +602,39 @@ class PyTypesVisitor(PickleVisitor): def visitModule(self, mod): self.emit(""" +typedef struct { + PyObject_HEAD + PyObject *dict; +} AST_object; + +static void +ast_dealloc(AST_object *self) +{ + Py_CLEAR(self->dict); + Py_TYPE(self)->tp_free(self); +} + +static int +ast_traverse(AST_object *self, visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + return 0; +} + +static void +ast_clear(AST_object *self) +{ + Py_CLEAR(self->dict); +} + static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { + _Py_IDENTIFIER(_fields); Py_ssize_t i, numfields = 0; int res = -1; PyObject *key, *value, *fields; - fields = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "_fields"); + fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields); if (!fields) PyErr_Clear(); if (fields) { @@ -644,7 +684,8 @@ static PyObject * ast_type_reduce(PyObject *self, PyObject *unused) { PyObject *res; - PyObject *dict = PyObject_GetAttrString(self, "__dict__"); + _Py_IDENTIFIER(__dict__); + PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); if (dict == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); @@ -664,12 +705,17 @@ static PyMethodDef ast_type_methods[] = { {NULL} }; +static PyGetSetDef ast_type_getsets[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + static PyTypeObject AST_type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "_ast.AST", - sizeof(PyObject), + sizeof(AST_object), 0, - 0, /* tp_dealloc */ + (destructor)ast_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -684,26 +730,26 @@ static PyTypeObject AST_type = { PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (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 */ - 0, /* tp_getset */ + ast_type_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(AST_object, dict),/* tp_dictoffset */ (initproc)ast_type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - PyObject_Del, /* tp_free */ + PyObject_GC_Del, /* tp_free */ }; @@ -730,6 +776,7 @@ static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) { int i, result; + _Py_IDENTIFIER(_attributes); PyObject *s, *l = PyTuple_New(num_fields); if (!l) return 0; @@ -741,7 +788,7 @@ static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) } PyTuple_SET_ITEM(l, i, s); } - result = PyObject_SetAttrString((PyObject*)type, "_attributes", l) >= 0; + result = _PyObject_SetAttrId((PyObject*)type, &PyId__attributes, l) >= 0; Py_DECREF(l); return result; } @@ -750,7 +797,7 @@ static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*)) { - int i, n = asdl_seq_LEN(seq); + Py_ssize_t i, n = asdl_seq_LEN(seq); PyObject *result = PyList_New(n); PyObject *value; if (!result) @@ -775,6 +822,7 @@ static PyObject* ast2obj_object(void *o) } #define ast2obj_identifier ast2obj_object #define ast2obj_string ast2obj_object +#define ast2obj_bytes ast2obj_object static PyObject* ast2obj_int(long b) { @@ -812,6 +860,15 @@ static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena) return obj2ast_object(obj, out, arena); } +static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena) +{ + if (!PyBytes_CheckExact(obj)) { + PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes"); + return 1; + } + return obj2ast_object(obj, out, arena); +} + static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) { int i; @@ -910,10 +967,6 @@ class ASTModuleVisitor(PickleVisitor): self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;', 1) self.emit('if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)', 1) self.emit("return NULL;", 2) - # Value of version: "$Revision$" - self.emit('if (PyModule_AddStringConstant(m, "__version__", "%s") < 0)' - % mod.version, 1) - self.emit("return NULL;", 2) for dfn in mod.dfns: self.visit(dfn) self.emit("return m;", 1) @@ -997,7 +1050,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_SetAttrString(result, "%s", value) < 0)' % a.name, 1) + self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1) self.emit('goto failed;', 2) self.emit('Py_DECREF(value);', 1) self.func_end() @@ -1043,7 +1096,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_SetAttrString(result, "%s", value) == -1)' % field.name, 0) + emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) == -1)' % field.name, 0) emit("goto failed;", 1) emit("Py_DECREF(value);", 0) @@ -1066,7 +1119,7 @@ class ObjVisitor(PickleVisitor): # While the sequence elements are stored as void*, # ast2obj_cmpop expects an enum self.emit("{", depth) - self.emit("int i, n = asdl_seq_LEN(%s);" % value, depth+1) + self.emit("Py_ssize_t i, n = asdl_seq_LEN(%s);" % value, depth+1) self.emit("value = PyList_New(n);", depth+1) self.emit("if (!value) goto failed;", depth+1) self.emit("for(i = 0; i < n; i++)", depth+1) @@ -1134,24 +1187,12 @@ class ChainOfVisitors: common_msg = "/* File automatically generated by %s. */\n\n" -c_file_msg = """ -/* - __version__ %s. - - This module must be committed separately after each AST grammar change; - The __version__ number is set to the revision number of the commit - containing the grammar change. -*/ - -""" - def main(srcfile): argv0 = sys.argv[0] components = argv0.split(os.sep) argv0 = os.sep.join(components[-2:]) auto_gen_msg = common_msg % argv0 mod = asdl.parse(srcfile) - mod.version = "82163" if not asdl.check(mod): sys.exit(1) if INC_DIR: @@ -1173,7 +1214,8 @@ def main(srcfile): p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c") f = open(p, "w") f.write(auto_gen_msg) - f.write(c_file_msg % mod.version) + f.write('#include <stddef.h>\n') + f.write('\n') f.write('#include "Python.h"\n') f.write('#include "%s-ast.h"\n' % mod.name) f.write('\n') |