Skip to content

Commit

Permalink
Add an iterator multi candidate to Supply
Browse files Browse the repository at this point in the history
A problem with Seq and List supply coercions was that take could be used
inside of them, which would mix values taken with those that are
actually emitted by the supply in the coercion. Instead of using gather
to handle coercions in the first place, this adds an iterator method to
Supply to handle that for these two methods. Because of this,
Supply.list no longer needs to create a throwaway Seq to coerce to a
List.
  • Loading branch information
Kaiepi committed Apr 15, 2020
1 parent 43c7e96 commit dc7a796
Showing 1 changed file with 42 additions and 21 deletions.
63 changes: 42 additions & 21 deletions src/core.c/Supply-coercers.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,51 @@
$c
}

my class ConcQueue is repr('ConcBlockingQueue') { }
my class SupplyIterator does Iterator {
my class ConcQueue is repr('ConcBlockingQueue') { }
has $!queue;
has $!exception;

method new($supply) {
nqp::create(self)!SET-SELF($supply)
}
method !SET-SELF($supply) {
$!queue := nqp::create(ConcQueue);
$!exception := Nil;
$supply.tap: {
nqp::push($!queue, $_)
}, done => -> {
nqp::push($!queue, ConcQueue); # Sentinel value.
}, quit => {
$!exception := $_;
nqp::push($!queue, ConcQueue); # Sentinel value.
};
self
}

method pull-one() is raw {
nqp::stmts(
(my $got := nqp::shift($!queue)),
nqp::if(
nqp::eqaddr($got, ConcQueue),
nqp::if(
nqp::isconcrete($!exception),
$!exception.throw,
IterationEnd),
$got))
}

# method is-lazy(--> Bool:D) { ... }
}

multi method iterator(Supply:D:) {
SupplyIterator.new: self
}
multi method list(Supply:D:) {
self.Seq.list
List.from-iterator: self.iterator
}
method Seq(Supply:D:) {
gather {
my Mu \queue = nqp::create(ConcQueue);
my $exception;
self.tap(
-> \val { nqp::push(queue, val) },
done => -> { nqp::push(queue, ConcQueue) }, # type obj as sentinel
quit => -> \ex { $exception := ex; nqp::push(queue, ConcQueue) });
loop {
my \got = nqp::shift(queue);
if got =:= ConcQueue {
$exception.DEFINITE
?? $exception.throw
!! last
}
else {
take got;
}
}
}
Seq.new: self.iterator
}

method Promise(Supply:D:) {
Expand Down

0 comments on commit dc7a796

Please sign in to comment.