Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix nested for-loop side-effects in sink context.
  • Loading branch information
jnthn committed Dec 9, 2012
1 parent 469768f commit d4bf9e4
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/core/List.pm
Expand Up @@ -97,14 +97,14 @@ my class List does Positional {
nqp::p6bool(nqp::existspos($!items, nqp::unbox_i(pos)))
}

method gimme($n) {
method gimme($n, :$sink) {
# loop through iterators until we have at least $n elements
my int $count = nqp::elems(nqp::p6listitems(self));
my $eager = nqp::p6bool(nqp::istype($n, Whatever) || $n == $Inf);
while $!nextiter.defined && ($eager
?? !$!nextiter.infinite
!! ($count < $n)) {
$!nextiter.reify($eager ?? Whatever !! $n - $count);
$!nextiter.reify($eager ?? Whatever !! $n - $count, :$sink);
$count = nqp::elems($!items);
}

Expand Down Expand Up @@ -381,7 +381,7 @@ my class List does Positional {
}

method sink() {
self.eager;
self.gimme(*, :sink);
Nil;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/ListIter.pm
Expand Up @@ -7,7 +7,7 @@ my class ListIter {
# has Mu $!rest; # RPA of elements remaining to be reified
# has $!list; # List object associated with this iterator

method reify($n = 1) {
method reify($n = 1, :$sink) {
unless nqp::isconcrete($!reified) {
my $eager = nqp::p6bool(nqp::istype($n, Whatever));
my $flattens = nqp::p6bool(nqp::isconcrete($!list)) && $!list.flattens;
Expand All @@ -33,7 +33,8 @@ my class ListIter {
$x := $x.iterator.reify(
$eager
?? Whatever
!! nqp::p6box_i($count - nqp::elems($rpa)))
!! nqp::p6box_i($count - nqp::elems($rpa)),
:$sink)
if nqp::istype($x, Iterable);
nqp::splice($!rest, nqp::getattr($x, Parcel, '$!storage'), 0, 0);

Expand Down
16 changes: 14 additions & 2 deletions src/core/MapIter.pm
Expand Up @@ -24,7 +24,7 @@ my class MapIter is Iterator {

method flattens() { $!flattens }

method reify($n = 1) {
method reify($n = 1, :$sink) {
unless nqp::isconcrete($!reified) {
my $argc = $!block.count;
$argc = 1 if $argc < 1 || $argc ~~ Inf;
Expand All @@ -48,9 +48,10 @@ my class MapIter is Iterator {

my int $NEXT = nqp::can($block, 'fire_phasers')
&& +$block.phasers('NEXT');
my int $is_sink = $sink ?? 1 !! 0;

Q:PIR {
.local int argc, count, NEXT
.local int argc, count, NEXT, is_sink
.local pmc handler, self, MapIter, items, args, result, block, rpa
$P0 = find_lex '$argc'
argc = repr_unbox_int $P0
Expand All @@ -64,6 +65,7 @@ my class MapIter is Iterator {
block = find_lex '$block'
handler = root_new ['parrot';'ExceptionHandler']
NEXT = find_lex '$NEXT'
is_sink = find_lex '$is_sink'
set_addr handler, catch
handler.'handle_types'(.CONTROL_LOOP_LAST, .CONTROL_LOOP_NEXT, .CONTROL_LOOP_REDO)
Expand All @@ -84,8 +86,18 @@ my class MapIter is Iterator {
unless args goto iter_done
redo:
result = block(args :flat)
if is_sink goto sink_result
push rpa, result
goto next
sink_result:
$I0 = repr_defined result
unless $I0 goto next
$I0 = can result, 'sink'
unless $I0 goto next
$I0 = defined result
unless $I0 goto next
result.'sink'()
goto next
catch:
.local pmc exception, type
.get_results (exception)
Expand Down

0 comments on commit d4bf9e4

Please sign in to comment.