diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ast.c | 4 | ||||
-rw-r--r-- | Python/ceval.c | 74 | ||||
-rw-r--r-- | Python/compile.c | 20 | ||||
-rw-r--r-- | Python/import.c | 5 |
4 files changed, 63 insertions, 40 deletions
diff --git a/Python/ast.c b/Python/ast.c index 8b68182..d5d84f7 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1994,10 +1994,14 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) } else if (TYPE(ch) == STAR) { vararg = ast_for_expr(c, CHILD(n, i+1)); + if (!vararg) + return NULL; i++; } else if (TYPE(ch) == DOUBLESTAR) { kwarg = ast_for_expr(c, CHILD(n, i+1)); + if (!kwarg) + return NULL; i++; } } diff --git a/Python/ceval.c b/Python/ceval.c index ec6d4e3..bac8278 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2021,17 +2021,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) case WITH_CLEANUP: { - /* TOP is the context.__exit__ bound method. - Below that are 1-3 values indicating how/why - we entered the finally clause: - - SECOND = None - - (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval - - SECOND = WHY_*; no retval below it - - (SECOND, THIRD, FOURTH) = exc_info() + /* At the top of the stack are 1-3 values indicating + how/why we entered the finally clause: + - TOP = None + - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval + - TOP = WHY_*; no retval below it + - (TOP, SECOND, THIRD) = exc_info() + Below them is EXIT, the context.__exit__ bound method. In the last case, we must call - TOP(SECOND, THIRD, FOURTH) + EXIT(TOP, SECOND, THIRD) otherwise we must call - TOP(None, None, None) + EXIT(None, None, None) + + In all cases, we remove EXIT from the stack, leaving + the rest in the same order. In addition, if the stack represents an exception, *and* the function call returns a 'true' value, we @@ -2040,36 +2043,59 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) should still be resumed.) */ - x = TOP(); - u = SECOND(); - if (PyLong_Check(u) || u == Py_None) { + PyObject *exit_func; + + u = POP(); + if (u == Py_None) { + exit_func = TOP(); + SET_TOP(u); + v = w = Py_None; + } + else if (PyLong_Check(u)) { + switch(PyLong_AS_LONG(u)) { + case WHY_RETURN: + case WHY_CONTINUE: + /* Retval in TOP. */ + exit_func = SECOND(); + SET_SECOND(TOP()); + SET_TOP(u); + break; + default: + exit_func = TOP(); + SET_TOP(u); + break; + } u = v = w = Py_None; } else { - v = THIRD(); - w = FOURTH(); + v = TOP(); + w = SECOND(); + exit_func = THIRD(); + SET_TOP(u); + SET_SECOND(v); + SET_THIRD(w); } /* XXX Not the fastest way to call it... */ - x = PyObject_CallFunctionObjArgs(x, u, v, w, NULL); - if (x == NULL) + x = PyObject_CallFunctionObjArgs(exit_func, u, v, w, + NULL); + if (x == NULL) { + Py_DECREF(exit_func); break; /* Go to error exit */ + } if (u != Py_None && PyObject_IsTrue(x)) { /* There was an exception and a true return */ - Py_DECREF(x); - x = TOP(); /* Again */ - STACKADJ(-3); + STACKADJ(-2); Py_INCREF(Py_None); SET_TOP(Py_None); - Py_DECREF(x); Py_DECREF(u); Py_DECREF(v); Py_DECREF(w); } else { - /* Let END_FINALLY do its thing */ - Py_DECREF(x); - x = POP(); - Py_DECREF(x); + /* The stack was rearranged to remove EXIT + above. Let END_FINALLY do its thing */ } + Py_DECREF(x); + Py_DECREF(exit_func); PREDICT(END_FINALLY); break; } diff --git a/Python/compile.c b/Python/compile.c index f415519..6ad3822 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3092,7 +3092,7 @@ compiler_with(struct compiler *c, stmt_ty s) { static identifier enter_attr, exit_attr; basicblock *block, *finally; - identifier tmpexit, tmpvalue = NULL; + identifier tmpvalue = NULL; assert(s->kind == With_kind); @@ -3112,12 +3112,6 @@ compiler_with(struct compiler *c, stmt_ty s) if (!block || !finally) return 0; - /* Create a temporary variable to hold context.__exit__ */ - tmpexit = compiler_new_tmpname(c); - if (tmpexit == NULL) - return 0; - PyArena_AddPyObject(c->c_arena, tmpexit); - if (s->v.With.optional_vars) { /* Create a temporary variable to hold context.__enter__(). We need to do this rather than preserving it on the stack @@ -3137,11 +3131,10 @@ compiler_with(struct compiler *c, stmt_ty s) /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); - /* Squirrel away context.__exit__ */ + /* Squirrel away context.__exit__ by stuffing it under context */ ADDOP(c, DUP_TOP); ADDOP_O(c, LOAD_ATTR, exit_attr, names); - if (!compiler_nameop(c, tmpexit, Store)) - return 0; + ADDOP(c, ROT_TWO); /* Call context.__enter__() */ ADDOP_O(c, LOAD_ATTR, enter_attr, names); @@ -3185,10 +3178,9 @@ compiler_with(struct compiler *c, stmt_ty s) if (!compiler_push_fblock(c, FINALLY_END, finally)) return 0; - /* Finally block starts; push tmpexit and issue our magic opcode. */ - if (!compiler_nameop(c, tmpexit, Load) || - !compiler_nameop(c, tmpexit, Del)) - return 0; + /* Finally block starts; context.__exit__ is on the stack under + the exception or return information. Just issue our magic + opcode. */ ADDOP(c, WITH_CLEANUP); /* Finally block ends. */ diff --git a/Python/import.c b/Python/import.c index 7dab46e..8f83410 100644 --- a/Python/import.c +++ b/Python/import.c @@ -72,6 +72,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *); storing constants that should have been removed) Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode) + Python 2.6a1: 62161 (WITH_CLEANUP optimization) Python 3000: 3000 3010 (removed UNARY_CONVERT) 3020 (added BUILD_SET) @@ -84,9 +85,9 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *); 3090 (kill str8 interning) 3100 (merge from 2.6a0, see 62151) 3102 (__file__ points to source file) -. + Python 3.0a4: 3110 (WITH_CLEANUP optimization). */ -#define MAGIC (3102 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3110 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the |