diff Python/ceval.c @ 36695:b6d2f6fd3e11 legacy-trunk

PEP 343 -- the with-statement. This was started by Mike Bland and completed by Guido (with help from Neal). This still needs a __future__ statement added; Thomas is working on Michael's patch for that aspect. There's a small amount of code cleanup and refactoring in ast.c, compile.c and ceval.c (I fixed the lltrace behavior when EXT_POP is used -- however I had to make lltrace a static global).
author Guido van Rossum <guido@python.org>
date Mon, 27 Feb 2006 22:32:47 +0000
parents 8e13236243dd
children 35dbbc1ab448
line wrap: on
line diff
--- a/Python/ceval.c	Mon Feb 27 21:41:03 2006 +0000
+++ b/Python/ceval.c	Mon Feb 27 22:32:47 2006 +0000
@@ -97,6 +97,7 @@
 #define CALL_FLAG_KW 2
 
 #ifdef LLTRACE
+static int lltrace;
 static int prtrace(PyObject *, char *);
 #endif
 static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
@@ -540,9 +541,6 @@
 	unsigned char *first_instr;
 	PyObject *names;
 	PyObject *consts;
-#ifdef LLTRACE
-	int lltrace;
-#endif
 #if defined(Py_DEBUG) || defined(LLTRACE)
 	/* Make it easier to find out where we are with a debugger */
 	char *filename;
@@ -661,10 +659,12 @@
 #define STACKADJ(n)	{ (void)(BASIC_STACKADJ(n), \
                                lltrace && prtrace(TOP(), "stackadj")); \
                                assert(STACK_LEVEL() <= f->f_stacksize); }
+#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER))
 #else
 #define PUSH(v)		BASIC_PUSH(v)
 #define POP()		BASIC_POP()
 #define STACKADJ(n)	BASIC_STACKADJ(n)
+#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
 #endif
 
 /* Local variable macros */
@@ -2172,6 +2172,43 @@
 					   STACK_LEVEL());
 			continue;
 
+		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 or WHY_CONTINUE), retval
+			   - SECOND = WHY_*; no retval below it
+			   - (SECOND, THIRD, FOURTH) = exc_info()
+			   In the last case, we must call
+			     TOP(SECOND, THIRD, FOURTH)
+			   otherwise we must call
+			     TOP(None, None, None)
+			   but we must preserve the stack entries below TOP.
+			   The code here just sets the stack up for the call;
+			   separate CALL_FUNCTION(3) and POP_TOP opcodes are
+			   emitted by the compiler.
+			*/
+			
+			x = TOP();
+			u = SECOND();
+			if (PyInt_Check(u) || u == Py_None) {
+				u = v = w = Py_None;
+			}
+			else {
+				v = THIRD();
+				w = FOURTH();
+			}
+			Py_INCREF(u);
+			Py_INCREF(v);
+			Py_INCREF(w);
+			PUSH(u);
+			PUSH(v);
+			PUSH(w);
+			break;
+		}
+
 		case CALL_FUNCTION:
 		{
 			PyObject **sp;
@@ -2511,9 +2548,9 @@
 	return retval;
 }
 
-/* this is gonna seem *real weird*, but if you put some other code between
+/* This is gonna seem *real weird*, but if you put some other code between
    PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
-	the test in the if statement in Misc/gdbinit:pystack* */
+   the test in the if statements in Misc/gdbinit (pystack and pystackv). */
 
 PyObject *
 PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
@@ -3473,8 +3510,6 @@
 	}
 }
 
-#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
-
 static void
 err_args(PyObject *func, int flags, int nargs)
 {