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