Skip to content

Commit

Permalink
Remove Range.clone-with-op / Fix bug on ops with subclasses of Range
Browse files Browse the repository at this point in the history
Addresses R#1582 #1582
Addresses D#1798 Raku/doc#1798

Also fixes explosion when subclasses/mixedin Range objects were used
with Range ops. Also fixes propagation of `infinite` attribute, tho
I'm unsure if it's possible to produce a Range with that attribute
different from original, using just the Range ops.

Fix the above bugs by using public interface to create modified Range
objects instead of poking into the guts. The choice for the ops
to produce a subclass of Range if one was given as the source of the
op is deliberate. While that's not the behaviour with, say,
`(42 but False) + 42`, which produces a plain `Int`, with Range ops,
there's always a single Range object involved, so we know for sure
what type to produce.
  • Loading branch information
zoffixznet committed Mar 2, 2018
1 parent efd0d6c commit 440fcea
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions src/core/Range.pm6
Expand Up @@ -632,15 +632,6 @@ my class Range is Cool does Iterable does Positional {
!! self.flat.elems
}

method clone-with-op(&op, $value) {
my $min = $!min [&op] $value;
my $max = $!max [&op] $value;
my $is-int = nqp::istype($min,Int) && nqp::istype($max,Int);
my $clone := self.clone( :$min, :$max );
nqp::bindattr_i($clone, $clone.WHAT, '$!is-int', $is-int);
$clone;
}

method push(|) is nodal {
X::Immutable.new(:typename<Range>,:method<push>).throw
}
Expand Down Expand Up @@ -756,12 +747,24 @@ multi sub infix:<eqv>(Range:D \a, Range:D \b) {
)
}

multi sub infix:<+>(Range:D \a, Real:D \b) { a.clone-with-op(&[+], b) }
multi sub infix:<+>(Real:D \a, Range:D \b) { b.clone-with-op(&[+], a) }
multi sub infix:<->(Range:D \a, Real:D \b) { a.clone-with-op(&[-], b) }
multi sub infix:<*>(Range:D \a, Real:D \b) { a.clone-with-op(&[*], b) }
multi sub infix:<*>(Real:D \a, Range:D \b) { b.clone-with-op(&[*], a) }
multi sub infix:</>(Range:D \a, Real:D \b) { a.clone-with-op(&[/], b) }
multi sub infix:<+>(Range:D \r, Real:D \v) {
r.new: r.min + v, r.max + v, :excludes-min(r.excludes-min), :excludes-max(r.excludes-max)
}
multi sub infix:<+>(Real:D \v, Range:D \r) {
r.new: v + r.min, v + r.max, :excludes-min(r.excludes-min), :excludes-max(r.excludes-max)
}
multi sub infix:<->(Range:D \r, Real:D \v) {
r.new: r.min - v, r.max - v, :excludes-min(r.excludes-min), :excludes-max(r.excludes-max)
}
multi sub infix:<*>(Range:D \r, Real:D \v) {
r.new: r.min * v, r.max * v, :excludes-min(r.excludes-min), :excludes-max(r.excludes-max)
}
multi sub infix:<*>(Real:D \v, Range:D \r) {
r.new: v * r.min, v * r.max, :excludes-min(r.excludes-min), :excludes-max(r.excludes-max)
}
multi sub infix:</>(Range:D \r, Real:D \v) {
r.new: r.min / v, r.max / v, :excludes-min(r.excludes-min), :excludes-max(r.excludes-max)
}

multi sub infix:<cmp>(Range:D \a, Range:D \b --> Order:D) {
a.min cmp b.min || a.excludes-min cmp b.excludes-min || a.max cmp b.max || b.excludes-max cmp a.excludes-max
Expand Down

0 comments on commit 440fcea

Please sign in to comment.