Skip to content

Commit

Permalink
Merge pull request #3623 from usev6/issue3622_label_for_nqp-handle
Browse files Browse the repository at this point in the history
Add missing label support for some loop constructs
  • Loading branch information
lizmat committed Apr 17, 2020
2 parents 717b326 + 66a2250 commit 77b7e0c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 28 deletions.
10 changes: 9 additions & 1 deletion src/Perl6/Actions.nqp
Expand Up @@ -157,10 +157,18 @@ sub wanted($ast,$by) {
$block := Perl6::Actions::make_thunk_ref($body, $body.node);
$block-closure := block_closure($block);
}

# make sure from-loop knows about existing label
my $label := QAST::WVal.new( :value($*W.find_symbol(['Any'])), :named('label') );
for @($ast) {
$label := $_ if nqp::istype($_, QAST::WVal) && nqp::istype($_.value, $*W.find_symbol(['Label']));
}

my $past := QAST::Op.new: :node($body.node),
:op<callmethod>, :name<from-loop>,
QAST::WVal.new(:value($*W.find_symbol(['Seq']))),
$block-closure;
$block-closure,
$label;

# Elevate statevars to enclosing thunk
if $body.has_ann('has_statevar') && $block.has_ann('past_block') {
Expand Down
57 changes: 39 additions & 18 deletions src/core.c/Rakudo/Iterator.pm6
Expand Up @@ -1404,25 +1404,28 @@ class Rakudo::Iterator {
)
}

