From ad74aa8dc015fab019ffa965f45cc3437ad152c2 Mon Sep 17 00:00:00 2001 From: Neal Norwitz Date: Mon, 31 Mar 2008 05:14:30 +0000 Subject: [PATCH] Merged revisions 62047 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r62047 | georg.brandl | 2008-03-29 23:40:17 -0700 (Sat, 29 Mar 2008) | 2 lines Patch #2511: Give the "excepthandler" AST item proper attributes by making it a Sum. ........ --- Include/Python-ast.h | 17 ++-- Lib/test/test_ast.py | 4 +- Parser/Python.asdl | 7 +- Python/Python-ast.c | 186 +++++++++++++++++++++++++------------------ Python/ast.c | 6 +- Python/compile.c | 20 ++--- Python/symtable.c | 10 +-- 7 files changed, 141 insertions(+), 109 deletions(-) diff --git a/Include/Python-ast.h b/Include/Python-ast.h index 6653b087ca0..0ad788b8eeb 100644 --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -342,10 +342,17 @@ struct _comprehension { asdl_seq *ifs; }; +enum _excepthandler_kind {ExceptHandler_kind=1}; struct _excepthandler { - expr_ty type; - identifier name; - asdl_seq *body; + enum _excepthandler_kind kind; + union { + struct { + expr_ty type; + identifier name; + asdl_seq *body; + } ExceptHandler; + + } v; int lineno; int col_offset; }; @@ -525,8 +532,8 @@ slice_ty _Py_Index(expr_ty value, PyArena *arena); #define comprehension(a0, a1, a2, a3) _Py_comprehension(a0, a1, a2, a3) comprehension_ty _Py_comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena); -#define excepthandler(a0, a1, a2, a3, a4, a5) _Py_excepthandler(a0, a1, a2, a3, a4, a5) -excepthandler_ty _Py_excepthandler(expr_ty type, identifier name, asdl_seq * +#define ExceptHandler(a0, a1, a2, a3, a4, a5) _Py_ExceptHandler(a0, a1, a2, a3, a4, a5) +excepthandler_ty _Py_ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int col_offset, PyArena *arena); #define arguments(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_arguments(a0, a1, a2, a3, a4, a5, a6, a7, a8) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index cd69ce1de72..d08003236f7 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -152,7 +152,7 @@ def run_tests(): #### EVERYTHING BELOW IS GENERATED ##### exec_results = [ ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Pass', (1, 9))], [], None)]), -('Module', [('ClassDef', (1, 0), 'C', [], [], None, None, [('Pass', (1, 8))], [], )]), +('Module', [('ClassDef', (1, 0), 'C', [], [], None, None, [('Pass', (1, 8))], [])]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), @@ -161,7 +161,7 @@ exec_results = [ ('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]), ('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]), ('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]), -('Module', [('TryExcept', (1, 0), [('Pass', (2, 2))], [('excepthandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))], 3, 0)], [])]), +('Module', [('TryExcept', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [])]), ('Module', [('TryFinally', (1, 0), [('Pass', (2, 2))], [('Pass', (4, 2))])]), ('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]), ('Module', [('Import', (1, 0), [('alias', 'sys', None)])]), diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 8686709b9b1..b4dd7928c91 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -101,11 +101,8 @@ module Python version "$Revision$" comprehension = (expr target, expr iter, expr* ifs) -- not sure what to call the first argument for raise and except - -- TODO(jhylton): Figure out if there is a better way to handle - -- lineno and col_offset fields, particularly when - -- ast is exposed to Python. - excepthandler = (expr? type, identifier? name, stmt* body, int lineno, - int col_offset) + excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) + attributes (int lineno, int col_offset) arguments = (arg* args, identifier? vararg, expr? varargannotation, arg* kwonlyargs, identifier? kwarg, diff --git a/Python/Python-ast.c b/Python/Python-ast.c index b88b310af53..a50435f2067 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -351,13 +351,16 @@ static char *comprehension_fields[]={ "ifs", }; static PyTypeObject *excepthandler_type; +static char *excepthandler_attributes[] = { + "lineno", + "col_offset", +}; static PyObject* ast2obj_excepthandler(void*); -static char *excepthandler_fields[]={ +static PyTypeObject *ExceptHandler_type; +static char *ExceptHandler_fields[]={ "type", "name", "body", - "lineno", - "col_offset", }; static PyTypeObject *arguments_type; static PyObject* ast2obj_arguments(void*); @@ -881,9 +884,13 @@ static int init_types(void) comprehension_type = make_type("comprehension", &AST_type, comprehension_fields, 3); if (!comprehension_type) return 0; - excepthandler_type = make_type("excepthandler", &AST_type, - excepthandler_fields, 5); + excepthandler_type = make_type("excepthandler", &AST_type, NULL, 0); if (!excepthandler_type) return 0; + if (!add_attributes(excepthandler_type, excepthandler_attributes, 2)) + return 0; + ExceptHandler_type = make_type("ExceptHandler", excepthandler_type, + ExceptHandler_fields, 3); + if (!ExceptHandler_type) return 0; arguments_type = make_type("arguments", &AST_type, arguments_fields, 8); if (!arguments_type) return 0; arg_type = make_type("arg", &AST_type, arg_fields, 2); @@ -2002,16 +2009,17 @@ comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena) } excepthandler_ty -excepthandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int +ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int col_offset, PyArena *arena) { excepthandler_ty p; p = (excepthandler_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; - p->type = type; - p->name = name; - p->body = body; + p->kind = ExceptHandler_kind; + p->v.ExceptHandler.type = type; + p->v.ExceptHandler.name = name; + p->v.ExceptHandler.body = body; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -3144,31 +3152,35 @@ ast2obj_excepthandler(void* _o) return Py_None; } - result = PyType_GenericNew(excepthandler_type, NULL, NULL); - if (!result) return NULL; - value = ast2obj_expr(o->type); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "type", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_identifier(o->name); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); + switch (o->kind) { + case ExceptHandler_kind: + result = PyType_GenericNew(ExceptHandler_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(o->v.ExceptHandler.type); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "type", value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_identifier(o->v.ExceptHandler.name); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "name", value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.ExceptHandler.body, ast2obj_stmt); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "body", value) == -1) + goto failed; + Py_DECREF(value); + break; + } value = ast2obj_int(o->lineno); if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) == -1) + if (PyObject_SetAttrString(result, "lineno", value) < 0) goto failed; Py_DECREF(value); value = ast2obj_int(o->col_offset); if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) == -1) + if (PyObject_SetAttrString(result, "col_offset", value) < 0) goto failed; Py_DECREF(value); return result; @@ -5976,58 +5988,13 @@ int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) { PyObject* tmp = NULL; - expr_ty type; - identifier name; - asdl_seq* body; + int lineno; int col_offset; - if (PyObject_HasAttrString(obj, "type")) { - int res; - tmp = PyObject_GetAttrString(obj, "type"); - if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &type, arena); - if (res != 0) goto failed; - Py_XDECREF(tmp); - tmp = NULL; - } else { - type = NULL; - } - if (PyObject_HasAttrString(obj, "name")) { - int res; - tmp = PyObject_GetAttrString(obj, "name"); - if (tmp == NULL) goto failed; - res = obj2ast_identifier(tmp, &name, arena); - if (res != 0) goto failed; - Py_XDECREF(tmp); - tmp = NULL; - } else { - name = NULL; - } - if (PyObject_HasAttrString(obj, "body")) { - int res; - Py_ssize_t len; - Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); - if (tmp == NULL) goto failed; - if (!PyList_Check(tmp)) { - PyErr_Format(PyExc_TypeError, "excepthandler field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); - goto failed; - } - len = PyList_GET_SIZE(tmp); - body = asdl_seq_new(len, arena); - if (body == NULL) goto failed; - for (i = 0; i < len; i++) { - stmt_ty value; - res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); - if (res != 0) goto failed; - asdl_seq_SET(body, i, value); - } - Py_XDECREF(tmp); - tmp = NULL; - } else { - PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from excepthandler"); - return 1; + if (obj == Py_None) { + *out = NULL; + return 0; } if (PyObject_HasAttrString(obj, "lineno")) { int res; @@ -6053,8 +6020,67 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from excepthandler"); return 1; } - *out = excepthandler(type, name, body, lineno, col_offset, arena); - return 0; + if (PyObject_IsInstance(obj, (PyObject*)ExceptHandler_type)) { + expr_ty type; + identifier name; + asdl_seq* body; + + if (PyObject_HasAttrString(obj, "type")) { + int res; + tmp = PyObject_GetAttrString(obj, "type"); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &type, arena); + if (res != 0) goto failed; + Py_XDECREF(tmp); + tmp = NULL; + } else { + type = NULL; + } + if (PyObject_HasAttrString(obj, "name")) { + int res; + tmp = PyObject_GetAttrString(obj, "name"); + if (tmp == NULL) goto failed; + res = obj2ast_identifier(tmp, &name, arena); + if (res != 0) goto failed; + Py_XDECREF(tmp); + tmp = NULL; + } else { + name = NULL; + } + if (PyObject_HasAttrString(obj, "body")) { + int res; + Py_ssize_t len; + Py_ssize_t i; + tmp = PyObject_GetAttrString(obj, "body"); + if (tmp == NULL) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "ExceptHandler field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + body = asdl_seq_new(len, arena); + if (body == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty value; + res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(body, i, value); + } + Py_XDECREF(tmp); + tmp = NULL; + } else { + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from ExceptHandler"); + return 1; + } + *out = ExceptHandler(type, name, body, lineno, col_offset, + arena); + if (*out == NULL) goto failed; + return 0; + } + + tmp = PyObject_Repr(obj); + if (tmp == NULL) goto failed; + PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %.400s", PyString_AS_STRING(tmp)); failed: Py_XDECREF(tmp); return 1; @@ -6493,6 +6519,8 @@ init_ast(void) (PyObject*)comprehension_type) < 0) return; if (PyDict_SetItemString(d, "excepthandler", (PyObject*)excepthandler_type) < 0) return; + if (PyDict_SetItemString(d, "ExceptHandler", + (PyObject*)ExceptHandler_type) < 0) return; if (PyDict_SetItemString(d, "arguments", (PyObject*)arguments_type) < 0) return; if (PyDict_SetItemString(d, "arg", (PyObject*)arg_type) < 0) return; diff --git a/Python/ast.c b/Python/ast.c index 759dd73ab94..6a9658a9742 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2787,7 +2787,7 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body) if (!suite_seq) return NULL; - return excepthandler(NULL, NULL, suite_seq, LINENO(exc), + return ExceptHandler(NULL, NULL, suite_seq, LINENO(exc), exc->n_col_offset, c->c_arena); } else if (NCH(exc) == 2) { @@ -2801,7 +2801,7 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body) if (!suite_seq) return NULL; - return excepthandler(expression, NULL, suite_seq, LINENO(exc), + return ExceptHandler(expression, NULL, suite_seq, LINENO(exc), exc->n_col_offset, c->c_arena); } else if (NCH(exc) == 4) { @@ -2817,7 +2817,7 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body) if (!suite_seq) return NULL; - return excepthandler(expression, e, suite_seq, LINENO(exc), + return ExceptHandler(expression, e, suite_seq, LINENO(exc), exc->n_col_offset, c->c_arena); } diff --git a/Python/compile.c b/Python/compile.c index ab51c7bb26b..9ce8ac334ff 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1984,22 +1984,22 @@ compiler_try_except(struct compiler *c, stmt_ty s) for (i = 0; i < n; i++) { excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( s->v.TryExcept.handlers, i); - if (!handler->type && i < n-1) + if (!handler->v.ExceptHandler.type && i < n-1) return compiler_error(c, "default 'except:' must be last"); c->u->u_lineno_set = 0; c->u->u_lineno = handler->lineno; except = compiler_new_block(c); if (except == NULL) return 0; - if (handler->type) { + if (handler->v.ExceptHandler.type) { ADDOP(c, DUP_TOP); - VISIT(c, expr, handler->type); + VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); ADDOP_JREL(c, JUMP_IF_FALSE, except); ADDOP(c, POP_TOP); } ADDOP(c, POP_TOP); - if (handler->name) { + if (handler->v.ExceptHandler.name) { basicblock *cleanup_end, *cleanup_body; cleanup_end = compiler_new_block(c); @@ -2007,7 +2007,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) if(!(cleanup_end || cleanup_body)) return 0; - compiler_nameop(c, handler->name, Store); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); ADDOP(c, POP_TOP); /* @@ -2028,7 +2028,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) return 0; /* second # body */ - VISIT_SEQ(c, stmt, handler->body); + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); @@ -2040,10 +2040,10 @@ compiler_try_except(struct compiler *c, stmt_ty s) /* name = None */ ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_nameop(c, handler->name, Store); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); /* del name */ - compiler_nameop(c, handler->name, Del); + compiler_nameop(c, handler->v.ExceptHandler.name, Del); ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, cleanup_end); @@ -2051,11 +2051,11 @@ compiler_try_except(struct compiler *c, stmt_ty s) else { ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - VISIT_SEQ(c, stmt, handler->body); + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); } ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, except); - if (handler->type) + if (handler->v.ExceptHandler.type) ADDOP(c, POP_TOP); } ADDOP(c, END_FINALLY); diff --git a/Python/symtable.c b/Python/symtable.c index b896c525639..0c11ee1aab3 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1431,12 +1431,12 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) { - if (eh->type) - VISIT(st, expr, eh->type); - if (eh->name) - if (!symtable_add_def(st, eh->name, DEF_LOCAL)) + if (eh->v.ExceptHandler.type) + VISIT(st, expr, eh->v.ExceptHandler.type); + if (eh->v.ExceptHandler.name) + if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) return 0; - VISIT_SEQ(st, stmt, eh->body); + VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); return 1; }