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; }