From: "[EMAIL PROTECTED] via RT" <[EMAIL PROTECTED]> Date: Fri, 27 Jun 2008 16:12:13 -0700
Fixed in r28763. Thanks, Jonathan Oops; r28763 seems to be the source of one of my problems, a "lexical not found" error. With this change, Parrot gets confused when multiple calls to the :outer sub have been made, such as when it is recursive. In the first place, I would claim that the test case is at fault. In badlex.pir, each call to "foo" makes a call to "inner", but it calls the named sub directly. This is always the same Closure object, and it captures only the initial call (as Patrick observed); this is the "autoclose" feature [1]. The Closure:invoke change gives priority to new calls to the outer sub, overwriting whatever context newclosure may have captured. What "foo" should do is create a closure and call that: .const .Sub inner = 'inner' inner = newclosure inner inner() The attached "goodlex.pir" case demonstrates this, and works as Patrick intends, before and after r28763. If you also did store_hll_global 'inner', inner to put the new closure back in the namespace, that would be fully transparent to any other callers of inner (hack, cough, gasp). In the second place, recursive calls do mess up even closures created with "newclosure". The recursive-lex.pir attachment illustrates the problem. With the recursive "rpwi(1)" call commented out, the cleanup sub runs normally: [EMAIL PROTECTED]> /usr/src/parrot/parrot recursive-lex.pir rpwi: lex case [restoring *SHARP-EQUAL-ALIST*] [got 99] [EMAIL PROTECTED]> (The cleanup sub was originally invoked via pushaction, but that isn't necessary.) With the recursive call, the closure we made with the outer recursive context gets overwritten with the inner context, in which the lexical variable isn't initialized, and so the cleanup fails: [EMAIL PROTECTED]> /usr/src/parrot/parrot recursive-lex.pir rpwi: lex case rpwi: recursive case [restoring *SHARP-EQUAL-ALIST*] [got Null PMC access in get_string() current instr.: '(:INTERNAL rpwi 0)' pc 64 (recursive-lex.pir:27) called from Sub 'rpwi' pc 52 (recursive-lex.pir:20) called from Sub 'main' pc 8 (recursive-lex.pir:3) [EMAIL PROTECTED]> It may be possible to rescue Patrick's desired behavior by keeping track of whether the outer_sub was initialized by newclosure or not. Personally, I'd prefer if it were always an error to call a closure sub directly; implicitly initializing the outer context is bad enough, but re-initializing it is worse. (But we've had this discussion before [1], and I was not persuasive.) -- Bob Rogers http://rgrjr.dyndns.org/ [1] http://groups.google.com/group/perl.perl6.internals/browse_thread/thread/41dbfee7b7b5bbe7
.sub 'main' :main foo('try 1') foo('try 2') foo('try 3') .end .sub 'foo' :lexid('foo') .param pmc x .lex '$x', x print "outer foo " say x .const .Sub inner = 'inner' inner = newclosure inner inner() .end .sub 'inner' :outer('foo') .local pmc x x = find_lex '$x' print "inner foo " say x $P0 = new 'String' $P0 = 'BOGUS!' store_lex '$x', $P0 .end
.sub main :main rpwi(0) .end .sub rpwi .param int recursive_p unless recursive_p goto do_lex print "rpwi: recursive case\n" .return () do_lex: .lex "(SAVED *SHARP-EQUAL-ALIST*)", $P40 $P40 = new 'Integer' $P40 = 99 .const .Sub $P80 = "(:INTERNAL rpwi 0)" newclosure $P81, $P80 ## pushaction $P81 print "rpwi: lex case\n" rpwi(1) $P81() .end .sub "(:INTERNAL rpwi 0)" :anon :outer('rpwi') print "[restoring *SHARP-EQUAL-ALIST*]\n" find_lex $P40, "(SAVED *SHARP-EQUAL-ALIST*)" print "[got " print $P40 print "]\n" .end