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