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.

Reply via email to