Author: pmichaud
Date: Sat Jan  3 06:14:11 2009
New Revision: 34877

Modified:
   branches/rvar/languages/perl6/src/parser/actions.pm

Log:
[rakudo]:  Clean up var node handling in actions.pm a bit.


Modified: branches/rvar/languages/perl6/src/parser/actions.pm
==============================================================================
--- branches/rvar/languages/perl6/src/parser/actions.pm (original)
+++ branches/rvar/languages/perl6/src/parser/actions.pm Sat Jan  3 06:14:11 2009
@@ -1530,49 +1530,35 @@
 }
 
 method variable($/, $key) {
-    my $past;
+    my $var;
     our @?BLOCK;
     my $?BLOCK := @?BLOCK[0];
     if $key eq 'desigilname' {
-        my $sigil      := ~$<sigil>;
-        my $twigil     := ~$<twigil>[0];
-        my @identifier := Perl6::Compiler.parse_name( $<desigilname> );
-        my $name       := ~...@identifier.pop();
-        my $varname    := $sigil ~ $name;
-        $past := PAST::Var.new( :name($varname), :node($/) );
-
-        ##  if namespace qualified or has a '*' twigil, it's a package var
-        if @identifier || $twigil eq '*' {
-            $past.namespace(@identifier);
-            $past.scope('package');
-            $past.viviself( container_itype($sigil) );
-        }
+        my $sigil    := ~$<sigil>;
+        if $sigil eq '&' { $sigil := ''; }
+        my $twigil   := ~$<twigil>[0];
+        my @ns       := Perl6::Compiler.parse_name( $<desigilname> );
+        my $name     := ~...@ns.pop();
+        my $varname  := $sigil ~ $twigil ~ $name;
 
-        if $varname eq '@_' || $varname eq '%_' {
-            unless $?BLOCK.symbol($varname) {
-                $?BLOCK.symbol( $varname, :scope('lexical') );
-                my $param := PAST::Var.new( :name($varname), 
-                                            :scope('parameter'),
-                                            :slurpy(1) );
-                if $sigil eq '%' { $param.named(1); }
-                $?BLOCK[0].unshift($param);
-            }
-        }
-
-        if $sigil eq '&' {
-            $sigil := '';
-            $varname := $name;
-            $past.name($varname);
-            $past.scope('package');
+        # If no twigil, but varname is 'attribute' in outer scope,
+        # it's really a private attribute and needs a '!' twigil
+        if !$twigil {
             my $sym := outer_symbol($varname);
-            if $sym && $sym<scope> { $past.scope( $sym<scope> ); }
+            if $sym && $sym<scope> eq 'attribute' { 
+                $twigil  := '!';
+                $varname := $sigil ~ $twigil ~ $name;
+            };
         }
 
-        ##  if twigil is ^ or :, it's a placeholder var
+        # If twigil is ^ or :, it's a placeholder var.  Create the
+        # parameter for the block if one doesn't already exist.
         if $twigil eq '^' || $twigil eq ':' {
             if $?BLOCK<signature> {
                 $/.panic("Cannot use placeholder var in block with 
signature.");
             }
+            $twigil := '';
+            $varname := $sigil ~ $name;
             unless $?BLOCK.symbol($varname) {
                 $?BLOCK.symbol( $varname, :scope('lexical') );
                 $?BLOCK.arity( +$?BLOCK.arity() + 1 );
@@ -1580,7 +1566,7 @@
                 if $twigil eq ':' { $param.named( $name ); }
                 my $block := $?BLOCK[0];
                 my $i := +@($block);
-                while $i > 0 && $block[$i-1]<name> gt $varname {
+                while $i > 0 && $block[$i-1].name() gt $varname {
                     $block[$i] := $block[$i-1];
                     $i--;
                 }
@@ -1588,38 +1574,56 @@
             }
         }
 
-        ##  if no twigil, but variable is 'attribute' in an outer scope,
-        ##  it's really a private attribute
-        if !$twigil {
+        $var := PAST::Var.new( :name($varname), :node($/) );
+        if $twigil { $var<twigil> := $twigil; }
+
+        # If namespace qualified or has a '*' twigil, it's a package var.
+        if @ns || $twigil eq '*' {
+            $var.namespace(@ns);
+            $var.scope('package');
+            $var.viviself( container_itype($sigil) );
+        }
+
+        ## @_ and %_ add a slurpy param to the block
+        if $varname eq '@_' || $varname eq '%_' {
+            unless $?BLOCK.symbol($varname) {
+                $?BLOCK.symbol( $varname, :scope('lexical') );
+                my $param := PAST::Var.new( :name($varname), 
+                                            :scope('parameter'),
+                                            :slurpy(1) );
+                if $sigil eq '%' { $param.named(1); }
+                $?BLOCK[0].unshift($param);
+            }
+        }
+
+        # Until PCT has 'name' scope, we handle lexical/package lookup here.
+        if $<sigil> eq '&' {
+            $var.scope('package');
             my $sym := outer_symbol($varname);
-            if $sym && $sym<scope> eq 'attribute' { $twigil := '!' };
+            if $sym && $sym<scope> { $var.scope( $sym<scope> ); }
         }
 
-        ##  handle ! and . twigil as attribute lookup...
-        our @?IN_DECL;
+        # ! and . twigils may need 'self' for attribute lookup ...
         if $twigil eq '!' || $twigil eq '.' {
-            $varname := $sigil ~ $twigil ~ $name;
-            $past.name($varname);
-            $past.scope('attribute');
-            $past.unshift( PAST::Var.new( :name('self'), :scope('lexical') ) );
+            $var.unshift( PAST::Var.new( :name('self'), :scope('lexical') ) );
         }
 
-        ## ...but return . twigil as a method call, saving the
-        ## PAST::Var node in $past <vardecl>where it can be easily 
-        ## retrieved by <variable_declarator> if we're called from there.
+        # ...but return . twigil as a method call, saving the
+        # PAST::Var node in $var<vardecl> where it can be easily 
+        # retrieved by <variable_declarator> if we're called from there.
         if $twigil eq '.' {
-            my $var := $past;
-            $past := PAST::Op.new( :node($/), :pasttype('callmethod'),
+            my $vardecl := $var;
+            $var := PAST::Op.new( :node($/), :pasttype('callmethod'),
                 :name($name),
                 PAST::Var.new( :name('self'), :scope('lexical') )
             );
-            $past<vardecl> := $var;
+            $var<vardecl> := $vardecl;
         }
     }
     elsif $key eq 'special_variable' {
-        $past := $( $<special_variable> );
+        $var := $( $<special_variable> );
     }
-    make $past;
+    make $var;
 }
 
 

Reply via email to