Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 207c9f3

Browse files
committed
Merged revisions 62049,62054 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r62049 | georg.brandl | 2008-03-30 00:01:47 -0700 (Sun, 30 Mar 2008) | 2 lines #2505: allow easier creation of AST nodes. ........ r62054 | georg.brandl | 2008-03-30 12:43:27 -0700 (Sun, 30 Mar 2008) | 2 lines Fix error message -- "expects either 0 or 0 arguments" ........
1 parent db4115f commit 207c9f3

3 files changed

Lines changed: 241 additions & 31 deletions

File tree

Doc/library/_ast.rst

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,32 @@ node. The utf8 offset is recorded because the parser uses utf8 internally.
4444
If these attributes are marked as optional in the grammar (using a question
4545
mark), the value might be ``None``. If the attributes can have zero-or-more
4646
values (marked with an asterisk), the values are represented as Python lists.
47+
All possible attributes must be present and have valid values when compiling an
48+
AST with :func:`compile`.
49+
50+
The constructor of a class ``_ast.T`` parses their arguments as follows:
51+
52+
* If there are positional arguments, there must be as many as there are items in
53+
``T._fields``; they will be assigned as attributes of these names.
54+
* If there are keyword arguments, they will set the attributes of the same names
55+
to the given values.
56+
57+
For example, to create and populate a ``UnaryOp`` node, you could use ::
58+
59+
node = _ast.UnaryOp()
60+
node.op = _ast.USub()
61+
node.operand = _ast.Num()
62+
node.operand.n = 5
63+
node.operand.lineno = 0
64+
node.operand.col_offset = 0
65+
node.lineno = 0
66+
node.col_offset = 0
67+
68+
or the more compact ::
69+
70+
node = _ast.UnaryOp(_ast.USub(), _ast.Num(5, lineno=0, col_offset=0),
71+
lineno=0, col_offset=0)
4772

48-
The constructors of all ``_ast`` classes don't take arguments; instead, if you
49-
create instances, you must assign the required attributes separately.
5073

5174

5275
Abstract Grammar

Parser/asdl_c.py

Lines changed: 102 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,100 @@ class PyTypesVisitor(PickleVisitor):
577577

