Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RakuAST: implement for { } otherwise { } #5390

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/Raku/Actions.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,21 @@ class Raku::Actions is HLL::Actions does Raku::CommonActions {
);
}

# Handling of for / otherwise
method statement-control:sym<for>($/) {
self.attach: $/, Nodify('Statement','For').new(
source => $<EXPR>.ast,
body => $<pointy-block>.ast,
otherwise => $<otherwise> ?? $<otherwise>.ast !! Mu
);
}

# Handling of simple control statements that take a block
method statement-control:sym<default>($/) { self.takes-none($/,'Default') }
method statement-control:sym<CATCH>($/) { self.takes-none($/,'Catch') }
method statement-control:sym<CONTROL>($/) { self.takes-none($/,'Control') }

# Handling of simple control statements that take a pointy block
method statement-control:sym<for>($/) { self.takes-source($/,'For') }
method statement-control:sym<given>($/) { self.takes-source($/,'Given') }
method statement-control:sym<unless>($/) { self.takes-cond($/,'Unless') }
method statement-control:sym<when>($/) { self.takes-cond($/,'When') }
Expand Down
1 change: 1 addition & 0 deletions src/Raku/Grammar.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,7 @@ grammar Raku::Grammar is HLL::Grammar does Raku::Common {
:my $*BORG := {};
<EXPR>
<pointy-block>
[ otherwise $<otherwise>=<.pointy-block> ]?
}

# Handle repeat ... while | until
Expand Down
41 changes: 34 additions & 7 deletions src/Raku/ast/statements.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -1056,14 +1056,23 @@ class RakuAST::Statement::For
# The body of the loop.
has RakuAST::Block $.body;

# The block to run if nothing to iterate over
has RakuAST::Block $.otherwise;

# The mode of evaluation, (defaults to serial, may be race or hyper also).
has str $.mode;

method new(RakuAST::Expression :$source!, RakuAST::Block :$body!, str :$mode,
List :$labels) {
method new(
RakuAST::Expression :$source!,
RakuAST::Block :$body!,
RakuAST::Block :$otherwise,
str :$mode,
List :$labels
) {
my $obj := nqp::create(self);
nqp::bindattr($obj, RakuAST::Statement::For, '$!source', $source);
nqp::bindattr($obj, RakuAST::Statement::For, '$!body', $body);
nqp::bindattr($obj, RakuAST::Statement::For, '$!otherwise', $otherwise);
nqp::bindattr_s($obj, RakuAST::Statement::For, '$!mode', $mode || 'serial');
$obj.set-labels($labels);
$obj
Expand Down Expand Up @@ -1091,7 +1100,11 @@ class RakuAST::Statement::For
# Figure out the execution mode modifiers to apply.
my str $mode := $!mode;
my str $after-mode := '';
if $mode eq 'lazy' {
if $!otherwise {
$mode := 'serial';
$after-mode := 'eager';
}
elsif $mode eq 'lazy' {
$mode := 'serial';
$after-mode := 'lazy';
}
Expand All @@ -1103,16 +1116,30 @@ class RakuAST::Statement::For
# attributes to in order to make it callable for the statement modifier
# form also).
my @labels := self.IMPL-UNWRAP-LIST(self.labels);
self.IMPL-FOR-QAST($context, $mode, $after-mode,
$!source.IMPL-TO-QAST($context),
$!body.IMPL-TO-QAST($context),
@labels ?? @labels[0] !! RakuAST::Label)
my $qast := self.IMPL-FOR-QAST(
$context,
$mode,
$after-mode,
$!source.IMPL-TO-QAST($context),
$!body.IMPL-TO-QAST($context),
@labels ?? @labels[0] !! RakuAST::Label
);

$!otherwise
?? QAST::Op.new(:op<unless>,
$qast,
QAST::Op.new(:op<call>,
$!otherwise.IMPL-TO-QAST($context)
)
)
!! $qast
}


method visit-children(Code $visitor) {
$visitor($!source);
$visitor($!body);
$visitor($!otherwise) if $!otherwise;
self.visit-labels($visitor);
}
}
Expand Down