/
ListIter.pm
91 lines (82 loc) · 3.64 KB
/
ListIter.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
my class List { ... }
my class ListIter { # declared in BOOTSTRAP
# class ListIter is Iterator {
# has $!reified; # return value for already-reified iterator
# has $!nextiter; # next iterator in sequence, if any
# has Mu $!rest; # VM's array of elements remaining to be reified
# has $!list; # List object associated with this iterator
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;
my int $max = 100_000;
my int $count = $eager
?? $max
!! nqp::unbox_i(nqp::istype($n, Int) ?? $n !! $n.Int);
my $rpa := nqp::list();
nqp::setelems($rpa, $count);
nqp::setelems($rpa, 0);
my Mu $x;
my int $index;
my $want_types := $flattens
?? nqp::list(Iterable, Parcel)
!! nqp::list(Iterable);
nqp::p6shiftpush($rpa, $!rest, nqp::elems($!rest))
if nqp::istype($!list, LoL);
while $!rest && (nqp::elems($rpa) < $count) {
$index = nqp::p6arrfindtypes($!rest, $want_types, 0, $max);
nqp::p6shiftpush($rpa, $!rest, $index);
if $!rest && (nqp::elems($rpa) < $count) {
$x := nqp::shift($!rest);
if nqp::isconcrete($x) {
(nqp::unshift($!rest, $x); last) if $eager && $x.infinite;
$x := $x.iterator.reify(
$eager
?? Whatever
!! nqp::p6box_i($count - nqp::elems($rpa)),
:$sink)
if nqp::istype($x, Iterable);
nqp::splice($!rest, nqp::getattr($x, Parcel, '$!storage'), 0, 0);
}
elsif nqp::not_i(nqp::istype($x, Nil)) {
nqp::push($rpa, $x);
}
}
}
my $reified := nqp::p6parcel($rpa, Any);
nqp::bindattr(self, ListIter, '$!nextiter', nqp::p6listiter($!rest, $!list))
if $!rest;
$reified := $!list.REIFY($reified, $!nextiter) if nqp::isconcrete($!list);
nqp::push( nqp::getattr($reified, Parcel, '$!storage'), $!nextiter)
if $!rest;
nqp::bindattr(self, ListIter, '$!reified', $reified);
# free up $!list and $!rest
nqp::bindattr(self, ListIter, '$!list', Mu);
nqp::bindattr(self, ListIter, '$!rest', Mu);
}
$!reified;
}
method infinite() {
$!rest
?? nqp::istype(nqp::atpos($!rest, 0), Iterable)
&& nqp::atpos($!rest,0).infinite
|| Nil
!! Bool::False
}
method iterator() { self }
method nextiter() { $!nextiter }
multi method DUMP(ListIter:D: :$indent-step = 4, :%ctx?) {
return DUMP(self, :$indent-step) unless %ctx;
my $flags := ("\x221e" if self.infinite);
my Mu $attrs := nqp::list();
nqp::push($attrs, '$!list' );
nqp::push($attrs, $!list );
nqp::push($attrs, '$!reified' );
nqp::push($attrs, $!reified );
nqp::push($attrs, '$!nextiter');
nqp::push($attrs, $!nextiter );
nqp::push($attrs, '$!rest' );
nqp::push($attrs, $!rest );
self.DUMP-OBJECT-ATTRS($attrs, :$indent-step, :%ctx, :$flags);
}
}