578578
def visitModule(self, mod):
579579
self.emit("""
580+
static int
581+
ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
582+
{
583+
Py_ssize_t i, numfields = 0;
584+
int res = -1;
585+
PyObject *key, *value, *fields;
586+
fields = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "_fields");
587+
if (!fields)
588+
PyErr_Clear();
589+
if (fields) {
590+
numfields = PySequence_Size(fields);
591+
if (numfields == -1)
592+
goto cleanup;
593+
}
594+
res = 0; /* if no error occurs, this stays 0 to the end */
595+
if (PyTuple_GET_SIZE(args) > 0) {
596+
if (numfields != PyTuple_GET_SIZE(args)) {
597+
PyErr_Format(PyExc_TypeError, "%.400s constructor takes %s"
598+
"%" PY_FORMAT_SIZE_T "d positional argument%s",
599+
Py_TYPE(self)->tp_name,
600+
numfields == 0 ? "" : "either 0 or ",
601+
numfields, numfields == 1 ? "" : "s");
602+
res = -1;
603+
goto cleanup;
604+
}
605+
for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
606+
/* cannot be reached when fields is NULL */
607+
PyObject *name = PySequence_GetItem(fields, i);
608+
if (!name) {
609+
res = -1;
610+
goto cleanup;
611+
}
612+
res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));
613+
Py_DECREF(name);
614+
if (res < 0)
615+
goto cleanup;
616+
}
617+
}
618+
if (kw) {
619+
i = 0; /* needed by PyDict_Next */
620+
while (PyDict_Next(kw, &i, &key, &value)) {
621+
res = PyObject_SetAttr(self, key, value);
622+
if (res < 0)
623+
goto cleanup;
624+
}
625+
}
626+
cleanup:
627+
Py_XDECREF(fields);
628+
return res;
629+
}
630+
631+
static PyTypeObject AST_type = {
632+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
633+
"AST",
634+
sizeof(PyObject),
635+
0,
636+
0, /* tp_dealloc */
637+
0, /* tp_print */
638+
0, /* tp_getattr */
639+
0, /* tp_setattr */
640+
0, /* tp_compare */
641+
0, /* tp_repr */
642+
0, /* tp_as_number */
643+
0, /* tp_as_sequence */
644+
0, /* tp_as_mapping */
645+
0, /* tp_hash */
646+
0, /* tp_call */
647+
0, /* tp_str */
648+
PyObject_GenericGetAttr, /* tp_getattro */
649+
PyObject_GenericSetAttr, /* tp_setattro */
650+
0, /* tp_as_buffer */
651+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
652+
0, /* tp_doc */
653+
0, /* tp_traverse */
654+
0, /* tp_clear */
655+
0, /* tp_richcompare */
656+
0, /* tp_weaklistoffset */
657+
0, /* tp_iter */
658+
0, /* tp_iternext */
659+
0, /* tp_methods */
660+
0, /* tp_members */
661+
0, /* tp_getset */
662+
0, /* tp_base */
663+
0, /* tp_dict */
664+
0, /* tp_descr_get */
665+
0, /* tp_descr_set */
666+
0, /* tp_dictoffset */
667+
(initproc)ast_type_init, /* tp_init */
668+
PyType_GenericAlloc, /* tp_alloc */
669+
PyType_GenericNew, /* tp_new */
670+
PyObject_Del, /* tp_free */
671+
};
672+
673+
580674
static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields)
581675
{
582676
PyObject *fnames, *result;
@@ -605,15 +699,15 @@ def visitModule(self, mod):
605699
static int add_attributes(PyTypeObject* type, char**attrs, int num_fields)
606700
{
607701
int i, result;
608-
PyObject *s, *l = PyList_New(num_fields);
702+
PyObject *s, *l = PyTuple_New(num_fields);
609703
if (!l) return 0;
610704
for(i = 0; i < num_fields; i++) {
611705
s = PyUnicode_FromString(attrs[i]);
612706
if (!s) {
613707
Py_DECREF(l);
614708
return 0;
615709
}
616-
PyList_SET_ITEM(l, i, s);
710+
PyTuple_SET_ITEM(l, i, s);
617711
}
618712
result = PyObject_SetAttrString((PyObject*)type, "_attributes", l) >= 0;
619713
Py_DECREF(l);
@@ -696,7 +790,6 @@ def visitModule(self, mod):
696790
self.emit("{", 0)
697791
self.emit("static int initialized;", 1)
698792
self.emit("if (initialized) return 1;", 1)
699-
self.emit('AST_type = make_type("AST", &PyBaseObject_Type, NULL, 0);', 1)
700793
for dfn in mod.dfns:
701794
self.visit(dfn)
702795
self.emit("initialized = 1;", 1)
@@ -708,12 +801,13 @@ def visitProduct(self, prod, name):
708801
fields = name.value+"_fields"
709802
else:
710803
fields = "NULL"
711-
self.emit('%s_type = make_type("%s", AST_type, %s, %d);' %
804+
self.emit('%s_type = make_type("%s", &AST_type, %s, %d);' %
712805
(name, name, fields, len(prod.fields)), 1)
713806
self.emit("if (!%s_type) return 0;" % name, 1)
714807

715808
def visitSum(self, sum, name):
716-
self.emit('%s_type = make_type("%s", AST_type, NULL, 0);' % (name, name), 1)
809+
self.emit('%s_type = make_type("%s", &AST_type, NULL, 0);' %
810+
(name, name), 1)
717811
self.emit("if (!%s_type) return 0;" % name, 1)
718812
if sum.attributes:
719813
self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" %
@@ -752,7 +846,7 @@ def visitModule(self, mod):
752846
self.emit('m = Py_InitModule3("_ast", NULL, NULL);', 1)
753847
self.emit("if (!m) return;", 1)
754848
self.emit("d = PyModule_GetDict(m);", 1)
755-
self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return;', 1)
849+
self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return;', 1)
756850
self.emit('if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)', 1)
757851
self.emit("return;", 2)
758852
# Value of version: "$Revision$"
@@ -959,7 +1053,7 @@ class PartingShots(StaticVisitor):
9591053
int PyAST_Check(PyObject* obj)
9601054
{
9611055
init_types();
962-
return PyObject_IsInstance(obj, (PyObject*)AST_type);
1056+
return PyObject_IsInstance(obj, (PyObject*)&AST_type);
9631057
}
9641058
"""
9651059

@@ -1016,7 +1110,7 @@ def main(srcfile):
10161110
f.write('#include "Python.h"\n')
10171111
f.write('#include "%s-ast.h"\n' % mod.name)
10181112
f.write('\n')
1019-
f.write("static PyTypeObject* AST_type;\n")
1113+
f.write("static PyTypeObject AST_type;\n")
10201114
v = ChainOfVisitors(
10211115
PyTypesDeclareVisitor(f),
10221116
PyTypesVisitor(f),

0 commit comments

Comments
 (0)