diff options
Diffstat (limited to 'Parser/asdl_c.py')
-rwxr-xr-x | Parser/asdl_c.py | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 4b84e0f..d6086e6 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -209,6 +209,11 @@ class StructVisitor(EmitVisitor): self.emit("struct _%(name)s {" % locals(), depth) for f in product.fields: self.visit(f, depth + 1) + for field in product.attributes: + # rudimentary attribute handling + type = str(field.type) + assert type in asdl.builtin_types, type + self.emit("%s %s;" % (type, field.name), depth + 1); self.emit("};", depth) self.emit("", depth) @@ -493,7 +498,11 @@ class Obj2ModVisitor(PickleVisitor): def visitField(self, field, name, sum=None, prod=None, depth=0): ctype = get_c_type(field.type) - self.emit("if (_PyObject_HasAttrId(obj, &PyId_%s)) {" % field.name, depth) + if field.opt: + check = "exists_not_none(obj, &PyId_%s)" % (field.name,) + else: + check = "_PyObject_HasAttrId(obj, &PyId_%s)" % (field.name,) + self.emit("if (%s) {" % (check,), depth, reflow=False) self.emit("int res;", depth+1) if field.seq: self.emit("Py_ssize_t len;", depth+1) @@ -510,9 +519,9 @@ class Obj2ModVisitor(PickleVisitor): self.emit("}", depth+1) self.emit("len = PyList_GET_SIZE(tmp);", depth+1) if self.isSimpleType(field): - self.emit("%s = asdl_int_seq_new(len, arena);" % field.name, depth+1) + self.emit("%s = _Py_asdl_int_seq_new(len, arena);" % field.name, depth+1) else: - self.emit("%s = asdl_seq_new(len, arena);" % field.name, depth+1) + self.emit("%s = _Py_asdl_seq_new(len, arena);" % field.name, depth+1) self.emit("if (%s == NULL) goto failed;" % field.name, depth+1) self.emit("for (i = 0; i < len; i++) {", depth+1) self.emit("%s value;" % ctype, depth+2) @@ -558,6 +567,13 @@ class PyTypesDeclareVisitor(PickleVisitor): def visitProduct(self, prod, name): self.emit("static PyTypeObject *%s_type;" % name, 0) self.emit("static PyObject* ast2obj_%s(void*);" % name, 0) + if prod.attributes: + for a in prod.attributes: + self.emit_identifier(a.name) + self.emit("static char *%s_attributes[] = {" % name, 0) + for a in prod.attributes: + self.emit('"%s",' % a.name, 1) + self.emit("};", 0) if prod.fields: for f in prod.fields: self.emit_identifier(f.name) @@ -819,6 +835,7 @@ static PyObject* ast2obj_object(void *o) Py_INCREF((PyObject*)o); return (PyObject*)o; } +#define ast2obj_singleton ast2obj_object #define ast2obj_identifier ast2obj_object #define ast2obj_string ast2obj_object #define ast2obj_bytes ast2obj_object @@ -830,6 +847,17 @@ static PyObject* ast2obj_int(long b) /* Conversion Python -> AST */ +static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena) +{ + if (obj != Py_None && obj != Py_True && obj != Py_False) { + PyErr_SetString(PyExc_ValueError, + "AST singleton must be True, False, or None"); + return 1; + } + *out = obj; + return 0; +} + static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) { if (obj == Py_None) @@ -904,6 +932,19 @@ static int add_ast_fields(void) return 0; } +static int exists_not_none(PyObject *obj, _Py_Identifier *id) +{ + int isnone; + PyObject *attr = _PyObject_GetAttrId(obj, id); + if (!attr) { + PyErr_Clear(); + return 0; + } + isnone = attr == Py_None; + Py_DECREF(attr); + return !isnone; +} + """, 0, reflow=False) self.emit("static int init_types(void)",0) @@ -925,6 +966,11 @@ static int add_ast_fields(void) self.emit('%s_type = make_type("%s", &AST_type, %s, %d);' % (name, name, fields, len(prod.fields)), 1) self.emit("if (!%s_type) return 0;" % name, 1) + if prod.attributes: + self.emit("if (!add_attributes(%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) def visitSum(self, sum, name): self.emit('%s_type = make_type("%s", &AST_type, NULL, 0);' % @@ -968,7 +1014,7 @@ class ASTModuleVisitor(PickleVisitor): 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('if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)', 1) + self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)', 1) self.emit("return NULL;", 2) for dfn in mod.dfns: self.visit(dfn) @@ -1080,6 +1126,12 @@ class ObjVisitor(PickleVisitor): 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('goto failed;', 2) + self.emit('Py_DECREF(value);', 1) self.func_end() def visitConstructor(self, cons, enum, name): @@ -1142,7 +1194,8 @@ class PartingShots(StaticVisitor): CODE = """ PyObject* PyAST_mod2obj(mod_ty t) { - init_types(); + if (!init_types()) + return NULL; return ast2obj_mod(t); } @@ -1160,7 +1213,8 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) assert(0 <= mode && mode <= 2); - init_types(); + if (!init_types()) + return NULL; isinstance = PyObject_IsInstance(ast, req_type[mode]); if (isinstance == -1) @@ -1178,7 +1232,8 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) int PyAST_Check(PyObject* obj) { - init_types(); + if (!init_types()) + return -1; return PyObject_IsInstance(obj, (PyObject*)&AST_type); } """ |