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

Reply via email to