Index: src/pmc/closure.pmc =================================================================== --- src/pmc/closure.pmc (revision 14848) +++ src/pmc/closure.pmc (working copy) @@ -92,46 +92,13 @@ outer_sub = sub->outer_sub; if (sub->outer_ctx) { /* during newclosure, outer's ctx was stored in - * sub->outer_ctx + * sub->outer_ctx. we need to copy it into our ctx. */ - sub->ctx->outer_ctx = sub->outer_ctx; + CONTEXT(INTERP->ctx)->outer_ctx = sub->outer_ctx; } - else if ((PObj_get_FLAGS(outer_sub) & SUB_FLAG_IS_OUTER) && - PMC_sub(outer_sub)->ctx) { - /* the sub was invoked earlier - it still has the context - * due to the SUB_FLAG_IS_OUTER flag - */ - sub->outer_ctx = sub->ctx->outer_ctx = PMC_sub(outer_sub)->ctx; - } else { - /* closure is just invoked - located :outer's ctx */ - parrot_context_t *caller = sub->ctx->caller_ctx; - while (caller) { - if (caller->current_sub == outer_sub) { - cont = caller->current_cont; - cont->vtable = - interpreter->vtables[enum_class_Continuation]; - sub->outer_ctx = sub->ctx->outer_ctx = caller; - caller->ref_count++; - return next; - } - caller = caller->caller_ctx; - } - if (!caller) { - /* outer has never been invoked, we fake a subroutine call - * which builds the LexPad and return immediately - * this will usually just lead to a Null PMC access - * exception - */ - INTERP->current_cont = NEED_CONTINUATION; - (void)VTABLE_invoke(INTERP, sub->outer_sub, next); - caller = CONTEXT(INTERP->ctx); - cont = caller->current_cont; - cont->vtable = interpreter->vtables[enum_class_Continuation]; - sub->outer_ctx = sub->ctx->outer_ctx = caller; - caller->ref_count++; - (void)VTABLE_invoke(INTERP, cont, next); - } + real_exception(interpreter, NULL, 1, + "Closure sub called without 'newclosure'.\n"); } return next; } Index: src/pmc/sub.pmc =================================================================== --- src/pmc/sub.pmc (revision 14848) +++ src/pmc/sub.pmc (working copy) @@ -275,10 +275,6 @@ * and copy set context variables */ PMC_cont(ccont)->from_ctx = context; - /* - * set context of the sub - */ - sub->ctx = context; if (PObj_get_FLAGS(SELF) & SUB_FLAG_IS_OUTER) { /* don't destroy context */ ccont->vtable = interpreter->vtables[enum_class_Continuation]; Index: include/parrot/sub.h =================================================================== --- include/parrot/sub.h (revision 14848) +++ include/parrot/sub.h (working copy) @@ -70,7 +70,7 @@ PMC *lex_info; /* LexInfo PMC */ PMC *outer_sub; /* :outer for closures */ PMC *eval_pmc; /* eval container / NULL */ - parrot_context_t *ctx; /* the context this sub is in */ + parrot_context_t *broken_ctx; /* the context this sub is in */ /* - end common */ struct Parrot_Context *outer_ctx; /* outer context, if a closure */ Index: t/pmc/exception.t =================================================================== --- t/pmc/exception.t (revision 14848) +++ t/pmc/exception.t (working copy) @@ -728,7 +728,8 @@ a = 42 print "main\n" .const .Sub at_exit = "exit_handler" - pushaction at_exit + $P0 = newclosure at_exit + pushaction $P0 .return() .end @@ -756,7 +757,8 @@ push_eh h print "main\n" .const .Sub at_exit = "exit_handler" - pushaction at_exit + $P0 = newclosure at_exit + pushaction $P0 $P1 = new .Exception throw $P1 print "never 1\n" @@ -783,10 +785,12 @@ pir_output_is(<<'CODE', <<'OUTPUT', "exit_handler via exit exception"); .sub main :main - .local pmc a + .local pmc a, exit_handler .lex 'a', a a = new .Integer a = 42 + .const .Sub exit_handler_sub = "exit_handler" + exit_handler = newclosure exit_handler_sub push_eh handler exit 0 handler: Index: t/op/lexicals.t =================================================================== --- t/op/lexicals.t (revision 14848) +++ t/op/lexicals.t (working copy) @@ -364,7 +364,9 @@ pir_output_is(<<'CODE', <<'OUTPUT', 'get_outer'); .sub "main" - foo() + .const .Sub foo = "foo" + $P0 = newclosure foo + $P0() .end .sub foo :outer('main') .include "interpinfo.pasm" @@ -379,10 +381,14 @@ pir_output_is(<<'CODE', <<'OUTPUT', 'get_outer 2'); .sub "main" - foo() + .const .Sub foo = "foo" + $P0 = newclosure foo + $P0() .end .sub foo :outer('main') - bar() + .const .Sub bar = "bar" + $P0 = newclosure bar + $P0() .end .sub bar :outer('foo') .include "interpinfo.pasm" @@ -820,7 +826,9 @@ .lex '$x', $P0 $P0 = new .Integer $P0 = 5 - anon_1() + .const .Sub $P1 = 'anon_1' + $P2 = newclosure $P1 + $P2() .end .sub anon_1 :anon :outer(main) @@ -839,11 +847,17 @@ pir_output_like(<<'CODE', <<'OUTPUT', 'get non existing'); .sub "main" :main .lex 'a', $P0 - foo() + .local pmc sub_foo, closure_foo + .const .Sub sub_foo = "foo" + closure_foo = newclosure sub_foo + closure_foo() .end .sub foo :outer('main') .lex 'b', $P0 - bar() + .local pmc sub_bar, closure_bar + .const .Sub sub_bar = "bar" + closure_bar = newclosure sub_bar + closure_bar() .end .sub bar :outer('foo') .lex 'c', $P0 @@ -898,8 +912,11 @@ # f() # print "$x\n" .sub '&main' :main :anon - .local pmc sx + .local pmc sx, sub_f, closure_f .lex '$x', sx + .const .Sub sub_f = "raw_&f" + closure_f = newclosure sub_f + store_global '&f', closure_f sx = new .Integer sx = 33 '&f'() @@ -915,7 +932,7 @@ print "\n" .end -.sub '&f' :outer('&main') +.sub 'raw_&f' :outer('&main') $P0 = find_lex '$x' # find_lex needed inc $P0 .end @@ -932,8 +949,12 @@ # g() # print "$x\n" .sub '&main' :main :anon - .local pmc sx + .local pmc sx, sub_f, closure_f .lex '$x', sx + .const .Sub sub_f = "raw_&f" + closure_f = newclosure sub_f + store_global '&f', closure_f + sx = new .Integer sx = -32 '&g'() @@ -950,12 +971,12 @@ .end -.sub '&f' :outer('&main') +.sub 'raw_&f' :outer('&main') $P0 = find_lex '$x' inc $P0 .end -.sub '&g' :outer('&main') # :outer not needed - no find_lex +.sub '&g' # :outer not needed - no find_lex '&f'() '&f'() .end @@ -974,11 +995,15 @@ .sub '&f' .param pmc x .lex '$x', x + .local pmc sub_g, closure_g + .const .Sub sub_g = "raw_&g" + closure_g = newclosure sub_g + store_global '&g', closure_g $P0 = '&g'(x) .return ($P0) .end -.sub '&g' :outer('&f') +.sub 'raw_&g' :outer('&f') .param pmc y .lex '$y', y .local pmc x @@ -1023,7 +1048,7 @@ print "never\n" .end CODE -/Null PMC access/ +/Closure sub called without 'newclosure'/ OUTPUT pir_output_is(<<'CODE', <<'OUTPUT', 'package-scoped closure 5 - autoclose'); @@ -1035,9 +1060,13 @@ .sub '&f' .param pmc x .lex '$x', x + .local pmc sub_g, closure_g + .const .Sub sub_g = "raw_&g" + closure_g = newclosure sub_g + store_global '&g', closure_g .end -.sub '&g' :outer('&f') +.sub 'raw_&g' :outer('&f') .local pmc x x = find_lex '$x' print x @@ -1062,9 +1091,13 @@ .sub '&f' .param pmc x .lex '$x', x + .local pmc sub_g, closure_g + .const .Sub sub_g = "raw_&g" + closure_g = newclosure sub_g + store_global '&g', closure_g .end -.sub '&g' :outer('&f') +.sub 'raw_&g' :outer('&f') .local pmc x x = find_lex '$x' print x