diff options
| -rw-r--r-- | Include/Python-ast.h | 17 | ||||
| -rw-r--r-- | Lib/test/test_ast.py | 4 | ||||
| -rw-r--r-- | Parser/Python.asdl | 7 | ||||
| -rw-r--r-- | Python/Python-ast.c | 186 | ||||
| -rw-r--r-- | Python/ast.c | 6 | ||||
| -rw-r--r-- | Python/compile.c | 20 | ||||
| -rw-r--r-- | Python/symtable.c | 10 | 
7 files changed, 141 insertions, 109 deletions
diff --git a/Include/Python-ast.h b/Include/Python-ast.h index 6653b087ca..0ad788b8ee 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 cd69ce1de7..d08003236f 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 8686709b9b..b4dd7928c9 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 b88b310af5..a50435f206 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 759dd73ab9..6a9658a974 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 ab51c7bb26..9ce8ac334f 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 b896c52563..0c11ee1aab 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;  }  | 
