Skip to content

Commit

Permalink
Modernize R:It.NextNValues
Browse files Browse the repository at this point in the history
- use fewer nqp ops
- one less scalar allocation per instance
- apply contract that it should not be called again after an IterationEnd
- add push-all for those cases where a .STORE is done, e.g. @A = Seq.head(5)
  • Loading branch information
lizmat committed Jun 7, 2020
1 parent a9796fe commit 98dec90
Showing 1 changed file with 32 additions and 42 deletions.
74 changes: 32 additions & 42 deletions src/core.c/Rakudo/Iterator.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -3017,52 +3017,42 @@ class Rakudo::Iterator {
my class NextNValues does Iterator {
has $!iterator;
has int $!times;
method !SET-SELF($!iterator,$!times) { self }
method new(\iterator,\times) {
nqp::if(
nqp::istype(times,Whatever),
iterator, # * just give back itself
nqp::if(
times <= 0, # must be HLL comparison
Rakudo::Iterator.Empty, # negative is just nothing
nqp::if(
nqp::istype(times,Int),
nqp::if(
nqp::isbig_I(nqp::decont(times)),
iterator, # big value = itself
nqp::create(self)!SET-SELF(iterator,times)
),
nqp::if(
times == Inf, # big value = itself
iterator,
nqp::create(self)!SET-SELF(iterator,times.Int)
)
)
)
)
method !SET-SELF(\iterator, int $times) {
$!iterator := iterator;
$!times = nqp::add_i($times,1);
self
}
method new(\iterator, \times) {
nqp::istype(times,Whatever)
?? iterator # * just give back itself
!! times <= 0 # must be HLL comparison
?? Rakudo::Iterator.Empty # negative is just nothing
!! nqp::istype(times,Int)
?? nqp::isbig_I(nqp::decont(times))
?? iterator # big value = itself
!! nqp::create(self)!SET-SELF(iterator,times)
!! times == Inf # big value = itself
?? iterator
!! nqp::create(self)!SET-SELF(iterator,times.Int)
}
method pull-one() is raw {
nqp::if(
nqp::isgt_i($!times,0),
nqp::if(
nqp::eqaddr(
(my \pulled := $!iterator.pull-one),
IterationEnd
),
nqp::stmts(
($!times = 0),
IterationEnd
),
nqp::stmts(
($!times = nqp::sub_i($!times,1)),
pulled
)
),
IterationEnd
)
($!times = nqp::sub_i($!times,1))
?? nqp::eqaddr((my \pulled := $!iterator.pull-one),IterationEnd)
?? IterationEnd
!! pulled
!! IterationEnd
}
method push-all(\target --> IterationEnd) {
my $iterator := $!iterator;
my int $times = $!times;
nqp::until(
nqp::not_i($times = nqp::sub_i($times,1))
|| nqp::eqaddr((my \pulled := $iterator.pull-one),IterationEnd),
target.push(pulled)
);
}
}
method NextNValues(\iterator,\times) { NextNValues.new(iterator,times) }
method NextNValues(\iterator, \times) { NextNValues.new(iterator, times) }

# Return an iterator that only will return the given value once.
# Basically the same as 42 xx 1.
Expand Down

0 comments on commit 98dec90

Please sign in to comment.