From: Bob Rogers <[EMAIL PROTECTED]> Date: Wed, 9 Jul 2008 01:27:29 -0400
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. The attached patch is a band-aid that fixes this problem without reverting r28763. I believe it is a minimal conservative fix (that happens to look huge because of merging t/op/lexicals-2.t into t/op/lexicals.t). Patrick, this not only passes your original badlex.pir case, but I also successfully ran "make spectest_regression" for Rakudo on it. IMHO, this fix should go into the imminent release because it restores functionality that had been lost since the previous release. Comments? Objections? -- Bob
[CORE] Keep Closure:invoke from breaking what newclosure hath wrought. This is a band-aid that will be removed along with "autoclose." * include/parrot/sub.h: + Add SUB_FLAG_NEWCLOSURE to sub_flags_enum. * src/sub.c: + (parrot_new_closure): Mark the closures we create. * src/pmc/closure.pmc: + (invoke): Only overwrite sub->outer_ctx if not from "newclosure". * MANIFEST, t/op/lexicals-2.t (deleted), t/op/lexicals.t: + Merge lexicals-2.t into lexicals.t, remove "todo" from "RT#56398: Bob's recursion bug" case. Diffs between last version checked in and current workfile(s): Index: include/parrot/sub.h =================================================================== --- include/parrot/sub.h (revision 29359) +++ include/parrot/sub.h (working copy) @@ -36,6 +36,9 @@ SUB_FLAG_PF_IMMEDIATE = PObj_private6_FLAG, SUB_FLAG_PF_POSTCOMP = PObj_private7_FLAG, + /* [temporary expedient. -- rgr, 13-Jul-08.] */ + SUB_FLAG_NEWCLOSURE = SUB_FLAG_PF_IMMEDIATE, + SUB_FLAG_PF_MASK = 0xfa /* anon ... postcomp, is_outer*/ } sub_flags_enum; Index: src/sub.c =================================================================== --- src/sub.c (revision 29359) +++ src/sub.c (working copy) @@ -527,6 +527,9 @@ cont = ctx->current_cont; + /* mark clos_pmc as having been created by newclosure. */ + SUB_FLAG_flag_SET(NEWCLOSURE, clos_pmc); + /* preserve this frame by converting the continuation */ cont->vtable = interp->vtables[enum_class_Continuation]; Index: src/pmc/closure.pmc =================================================================== --- src/pmc/closure.pmc (revision 29359) +++ src/pmc/closure.pmc (working copy) @@ -91,9 +91,10 @@ opcode_t *next = SUPER(in_next); PMC *outer_sub = sub->outer_sub; - if (sub->ctx->caller_ctx->current_sub == outer_sub) { - /* Being called from outer sub, in which case our outer is its - * context. */ + if (! (PObj_get_FLAGS(SELF) & SUB_FLAG_NEWCLOSURE) + && sub->ctx->caller_ctx->current_sub == outer_sub) { + /* Autoclose sub being called from the :outer sub, in which case our + * outer is its context. */ sub->outer_ctx = sub->ctx->outer_ctx = PMC_sub(outer_sub)->ctx; } else if (sub->outer_ctx) { Index: MANIFEST =================================================================== --- MANIFEST (revision 29361) +++ MANIFEST (working copy) @@ -1,7 +1,7 @@ # ex: set ro: # $Id$ # -# generated by tools/dev/mk_manifest_and_skip.pl Sat Jul 12 13:47:29 2008 UT +# generated by tools/dev/mk_manifest_and_skip.pl Mon Jul 14 02:56:21 2008 UT # # See tools/dev/install_files.pl for documentation on the # format of this file. @@ -3464,7 +3464,6 @@ t/op/jit.t [] t/op/jitn.t [] t/op/lexicals.t [] -t/op/lexicals-2.t [] t/op/literal.t [] t/op/load_bytecode.t [] t/op/number.t [] Index: t/op/lexicals-2.t =================================================================== --- t/op/lexicals-2.t (revision 29360) +++ t/op/lexicals-2.t (working copy) @@ -1,200 +0,0 @@ -#!perl -# Copyright (C) 2001-2008, The Perl Foundation. -# $Id$ - -use strict; -use warnings; -use lib qw( . lib ../lib ../../lib ); - -use Test::More; -use Parrot::Test tests => 3; - -=head1 NAME - -t/op/lexicals-2.t - Lexical Ops - -=head1 SYNOPSIS - - % prove t/op/lexicals-2.t - -=head1 DESCRIPTION - -More elaborate tests of closure and lexical variable operations. -See PDD20. - -=cut - -pir_output_is( <<'CODE', <<'OUTPUT', "RT#56398: Patrick's request" ); -.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 - '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 -CODE -outer foo try 1 -inner foo try 1 -outer foo try 2 -inner foo try 2 -outer foo try 3 -inner foo try 3 -OUTPUT - -pir_output_is( <<'CODE', <<'OUTPUT', "RT#56398: Bob's recursion bug", todo => 'not working after r28763.'); -.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 - ## $P81 = clone $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 -CODE -rpwi: lex case -rpwi: recursive case -[restoring *SHARP-EQUAL-ALIST*] -[got 99] -OUTPUT - -pir_output_is( <<'CODE', <<'OUTPUT', "RT#56398: Jonathan's recursive case" ); -.sub 'main' :main - $P0 = new 'ResizablePMCArray' - push $P0, 'a' - $P1 = new 'ResizablePMCArray' - $P2 = new 'ResizablePMCArray' - push $P2, 'simple' - push $P1, $P2 - push $P1, 'test' - $P3 = new 'ResizablePMCArray' - push $P3, 'for' - push $P3, 'a' - push $P3, 'simple' - push $P1, $P3 - push $P0, $P1 - push $P0, 'script' - 'dump_thing'($P0, '# ') -.end - -.sub 'dump_thing' - .param pmc thing - .param pmc prefix - .lex '$thing', thing - .lex '$prefix', prefix - - $P0 = find_global 'anon_1' - $P1 = newclosure $P0 - .lex '$recur', $P1 - - $P2 = find_lex '$thing' - $I0 = isa $P2, 'ResizablePMCArray' - unless $I0 goto not_ResizablePMCArray - - $P3 = find_lex '$prefix' - print $P3 - print "[\n" - $P4 = find_global 'anon_2' - $P5 = newclosure $P4 - $P6 = find_lex '$thing' - 'map'($P5, $P6) - $P7 = find_lex '$prefix' - print $P7 - print "]\n" - goto end_if - - not_ResizablePMCArray: - $P8 = find_lex '$prefix' - print $P8 - $P9 = find_lex '$thing' - print $P9 - print "\n" - end_if: -.end - -.sub 'anon_1' :outer('dump_thing') - .param pmc subthing - .lex '$subthing', subthing - $P0 = find_lex '$subthing' - $P1 = find_lex '$prefix' - $P2 = new 'String' - $P2 = concat $P1, ' ' - 'dump_thing'($P0, $P2) -.end - -.sub 'anon_2' :outer('dump_thing') - .param pmc topic - .lex "$_", topic - $P0 = find_lex '$recur' - $P1 = find_lex '$_' - $P0($P1) -.end - -.sub 'map' - .param pmc block - .param pmc array - .local pmc result, it - result = new 'ResizablePMCArray' - it = iter array - loop: - unless it goto loop_end - $P0 = shift it - $P0 = block($P0) - push result, $P0 - goto loop - loop_end: - .return (result) -.end -CODE -# [ -# a -# [ -# [ -# simple -# ] -# test -# [ -# for -# a -# simple -# ] -# ] -# script -# ] -OUTPUT Index: t/op/lexicals.t =================================================================== --- t/op/lexicals.t (revision 29359) +++ t/op/lexicals.t (working copy) @@ -7,7 +7,7 @@ use lib qw( . lib ../lib ../../lib ); use Test::More; -use Parrot::Test tests => 44; +use Parrot::Test tests => 47; =head1 NAME @@ -1282,6 +1282,181 @@ hello world OUTPUT +pir_output_is( <<'CODE', <<'OUTPUT', "RT#56398: Patrick's request" ); +.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 + '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 +CODE +outer foo try 1 +inner foo try 1 +outer foo try 2 +inner foo try 2 +outer foo try 3 +inner foo try 3 +OUTPUT + +pir_output_is( <<'CODE', <<'OUTPUT', "RT#56398: Bob's recursion bug"); +.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 + ## $P81 = clone $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 +CODE +rpwi: lex case +rpwi: recursive case +[restoring *SHARP-EQUAL-ALIST*] +[got 99] +OUTPUT + +pir_output_is( <<'CODE', <<'OUTPUT', "RT#56398: Jonathan's recursive case" ); +.sub 'main' :main + $P0 = new 'ResizablePMCArray' + push $P0, 'a' + $P1 = new 'ResizablePMCArray' + $P2 = new 'ResizablePMCArray' + push $P2, 'simple' + push $P1, $P2 + push $P1, 'test' + $P3 = new 'ResizablePMCArray' + push $P3, 'for' + push $P3, 'a' + push $P3, 'simple' + push $P1, $P3 + push $P0, $P1 + push $P0, 'script' + 'dump_thing'($P0, '# ') +.end + +.sub 'dump_thing' + .param pmc thing + .param pmc prefix + .lex '$thing', thing + .lex '$prefix', prefix + + $P0 = find_global 'anon_1' + $P1 = newclosure $P0 + .lex '$recur', $P1 + + $P2 = find_lex '$thing' + $I0 = isa $P2, 'ResizablePMCArray' + unless $I0 goto not_ResizablePMCArray + + $P3 = find_lex '$prefix' + print $P3 + print "[\n" + $P4 = find_global 'anon_2' + $P5 = newclosure $P4 + $P6 = find_lex '$thing' + 'map'($P5, $P6) + $P7 = find_lex '$prefix' + print $P7 + print "]\n" + goto end_if + + not_ResizablePMCArray: + $P8 = find_lex '$prefix' + print $P8 + $P9 = find_lex '$thing' + print $P9 + print "\n" + end_if: +.end + +.sub 'anon_1' :outer('dump_thing') + .param pmc subthing + .lex '$subthing', subthing + $P0 = find_lex '$subthing' + $P1 = find_lex '$prefix' + $P2 = new 'String' + $P2 = concat $P1, ' ' + 'dump_thing'($P0, $P2) +.end + +.sub 'anon_2' :outer('dump_thing') + .param pmc topic + .lex "$_", topic + $P0 = find_lex '$recur' + $P1 = find_lex '$_' + $P0($P1) +.end + +.sub 'map' + .param pmc block + .param pmc array + .local pmc result, it + result = new 'ResizablePMCArray' + it = iter array + loop: + unless it goto loop_end + $P0 = shift it + $P0 = block($P0) + push result, $P0 + goto loop + loop_end: + .return (result) +.end +CODE +# [ +# a +# [ +# [ +# simple +# ] +# test +# [ +# for +# a +# simple +# ] +# ] +# script +# ] +OUTPUT + # Local Variables: # mode: cperl # cperl-indent-level: 4 End of diffs.