Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 207 lines (192 sloc) 7.294 kB
47e455e @moritz Iterable should not inherit from Cool
moritz authored
1 class Range is Iterable is Cool does Positional {
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
2 has $.min;
3 has $.max;
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
4 has $.excludes_min;
5 has $.excludes_max;
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
6
53c7856 @moritz switch protos to use | instead of |$
moritz authored
7 proto method new(|) { * }
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
8 multi method new($min, $max, :$excludes_min, :$excludes_max) {
0a93f6e @jnthn Improve object creation performance in a few hot-path places (e.g. it…
jnthn authored
9 nqp::create(self).BUILD($min, $max, $excludes_min, $excludes_max)
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
10 }
cc19e25 @moritz make a range with Real min coerce the max to to Real too
moritz authored
11 multi method new(Real $min, $max, :$excludes_min, :$excludes_max) {
12 nqp::create(self).BUILD($min, $max.Real, $excludes_min, $excludes_max)
13 }
14 multi method new(Real $min, Whatever $max, :$excludes_min, :$excludes_max) {
15 nqp::create(self).BUILD($min, $Inf, $excludes_min, $excludes_max)
16 }
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
17 multi method new($min, Whatever $max, :$excludes_min, :$excludes_max) {
0a93f6e @jnthn Improve object creation performance in a few hot-path places (e.g. it…
jnthn authored
18 nqp::create(self).BUILD($min, $Inf, $excludes_min, $excludes_max)
33c6b6c @pmichaud Initial version of 1..* ranges.
pmichaud authored
19 }
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
20 multi method new(Whatever $min, $max, :$excludes_min, :$excludes_max) {
0a93f6e @jnthn Improve object creation performance in a few hot-path places (e.g. it…
jnthn authored
21 nqp::create(self).BUILD(-$Inf, $max, $excludes_min, $excludes_max)
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
22 }
602c0af @pmichaud Some additional Range methods.
pmichaud authored
23 multi method new(Whatever $min, Whatever $max, :$excludes_min, :$excludes_max) {
24 fail "*..* is not a valid range";
25 }
26
33c6b6c @pmichaud Initial version of 1..* ranges.
pmichaud authored
27
548e56a @moritz BUILD should be a submethod
moritz authored
28 submethod BUILD($min, $max, $excludes_min, $excludes_max) {
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
29 $!min = $min;
30 $!max = $max;
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
31 $!excludes_min = $excludes_min.Bool;
32 $!excludes_max = $excludes_max.Bool;
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
33 self;
34 }
35
7019642 @pmichaud Convert instances of 1.Bool into Bool::True.
pmichaud authored
36 method flat() { nqp::p6list(nqp::list(self), List, Bool::True) }
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
37 method infinite() { nqp::p6bool(nqp::istype($!max, Num)) && $!max eq 'Inf' }
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
38 method iterator() { self }
d19672e @pmichaud Significant refactor of lists and iterators. Results in a 50%
pmichaud authored
39 method list() { self.flat }
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
40
602c0af @pmichaud Some additional Range methods.
pmichaud authored
41 method bounds() { ($!min, $!max) }
42
30fab97 @moritz switch more of the setting to sigilless params (Int, Junction, Parcel…
moritz authored
43 multi method ACCEPTS(Range:D: Mu \topic) {
44 (topic cmp $!min) > -(!$!excludes_min)
45 and (topic cmp $!max) < +(!$!excludes_max)
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
46 }
47
30fab97 @moritz switch more of the setting to sigilless params (Int, Junction, Parcel…
moritz authored
48 multi method ACCEPTS(Range:D: Range \topic) {
49 (topic.min > $!min
50 || topic.min == $!min
51 && !(!topic.excludes_min && $!excludes_min))
cb61d59 @masak [src/core/Range.pm] Range ~~ Range semantics
masak authored
52 &&
30fab97 @moritz switch more of the setting to sigilless params (Int, Junction, Parcel…
moritz authored
53 (topic.max < $!max
54 || topic.max == $!max
55 && !(!topic.excludes_max && $!excludes_max))
cb61d59 @masak [src/core/Range.pm] Range ~~ Range semantics
masak authored
56 }
57
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
58 method reify($n = 10) {
3823e80 @pmichaud Fix 'a'..'z' (and other Str-based Ranges) by delegating to
pmichaud authored
59 my $value = $!excludes_min ?? $!min.succ !! $!min;
60 # Iterating a Str range delegates to iterating a sequence.
61 if Str.ACCEPTS($value) {
62 return $value after $!max
63 ?? ()
64 !! SEQUENCE($value, $!max, :exclude_end($!excludes_max)).iterator.reify($n)
65 }
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
66 my $count;
67 if nqp::istype($n, Whatever) {
68 $count = self.infinite ?? 10 !! $Inf;
69 }
70 else {
71 $count = $n.Num;
72 fail "request for infinite elements from range"
73 if $count == $Inf && self.infinite;
74 }
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
75 my $cmpstop = $!excludes_max ?? 0 !! 1;
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
76 my $realmax = nqp::istype($!min, Numeric) && !nqp::istype($!max, Callable) && !nqp::istype($!max, Whatever)
3bfaa06 @moritz Range iteration fixes
moritz authored
77 ?? $!max.Numeric
78 !! $!max;
ab1dda5 @pmichaud Convert some more pir:: opcodes to nqp:: .
pmichaud authored
79 my Mu $rpa := nqp::list();
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
80 if nqp::istype($value, Int) && nqp::istype($!max, Int) && !nqp::isbig_I(nqp::p6decont $!max)
81 || nqp::istype($value, Num) {
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
82 # Q:PIR optimized for int/num ranges
83 $value = $value.Num;
84 my $max = $!max.Num;
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
85 my $box_int = nqp::p6bool(nqp::istype($!min, Int));
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
86 Q:PIR {
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
87 .local pmc rpa, value_pmc, count_pmc
88 .local num value, count, max
e035eed @moritz Num ranges now produce Num lists
moritz authored
89 .local int cmpstop, box_int
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
90 rpa = find_lex '$rpa'
91 value_pmc = find_lex '$value'
92 value = repr_unbox_num value_pmc
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
93 count_pmc = find_lex '$count'
94 count = repr_unbox_num count_pmc
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
95 $P0 = find_lex '$max'
96 max = repr_unbox_num $P0
97 $P0 = find_lex '$cmpstop'
98 cmpstop = repr_unbox_int $P0
e035eed @moritz Num ranges now produce Num lists
moritz authored
99 $P0 = find_lex '$box_int'
100 box_int = repr_unbox_int $P0
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
101 loop:
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
102 unless count > 0 goto done
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
103 $I0 = cmp value, max
104 unless $I0 < cmpstop goto done
e035eed @moritz Num ranges now produce Num lists
moritz authored
105 unless box_int goto box_num
a4a40c0 @pmichaud Make Range smart enough to return Int instead of Num, add temporary o…
pmichaud authored
106 $P0 = perl6_box_bigint value
e035eed @moritz Num ranges now produce Num lists
moritz authored
107 goto box_done
108 box_num:
109 $P0 = perl6_box_num value
110 box_done:
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
111 push rpa, $P0
112 inc value
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
113 dec count
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
114 goto loop
115 done:
6084be6 @moritz Do not treat the last value of a range as a Num
moritz authored
116 $P0 = perl6_box_bigint value
8ba6979 @jnthn Tiny optimization to range iteration.
jnthn authored
117 perl6_container_store value_pmc, $P0
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
118 %r = rpa
119 };
120 }
121 else {
2630e16 @pmichaud Improve handling of .reify(*) and infinite lists.
pmichaud authored
122 (nqp::push($rpa, $value++); $count--)
3bfaa06 @moritz Range iteration fixes
moritz authored
123 while $count > 0 && ($value cmp $realmax) < $cmpstop;
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
124 }
125 if ($value cmp $!max) < $cmpstop {
ab1dda5 @pmichaud Convert some more pir:: opcodes to nqp:: .
pmichaud authored
126 nqp::push($rpa,
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
127 ($value.succ cmp $!max < $cmpstop)
0a93f6e @jnthn Improve object creation performance in a few hot-path places (e.g. it…
jnthn authored
128 ?? nqp::create(self).BUILD($value, $!max, 0, $!excludes_max)
bdfbe6b @pmichaud Use Q:PIR to hotpath the generation of int/num ranges.
pmichaud authored
129 !! $value);
130 }
ab1dda5 @pmichaud Convert some more pir:: opcodes to nqp:: .
pmichaud authored
131 nqp::p6parcel($rpa, nqp::null());
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
132 }
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
133
9e91676 @pmichaud Add List.pick, Any.pick, and Range.at_pos.
pmichaud authored
134 method at_pos($pos) { self.flat.at_pos($pos) }
602c0af @pmichaud Some additional Range methods.
pmichaud authored
135
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
136 multi method perl(Range:D:) {
2f4210b @pmichaud Fix Range.perl for non-numeric ranges.
pmichaud authored
137 $.min.perl
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
138 ~ ('^' if $.excludes_min)
139 ~ '..'
140 ~ ('^' if $.excludes_max)
2f4210b @pmichaud Fix Range.perl for non-numeric ranges.
pmichaud authored
141 ~ $.max.perl
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
142 }
92fa939 @pmichaud Improve iterator dumpers a bit.
pmichaud authored
143
144 multi method DUMP(Range:D:) {
145 self.DUMP-ID() ~ '('
146 ~ ':min(' ~ DUMP($!min) ~ '), '
147 ~ ':max(' ~ DUMP($!max) ~ ')'
148 ~ ')'
149 }
f56c3ec @moritz optimize Range.roll, and Range.pick if the number of range elems is m…
moritz authored
150
53c7856 @moritz switch protos to use | instead of |$
moritz authored
151 proto method roll(|) { * }
f56c3ec @moritz optimize Range.roll, and Range.pick if the number of range elems is m…
moritz authored
152 multi method roll(Range:D: Whatever) {
153 gather loop { take self.roll }
154 }
155 multi method roll(Range:D:) {
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
156 return self.list.roll unless nqp::istype($!min, Int) && nqp::istype($!max, Int);
f56c3ec @moritz optimize Range.roll, and Range.pick if the number of range elems is m…
moritz authored
157 my Int:D $least = $!excludes_min ?? $!min + 1 !! $!min;
158 my Int:D $elems = 1 + ($!excludes_max ?? $!max - 1 !! $!max) - $least;
159 $elems ?? ($least + $elems.rand.floor) !! Any;
160 }
161 multi method roll(Cool $num as Int) {
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
162 return self.list.roll($num) unless nqp::istype($!min, Int) && nqp::istype($!max, Int);
f56c3ec @moritz optimize Range.roll, and Range.pick if the number of range elems is m…
moritz authored
163 return self.roll if $num == 1;
164 my int $n = nqp::unbox_i($num);
165 gather loop (my int $i = 0; $i < $n; $i = $i + 1) {
166 take self.roll;
167 }
168 }
169
53c7856 @moritz switch protos to use | instead of |$
moritz authored
170 proto method pick(|) { * }
f56c3ec @moritz optimize Range.roll, and Range.pick if the number of range elems is m…
moritz authored
171 multi method pick() { self.roll };
172 multi method pick(Whatever) { self.list.pick(*) };
173 multi method pick(Cool $n as Int) {
2c672ae @jnthn Optimize range iteration code a bit to shave 40% or so off [+] 1..100…
jnthn authored
174 return self.list.pick($n) unless nqp::istype($!min, Int) && nqp::istype($!max, Int);
0291402 @moritz Return an Int from Range.pick(1)
moritz authored
175 return self.roll if $n == 1;
f56c3ec @moritz optimize Range.roll, and Range.pick if the number of range elems is m…
moritz authored
176 my Int:D $least = $!excludes_min ?? $!min + 1 !! $!min;
177 my Int:D $elems = 1 + ($!excludes_max ?? $!max - 1 !! $!max) - $least;
178 return self.list.pick($n) unless $elems > 3 * $n;
179 my %seen;
180 my int $i_n = nqp::unbox_i($n);
181 gather while $i_n > 0 {
182 my Int $x = $least + $elems.rand.floor;
183 unless %seen{$x} {
184 %seen{$x} = 1;
185 $i_n = $i_n - 1;
186 take $x;
187 }
188 }
189 }
cd87a74 @pmichaud Add preliminary Range and RangeIter type.
pmichaud authored
190 }
191
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
192 sub infix:<..>($min, $max) {
193 Range.new($min, $max)
194 }
195 sub infix:<^..>($min, $max) {
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
196 Range.new($min, $max, :excludes_min)
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
197 }
198 sub infix:<..^>($min, $max) {
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
199 Range.new($min, $max, :excludes_max)
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
200 }
201 sub infix:<^..^>($min, $max) {
f7f0c00 @pmichaud More fixes for Range class, now pass S03-operators/range-basic.t .
pmichaud authored
202 Range.new($min, $max, :excludes_min, :excludes_max)
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
203 }
204 sub prefix:<^>($max) {
1701cb2 @pmichaud Add Stringy role. prefix:<^> enforces numeric context. Another spec…
pmichaud authored
205 Range.new(0, $max.Numeric, :excludes_max)
66c1021 @pmichaud Refactor Range, add the ability to exclude endpoints. Also remove th…
pmichaud authored
206 }
Something went wrong with that request. Please try again.