Author: pmichaud
Date: Sun Nov 30 18:52:03 2008
New Revision: 33396

Modified:
   trunk/languages/perl6/src/builtins/guts.pir
   trunk/languages/perl6/src/parser/actions.pm

Log:
[rakudo]: !OUTER doesn't work for bare closures, so refactor implicit lexicals 
to avoid it.


Modified: trunk/languages/perl6/src/builtins/guts.pir
==============================================================================
--- trunk/languages/perl6/src/builtins/guts.pir (original)
+++ trunk/languages/perl6/src/builtins/guts.pir Sun Nov 30 18:52:03 2008
@@ -58,54 +58,6 @@
 .end
 
 
-=item !OUTER(name [,'max'=>max])
-
-Helper function to obtain the lexical C<name> from the
-caller's outer scope.  (Note that it never finds a lexical
-in the caller's lexpad -- use C<find_lex> for that.)  The
-C<max> parameter specifies the maximum outer to search --
-the default value of 1 will search the caller's immediate
-outer scope and no farther.  If the requested lexical is
-not found, C<!OUTER> returns null.
-
-=cut
-
-.sub '!OUTER'
-    .param string name
-    .param int max             :named('max') :optional
-    .param int has_max         :opt_flag
-
-    if has_max goto have_max
-    max = 1
-  have_max:
-
-    .local int min
-    min = 1
-
-    ##  the depth we use here is one more than the minimum,
-    ##  because we want min/max to be relative to the caller's
-    ##  context, not !OUTER itself.
-    .local int depth
-    depth = min + 1
-    .local pmc lexpad, value
-    $P0 = getinterp
-    null value
-  loop:
-    lexpad = $P0['lexpad', depth]
-    if null lexpad goto next
-    value = lexpad[name]
-    unless null value goto done
-  next:
-    # depth goes from min + 1 to max + 1
-    if depth > max goto done
-    inc depth
-    goto loop
-  done:
-  outer_err:
-    .return (value)
-.end
-
-
 =item !VAR
 
 Helper function for implementing the VAR and .VAR macros.