# Returns an iterator that handles all properties of a -while- with
# Returns an iterator that handles all properties of a C-style loop with
# a condition. Takes a Callable to be considered the body of the loop,
# and a Callable for the condition..
# another Callable for the condition, and a third Callable to be executed
# after each iteration.
my class CStyleLoop does SlippyIterator {
has &!body;
has &!cond;
has &!afterwards;
has $!label;
has int $!seen-first;

method !SET-SELF(\body,\cond,\afterwards) {
method !SET-SELF(\body,\cond,\afterwards,\label) {
nqp::stmts(
(&!body := body),
(&!cond := cond),
(&!afterwards := afterwards),
($!label := nqp::decont(label)),
self
)
}
method new(\body,\cond,\afterwards) {
nqp::create(self)!SET-SELF(body,cond,afterwards)
method new(\body,\cond,\afterwards,\label) {
nqp::create(self)!SET-SELF(body,cond,afterwards,label)
}

method pull-one() {
Expand Down Expand Up @@ -1459,6 +1462,7 @@ class Rakudo::Iterator {
)
)
),
'LABELED', $!label,
'NEXT', nqp::stmts(
&!afterwards(),
($stopped = nqp::if(&!cond(),0,1))
Expand All @@ -1477,8 +1481,8 @@ class Rakudo::Iterator {
}
}
}
method CStyleLoop(&body,&cond,&afterwards) {
CStyleLoop.new(&body,&cond,&afterwards)
method CStyleLoop(&body,&cond,&afterwards,:$label) {
CStyleLoop.new(&body,&cond,&afterwards,$label)
}

my role DelegateCountOnly[\iter] does PredictiveIterator {
Expand Down Expand Up @@ -2329,9 +2333,18 @@ class Rakudo::Iterator {
# Takes a Callable to be considered the body of the loop.
my class Loop does SlippyIterator {
has &!body;
has $!label;

method new(&body) {
nqp::p6bindattrinvres(nqp::create(self),self,'&!body',&body)
method !SET-SELF(\body,\label) {
nqp::stmts(
(&!body := body),
($!label := nqp::decont(label)),
self
)
}

method new(\body,\label) {
nqp::create(self)!SET-SELF(body,label)
}

method pull-one() {
Expand All @@ -2355,6 +2368,7 @@ class Rakudo::Iterator {
IterationEnd
))
),
'LABELED', $!label,
'NEXT', ($stopped = 0),
'REDO', ($stopped = 0),
'LAST', ($result := IterationEnd)
Expand All @@ -2369,7 +2383,7 @@ class Rakudo::Iterator {

method is-lazy(--> True) { }
}
method Loop(&body) { Loop.new(&body) }
method Loop(&body,:$label) { Loop.new(&body,$label) }

# An often occurring use of the Mappy role to generate all of the
# keys of a Map / Hash. Takes a Map / Hash as the only parameter.
Expand Down Expand Up @@ -2984,18 +2998,20 @@ class Rakudo::Iterator {
my class RepeatLoop does SlippyIterator {
has $!body;
has $!cond;
has $!label;
has int $!skip;

method !SET-SELF(\body,\cond) {
method !SET-SELF(\body,\cond,\label) {
nqp::stmts(
($!body := body),
($!cond := cond),
($!label := nqp::decont(label)),
($!skip = 1),
self
)
}
method new(\body,\cond) {
nqp::create(self)!SET-SELF(body,cond)
method new(\body,\cond,\label) {
nqp::create(self)!SET-SELF(body,cond,label)
}

method pull-one() {
Expand All @@ -3021,6 +3037,7 @@ class Rakudo::Iterator {
IterationEnd
) && nqp::if($!cond(),0,1))
),
'LABELED', $!label,
'NEXT', ($stopped = nqp::if($!cond(),0,1)),
'REDO', ($stopped = 0),
'LAST', ($result := IterationEnd)
Expand All @@ -3035,7 +3052,7 @@ class Rakudo::Iterator {
}
}
}
method RepeatLoop(&body, &cond) { RepeatLoop.new(&body,&cond) }
method RepeatLoop(&body, &cond, :$label) { RepeatLoop.new(&body,&cond,$label) }

# Return an iterator that rotorizes the given iterator with the
# given cycle. If the cycle is a Cool, then it is assumed to
Expand Down Expand Up @@ -3926,16 +3943,18 @@ class Rakudo::Iterator {
my class WhileLoop does SlippyIterator {
has $!body;
has $!cond;
has $!label;

method !SET-SELF(\body,\cond) {
method !SET-SELF(\body,\cond,\label) {
nqp::stmts(
($!body := body),
($!cond := cond),
($!label := nqp::decont(label)),
self
)
}
method new(\body,\cond) {
nqp::create(self)!SET-SELF(body,cond)
method new(\body,\cond,\label) {
nqp::create(self)!SET-SELF(body,cond,label)
}

method pull-one() {
Expand All @@ -3960,6 +3979,7 @@ class Rakudo::Iterator {
IterationEnd
) && nqp::if($!cond(),0,1))
),
'LABELED', $!label,
'NEXT', ($stopped = nqp::if($!cond(),0,1)),
'REDO', ($stopped = 0),
'LAST', ($result := IterationEnd)
Expand All @@ -3973,8 +3993,9 @@ class Rakudo::Iterator {
)
}
}

}
method WhileLoop(&body, &cond) { WhileLoop.new(&body,&cond) }
method WhileLoop(&body, &cond, :$label) { WhileLoop.new(&body,&cond,$label) }

# Return an iterator that will zip the given iterables (with &[,])
# Basically the functionality of @a Z @b
Expand Down
18 changes: 9 additions & 9 deletions src/core.c/Seq.pm6
Expand Up @@ -125,20 +125,20 @@ my class Seq is Cool does Iterable does Sequence {
}

proto method from-loop(|) {*}
multi method from-loop(&body) {
Seq.new(Rakudo::Iterator.Loop(&body))
multi method from-loop(&body, :$label) {
Seq.new(Rakudo::Iterator.Loop(&body, :$label))
}
multi method from-loop(&body, &cond, :$repeat!) {
multi method from-loop(&body, &cond, :$repeat!, :$label) {
Seq.new($repeat
?? Rakudo::Iterator.RepeatLoop(&body, &cond)
!! Rakudo::Iterator.WhileLoop(&body, &cond)
?? Rakudo::Iterator.RepeatLoop(&body, &cond, :$label)
!! Rakudo::Iterator.WhileLoop(&body, &cond, :$label)
)
}
multi method from-loop(&body, &cond) {
Seq.new(Rakudo::Iterator.WhileLoop(&body, &cond))
multi method from-loop(&body, &cond, :$label) {
Seq.new(Rakudo::Iterator.WhileLoop(&body, &cond, :$label))
}
multi method from-loop(&body, &cond, &afterwards) {
Seq.new(Rakudo::Iterator.CStyleLoop(&body, &cond, &afterwards))
multi method from-loop(&body, &cond, &afterwards, :$label) {
Seq.new(Rakudo::Iterator.CStyleLoop(&body, &cond, &afterwards, :$label))
}

multi method ACCEPTS(Seq:D: Iterable:D \iterable --> Bool:D) {
Expand Down

0 comments on commit 77b7e0c

Please sign in to comment.