Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement temp and let. Passes all of let.t and all the temp.t tests …
…apart from those that depend on TEMP phaser, which is still NYI.
  • Loading branch information
jnthn committed May 6, 2012
1 parent dbcdb16 commit 973df80
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/Perl6/Grammar.pm
Expand Up @@ -2533,7 +2533,9 @@ grammar Perl6::Grammar is HLL::Grammar {
token infix:sym<|> { <sym> <O('%junctive_or')> }
token infix:sym<^> { <sym> <O('%junctive_or')> }

token prefix:sym<abs> { <sym> » <O('%named_unary')> }
token prefix:sym<abs> { <sym> » <O('%named_unary')> }
token prefix:sym<let> { <sym> \s+ <!before '=>'> <O('%named_unary')> { $*W.give_cur_block_let($/) } }
token prefix:sym<temp> { <sym> \s+ <!before '=>'> <O('%named_unary')> { $*W.give_cur_block_temp($/) } }

token infix:sym«==» { <sym> <O('%chaining')> }
token infix:sym«!=» { <sym> <?before \s|']'> <O('%chaining')> }
Expand Down
45 changes: 45 additions & 0 deletions src/Perl6/World.pm
Expand Up @@ -789,6 +789,51 @@ class Perl6::World is HLL::World {
}
}

# Gives the current block what's needed for "let"/"temp" support.
method give_cur_block_let($/) {
my $block := self.cur_lexpad();
unless $block.symbol('!LET-RESTORE') {
self.setup_let_or_temp($/, '!LET-RESTORE', 'UNDO');
}
}
method give_cur_block_temp($/) {
my $block := self.cur_lexpad();
unless $block.symbol('!TEMP-RESTORE') {
self.setup_let_or_temp($/, '!TEMP-RESTORE', 'LEAVE');
}
}
method setup_let_or_temp($/, $value_stash, $phaser) {
# Add variable to current block.
my $block := self.cur_lexpad();
$block[0].push(PAST::Op.new(
:pasttype('bind'),
PAST::Var.new( :name($value_stash), :scope('lexical_6model'), :isdecl(1) ),
PAST::Op.new( :pasttype('list') )));
$block.symbol($value_stash, :scope('lexical_6model'));

# Create a phasser block that will do the restoration.
my $phaser_block := self.push_lexpad($/);
self.pop_lexpad();
$phaser_block.push(PAST::Op.new(
:pasttype('while'),
PAST::Var.new( :name($value_stash), :scope('lexical_6model') ),
PAST::Op.new(
:pirop('perl6_container_store__0PP'),
PAST::Op.new(
:pirop('shift__PP'),
PAST::Var.new( :name($value_stash), :scope('lexical_6model') )
),
PAST::Op.new(
:pirop('shift__PP'),
PAST::Var.new( :name($value_stash), :scope('lexical_6model') )
))));

# Add as phaser.
$block[0].push($phaser_block);
self.add_phaser($/, $phaser,
self.create_code_object($phaser_block, 'Code', self.create_signature([])));
}

# Adds a multi candidate to a proto/dispatch.
method add_dispatchee_to_proto($proto, $candidate) {
$proto.add_dispatchee($candidate);
Expand Down
40 changes: 40 additions & 0 deletions src/core/operators.pm
Expand Up @@ -211,6 +211,46 @@ sub infix:<^ff^>($a as Bool, $b as Bool) {
}
}

sub prefix:<temp>(\$cont) is rw {
my $temp_restore := pir::find_caller_lex__Ps('!TEMP-RESTORE');
if nqp::iscont($cont) {
nqp::push($temp_restore, $cont);
nqp::push($temp_restore, nqp::p6decont($cont));
}
elsif nqp::istype($cont, Array) {
nqp::push($temp_restore, $cont);
nqp::push($temp_restore, my @a = $cont);
}
elsif nqp::istype($cont, Hash) {
nqp::push($temp_restore, $cont);
nqp::push($temp_restore, my %h = $cont);
}
else {
die "Can only use 'temp' on a container";
}
$cont
}

sub prefix:<let>(\$cont) is rw {
my $let_restore := pir::find_caller_lex__Ps('!LET-RESTORE');
if nqp::iscont($cont) {
nqp::push($let_restore, $cont);
nqp::push($let_restore, nqp::p6decont($cont));
}
elsif nqp::istype($cont, Array) {
nqp::push($let_restore, $cont);
nqp::push($let_restore, my @a = $cont);
}
elsif nqp::istype($cont, Hash) {
nqp::push($let_restore, $cont);
nqp::push($let_restore, my %h = $cont);
}
else {
die "Can only use 'let' on a container";
}
$cont
}

# not sure where this should go
# this implements the ::() indirect lookup
sub INDIRECT_NAME_LOOKUP($root, *@chunks) is rw {
Expand Down

0 comments on commit 973df80

Please sign in to comment.