Modified: trunk/languages/perl6/src/parser/actions.pm
==============================================================================
--- trunk/languages/perl6/src/parser/actions.pm (original)
+++ trunk/languages/perl6/src/parser/actions.pm Sun Nov 30 18:52:03 2008
@@ -6,9 +6,7 @@
 method TOP($/) {
     my $past := $( $<statement_block> );
     $past.blocktype('declaration');
-    declare_implicit_var($past, '$_', 'new');
-    declare_implicit_var($past, '$!', 'new');
-    declare_implicit_var($past, '$/', 'new');
+    declare_implicit_routine_vars($past);
 
     # Attach any initialization code.
     our $?INIT;
@@ -208,12 +206,12 @@
 method if_statement($/) {
     my $count := +$<xblock> - 1;
     my $past  := $( $<xblock>[$count] );
-    declare_implicit_immediate_vars( $past[1] );
+    declare_implicit_block_vars($past[1], 0);
     ## add any 'else' clause
     if $<pblock> {
         my $else := $( $<pblock>[0] );
         $else.blocktype('immediate');
-        declare_implicit_immediate_vars($else);
+        declare_implicit_block_vars($else, 0);
         $past.push( $else );
     }
     ## build if/then/elsif structure
@@ -221,7 +219,7 @@
         $count--;
         my $else := $past;
         $past := $( $<xblock>[$count] );
-        declare_implicit_immediate_vars( $past[1] );
+        declare_implicit_block_vars($past[1], 0);
         $past.push($else);
     }
     make $past;
@@ -230,14 +228,14 @@
 method unless_statement($/) {
     my $past := $( $<xblock> );
     $past.pasttype('unless');
-    declare_implicit_immediate_vars( $past[1] );
+    declare_implicit_block_vars($past[1], 0);
     make $past;
 }
 
 method while_statement($/) {
     my $past := $( $<xblock> );
     $past.pasttype(~$<sym>);
-    declare_implicit_immediate_vars( $past[1] );
+    declare_implicit_block_vars($past[1], 0);
     make $past;
 }
 
@@ -365,6 +363,7 @@
 method begin_statement($/) {
     my $past := $( $<block> );
     $past.blocktype('declaration');
+    declare_implicit_routine_vars($past);                  # FIXME
     my $sub := PAST::Compiler.compile( $past );
     $sub();
     # XXX - should emit BEGIN side-effects, and do a proper return()
@@ -374,6 +373,7 @@
 method end_statement($/) {
     my $past := $( $<block> );
     $past.blocktype('declaration');
+    declare_implicit_routine_vars($past);                  # FIXME
     my $sub := PAST::Compiler.compile( $past );
     PIR q<  $P0 = get_hll_global ['Perl6'], '@?END_BLOCKS' >;
     PIR q<  $P1 = find_lex '$sub' >;
@@ -575,9 +575,7 @@
     }
     $past.node($/);
     if (+@($past[1])) {
-        declare_implicit_var($past, '$_', 'new');
-        declare_implicit_var($past, '$!', 'new');
-        declare_implicit_var($past, '$/', 'new');
+        declare_implicit_routine_vars($past);
     }
     else {
         $past[1].push( PAST::Op.new( :name('list') ) );
@@ -3162,41 +3160,44 @@
 }
 
 
-sub declare_implicit_var($block, $name, $type) {
-    unless $block.symbol($name) {
-        my $var := PAST::Var.new( :name($name), :isdecl(1) );
-        $var.scope($type eq 'parameter' ?? 'parameter' !! 'lexical');
-        if $type eq 'new' {
-            $var.viviself( 'Perl6Scalar' );
+sub declare_implicit_routine_vars($block) {
+    for ('$_', '$/', '$!') {
+        unless $block.symbol($_) {
+            $block[0].push( PAST::Var.new( :name($_), 
+                                           :scope('lexical'),
+                                           :isdecl(1),
+                                           :viviself('Perl6Scalar') ) );
+            $block.symbol($_, :scope('lexical') );
         }
-        else {
-            my $opast := PAST::Op.new(
-                :name('!OUTER'),
-                PAST::Val.new( :value($name) )
-            );
-            $var.viviself($opast);
-        }
-        $block[0].push($var);
-        $block.symbol($name, :scope('lexical') );
     }
 }
 
 
-sub declare_implicit_function_vars($block) {
-    declare_implicit_var($block, '$_',
-        defined($block.arity()) ?? 'outer' !! 'parameter');
-    declare_implicit_var($block, '$!', 'outer');
-    declare_implicit_var($block, '$/', 'outer');
+sub declare_implicit_block_vars($block, $tparam) {
+    $block[0].push( PAST::Op.new(
+                        :inline('    .local pmc outerlex',
+                                '    getinterp $P0',
+                                '    set outerlex, $P0["outer";"lexpad";1]')));
+    for ('$_', '$/', '$!') {
+        unless $block.symbol($_) {
+            my $lex := PAST::Op.new(:inline('    set %r, outerlex[%0]'), $_);
+            my $scope := ($tparam && $_ eq '$_') ?? 'parameter' !! 'lexical';
+            $block[0].push( 
+                PAST::Var.new( :name($_),
+                               :scope($scope),
+                               :isdecl(1),
+                               :viviself($lex)
+                )
+            );
+            $block.symbol($_, :scope('lexical') );
+        }
+    }
 }
 
-
-sub declare_implicit_immediate_vars($block) {
-    declare_implicit_var($block, '$_', 'outer');
-    declare_implicit_var($block, '$!', 'outer');
-    declare_implicit_var($block, '$/', 'outer');
+sub declare_implicit_function_vars($block) {
+    declare_implicit_block_vars($block, !defined($block.arity()));
 }
 
-
 sub contextualizer_name($/, $sigil) {
     ##  Contextualizing is calling .item, .list, .hash, etc.
     ##  on the expression in the brackets

Reply via email to