@@ -761,6 +761,8 @@ opcode_stack_effect(int opcode, int oparg)
761761 return -1 ;
762762 case BREAK_LOOP :
763763 return 0 ;
764+ case SETUP_WITH :
765+ return 7 ;
764766 case WITH_CLEANUP :
765767 return -1 ; /* XXX Sometimes more */
766768 case STORE_LOCALS :
@@ -3085,85 +3087,31 @@ expr_constant(expr_ty e)
30853087static int
30863088compiler_with (struct compiler * c , stmt_ty s )
30873089{
3088- static identifier enter_attr , exit_attr ;
30893090 basicblock * block , * finally ;
3090- identifier tmpvalue = NULL , tmpexit = NULL ;
30913091
30923092 assert (s -> kind == With_kind );
30933093
3094- if (!enter_attr ) {
3095- enter_attr = PyUnicode_InternFromString ("__enter__" );
3096- if (!enter_attr )
3097- return 0 ;
3098- }
3099- if (!exit_attr ) {
3100- exit_attr = PyUnicode_InternFromString ("__exit__" );
3101- if (!exit_attr )
3102- return 0 ;
3103- }
3104-
31053094 block = compiler_new_block (c );
31063095 finally = compiler_new_block (c );
31073096 if (!block || !finally )
31083097 return 0 ;
31093098
3110- if (s -> v .With .optional_vars ) {
3111- /* Create a temporary variable to hold context.__enter__().
3112- We need to do this rather than preserving it on the stack
3113- because SETUP_FINALLY remembers the stack level.
3114- We need to do the assignment *inside* the try/finally
3115- so that context.__exit__() is called when the assignment
3116- fails. But we need to call context.__enter__() *before*
3117- the try/finally so that if it fails we won't call
3118- context.__exit__().
3119- */
3120- tmpvalue = compiler_new_tmpname (c );
3121- if (tmpvalue == NULL )
3122- return 0 ;
3123- PyArena_AddPyObject (c -> c_arena , tmpvalue );
3124- }
3125- tmpexit = compiler_new_tmpname (c );
3126- if (tmpexit == NULL )
3127- return 0 ;
3128- PyArena_AddPyObject (c -> c_arena , tmpexit );
3129-
31303099 /* Evaluate EXPR */
31313100 VISIT (c , expr , s -> v .With .context_expr );
3101+ ADDOP_JREL (c , SETUP_WITH , finally );
31323102
3133- /* Squirrel away context.__exit__ by stuffing it under context */
3134- ADDOP (c , DUP_TOP );
3135- ADDOP_O (c , LOAD_ATTR , exit_attr , names );
3136- if (!compiler_nameop (c , tmpexit , Store ))
3137- return 0 ;
3138-
3139- /* Call context.__enter__() */
3140- ADDOP_O (c , LOAD_ATTR , enter_attr , names );
3141- ADDOP_I (c , CALL_FUNCTION , 0 );
3142-
3143- if (s -> v .With .optional_vars ) {
3144- /* Store it in tmpvalue */
3145- if (!compiler_nameop (c , tmpvalue , Store ))
3146- return 0 ;
3147- }
3148- else {
3149- /* Discard result from context.__enter__() */
3150- ADDOP (c , POP_TOP );
3151- }
3152-
3153- /* Start the try block */
3154- ADDOP_JREL (c , SETUP_FINALLY , finally );
3155-
3103+ /* SETUP_WITH pushes a finally block. */
31563104 compiler_use_next_block (c , block );
31573105 if (!compiler_push_fblock (c , FINALLY_TRY , block )) {
31583106 return 0 ;
31593107 }
31603108
31613109 if (s -> v .With .optional_vars ) {
3162- /* Bind saved result of context.__enter__() to VAR */
3163- if (! compiler_nameop ( c , tmpvalue , Load ) ||
3164- ! compiler_nameop ( c , tmpvalue , Del ))
3165- return 0 ;
3166- VISIT (c , expr , s -> v . With . optional_vars );
3110+ VISIT ( c , expr , s -> v . With . optional_vars );
3111+ }
3112+ else {
3113+ /* Discard result from context.__enter__() */
3114+ ADDOP (c , POP_TOP );
31673115 }
31683116
31693117 /* BLOCK code */
@@ -3181,9 +3129,6 @@ compiler_with(struct compiler *c, stmt_ty s)
31813129 /* Finally block starts; context.__exit__ is on the stack under
31823130 the exception or return information. Just issue our magic
31833131 opcode. */
3184- if (!compiler_nameop (c , tmpexit , Load ) ||
3185- !compiler_nameop (c , tmpexit , Del ))
3186- return 0 ;
31873132 ADDOP (c , WITH_CLEANUP );
31883133
31893134 /* Finally block ends. */
0 commit comments