Skip to content

Commit

Permalink
CLJS-3271: nth on range produces nonexistent values considering float…
Browse files Browse the repository at this point in the history
…ing point
  • Loading branch information
mfikes committed Jul 25, 2020
1 parent f5f9b79 commit bdbd6c5
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 23 deletions.
138 changes: 126 additions & 12 deletions src/main/cljs/cljs/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9650,7 +9650,7 @@ reduces them without incurring seq initialization"
(take-while (mk-bound-fn sc start-test start-key)
(if ((mk-bound-fn sc end-test end-key) e) s (next s))))))

(deftype RangeChunk [start step count]
(deftype IntegerRangeChunk [start step count]
ICounted
(-count [coll] count)

Expand All @@ -9669,7 +9669,7 @@ reduces them without incurring seq initialization"
(-drop-first [coll]
(if (<= count 1)
(throw (js/Error. "-drop-first of empty chunk"))
(RangeChunk. (+ start step) step (dec count)))))
(IntegerRangeChunk. (+ start step) step (dec count)))))

(deftype RangeIterator [^:mutable i end step]
Object
Expand All @@ -9682,7 +9682,7 @@ reduces them without incurring seq initialization"
(set! i (+ i step))
ret)))

(deftype Range [meta start end step ^:mutable chunk ^:mutable chunk-next ^:mutable __hash]
(deftype IntegerRange [meta start end step ^:mutable chunk ^:mutable chunk-next ^:mutable __hash]
Object
(toString [coll]
(pr-str* coll))
Expand All @@ -9701,18 +9701,18 @@ reduces them without incurring seq initialization"
(let [count (-count coll)]
(if (> count 32)
(do
(set! chunk-next (Range. nil (+ start (* step 32)) end step nil nil nil))
(set! chunk (RangeChunk. start step 32)))
(set! chunk (RangeChunk. start step count))))))
(set! chunk-next (IntegerRange. nil (+ start (* step 32)) end step nil nil nil))
(set! chunk (IntegerRangeChunk. start step 32)))
(set! chunk (IntegerRangeChunk. start step count))))))

ICloneable
(-clone [_] (Range. meta start end step chunk chunk-next __hash))
(-clone [_] (IntegerRange. meta start end step chunk chunk-next __hash))

IWithMeta
(-with-meta [rng new-meta]
(if (identical? new-meta meta)
rng
(Range. new-meta start end step chunk chunk-next __hash)))
(IntegerRange. new-meta start end step chunk chunk-next __hash)))

IMeta
(-meta [rng] meta)
Expand All @@ -9736,9 +9736,9 @@ reduces them without incurring seq initialization"
(-next [rng]
(if (pos? step)
(when (< (+ start step) end)
(Range. nil (+ start step) end step nil nil nil))
(IntegerRange. nil (+ start step) end step nil nil nil))
(when (> (+ start step) end)
(Range. nil (+ start step) end step nil nil nil))))
(IntegerRange. nil (+ start step) end step nil nil nil))))

IChunkedSeq
(-chunked-first [rng]
Expand Down Expand Up @@ -9796,6 +9796,113 @@ reduces them without incurring seq initialization"
(recur (+ i step) ret)))
ret))))

(es6-iterable IntegerRange)

(deftype Range [meta start end step ^:mutable chunk ^:mutable chunk-next ^:mutable __hash]
Object
(toString [coll]
(pr-str* coll))
(equiv [this other]
(-equiv this other))
(indexOf [coll x]
(-indexOf coll x 0))
(indexOf [coll x start]
(-indexOf coll x start))
(lastIndexOf [coll x]
(-lastIndexOf coll x (count coll)))
(lastIndexOf [coll x start]
(-lastIndexOf coll x start))
(forceChunk [coll]
(when (nil? chunk)
(let [arr (make-array 32)
val (loop [n 0 val start]
(if (< n 32)
(do
(aset arr n val)
(let [n (inc n)
val (+ val step)]
(if (if (pos? step) (< val end) (> val end))
(recur n val)
(set! chunk (array-chunk arr 0 n)))))
val))]
(when (nil? chunk)
(set! chunk (array-chunk arr 0 32))
(when (if (pos? step) (< val end) (> val end))
(set! chunk-next (Range. nil val end step nil nil nil)))))))

ICloneable
(-clone [_] (Range. meta start end step chunk chunk-next __hash))

IWithMeta
(-with-meta [rng new-meta]
(if (identical? new-meta meta)
rng
(Range. new-meta start end step chunk chunk-next __hash)))

IMeta
(-meta [rng] meta)

ISeqable
(-seq [rng] rng)

ISeq
(-first [rng] start)
(-rest [rng]
(let [s (-next rng)]
(if (nil? s)
()
s)))

IIterable
(-iterator [_]
(RangeIterator. start end step))

INext
(-next [rng]
(if (pos? step)
(when (< (+ start step) end)
(Range. nil (+ start step) end step nil nil nil))
(when (> (+ start step) end)
(Range. nil (+ start step) end step nil nil nil))))

IChunkedSeq
(-chunked-first [rng]
(.forceChunk rng)
chunk)
(-chunked-rest [rng]
(.forceChunk rng)
(if (nil? chunk-next)
()
chunk-next))

IChunkedNext
(-chunked-next [rng]
(seq (-chunked-rest rng)))

ICollection
(-conj [rng o] (cons o rng))

IEmptyableCollection
(-empty [rng] (.-EMPTY List))

ISequential
IEquiv
(-equiv [rng other] (equiv-sequential rng other))

IHash
(-hash [rng] (caching-hash rng hash-ordered-coll __hash))

IReduce
(-reduce [rng f] (seq-reduce f rng))
(-reduce [rng f init]
(loop [i start ret init]
(if (if (pos? step) (< i end) (> i end))
(let [ret (f ret i)]
(if (reduced? ret)
@ret
(recur (+ i step) ret)))
ret))))

(es6-iterable Range)

(defn range
Expand All @@ -9810,12 +9917,16 @@ reduces them without incurring seq initialization"
(pos? step)
(if (<= end start)
()
(Range. nil start end step nil nil nil))
(if (and (integer? start) (integer? end) (integer? step))
(IntegerRange. nil start end step nil nil nil)
(Range. nil start end step nil nil nil)))

(neg? step)
(if (>= end start)
()
(Range. nil start end step nil nil nil))
(if (and (integer? start) (integer? end) (integer? step))
(IntegerRange. nil start end step nil nil nil)
(Range. nil start end step nil nil nil)))

:else
(if (== end start)
Expand Down Expand Up @@ -10429,6 +10540,9 @@ reduces them without incurring seq initialization"
Range
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))

IntegerRange
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))

Cycle
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))

Expand Down
51 changes: 51 additions & 0 deletions src/test/cljs/cljs/collections_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
(ns cljs.collections-test
(:refer-clojure :exclude [iter])
(:require [cljs.test :refer-macros [deftest testing is are run-tests]]
[clojure.test.check :as tc]
[clojure.test.check.clojure-test :refer-macros [defspec]]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as prop :include-macros true]
[clojure.string :as s]
[clojure.set :as set]))

Expand Down Expand Up @@ -141,10 +145,18 @@
(is (= #{1} (disj #{1 2 3} 2 3)))
(is (nil? (disj nil :foo)))))

(defspec integerrange-equals-range 100
(prop/for-all [start gen/int
end gen/int
step gen/s-pos-int]
(= (Range. nil start end step nil nil nil)
(IntegerRange. nil start end step nil nil nil))))

(deftest test-range
(testing "Testing Range"
;; Range
(is (= (range 0 10 3) (list 0 3 6 9)))
(is (= (range 2.5) '(0 1 2)))
(is (= (count (range 0 10 3)) 4))
(is (= (range 0 -10 -3) (list 0 -3 -6 -9)))
(is (= (count (range 0 -10 -3)) 4))
Expand All @@ -163,6 +175,45 @@
(is (= (count (range 0 0 0)) 0))
(is (= (take 3 (range 1 0 0)) (list 1 1 1)))
(is (= (take 3 (range 3 1 0)) (list 3 3 3)))
(is (not (counted? (range))))
(is (counted? (range 0 10 1)))
(is (not (counted? (range 0.1 10 1))))
(is (chunked-seq? (range 0 10 1)))
(is (chunked-seq? (range 0.1 10 1)))
(is (= (range 0.5 8 1.2) '(0.5 1.7 2.9 4.1 5.3 6.5 7.7)))
(is (= (range 0.5 -4 -2) '(0.5 -1.5 -3.5)))
(is (= (reduce + (range 0 100)) 4950))
(is (= (reduce + 0 (range 0 100)) 4950))
(is (= (reduce + (range 0.1 100)) 4960))
(is (= (reduce + 0 (range 0.1 100)) 4960))
(is (= (reduce + (map inc (range 0 100 1))) 5050))
(is (= (reduce + 0 (map inc (range 0 100 1))) 5050))
(is (= (reduce + (map inc (range 0 100 0.1))) 51051))
(is (= (reduce + 0 (map inc (range 0 100 0.1))) 51051))
(is (= (reduce + (range 0 3.1 0.1)) 46.500000000000014))
(is (= (reduce + 0 (range 0 3.1 0.1)) 46.500000000000014))
(is (= (reduce + (range 0 3.2 0.1)) 49.600000000000016))
(is (= (reduce + 0 (range 0 3.2 0.1)) 49.600000000000016))
(is (= (reduce + (range 0 3.3 0.1)) 52.80000000000002))
(is (= (reduce + 0 (range 0 3.3 0.1)) 52.80000000000002))
(is (= (reduce + (range 0 -3.1 -0.1)) -46.500000000000014))
(is (= (reduce + 0 (range 0 -3.1 -0.1)) -46.500000000000014))
(is (= (reduce + (range 0 -3.2 -0.1)) -49.600000000000016))
(is (= (reduce + 0 (range 0 -3.2 -0.1)) -49.600000000000016))
(is (= (reduce + (range 0 -3.3 -0.1)) -52.80000000000002))
(is (= (reduce + 0 (range 0 -3.3 -0.1)) -52.80000000000002))
(is (= (reduce + (map inc (range 0 3.1 0.1))) 77.50000000000001))
(is (= (reduce + 0 (map inc (range 0 3.1 0.1))) 77.50000000000001))
(is (= (reduce + (map inc (range 0 3.2 0.1))) 81.60000000000002))
(is (= (reduce + 0 (map inc (range 0 3.2 0.1))) 81.60000000000002))
(is (= (reduce + (map inc (range 0 3.3 0.1))) 85.80000000000003))
(is (= (reduce + 0 (map inc (range 0 3.3 0.1))) 85.80000000000003))
(is (= (reduce + (map inc (range 0 -3.1 -0.1))) -15.500000000000012))
(is (= (reduce + 0 (map inc (range 0 -3.1 -0.1))) -15.500000000000012))
(is (= (reduce + (map inc (range 0 -3.2 -0.1))) -17.600000000000016))
(is (= (reduce + 0 (map inc (range 0 -3.2 -0.1))) -17.600000000000016))
(is (= (reduce + (map inc (range 0 -3.3 -0.1))) -19.80000000000002))
(is (= (reduce + 0 (map inc (range 0 -3.3 -0.1))) -19.80000000000002))
))

(deftest test-cycle
Expand Down
18 changes: 7 additions & 11 deletions src/test/cljs/cljs/core_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -621,16 +621,6 @@
(is (= (meta (with-meta (reify IFoo (foo [this] :foo)) {:foo :bar}))
{:foo :bar})))


(defprotocol Slashy (/ [_]))

(extend-type string
Slashy
(/ [_] "result"))

(deftest test-protocol-with-slash
(is (= "result" (/ ""))))

(let [x "original"]
(defn original-closure-stmt [] x))

Expand Down Expand Up @@ -1818,4 +1808,10 @@

(deftest test-cljs-3202
(is (= :/ (keyword "/")))
(is (= (hash :/) (hash (keyword "/")))))
(is (= (hash :/) (hash (keyword "/")))))

(deftest test-cljs-3270
(is (== 10 (count (range 0 (+ 1 (/ 9)) (/ 9))))))

(deftest test-cljs-3271
(is (== 0.6 (nth (range 0 1 0.1) 6))))
9 changes: 9 additions & 0 deletions src/test/cljs/cljs/extend_to_native_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,12 @@
(is (= :p (test-seqable 1)))
(extend-type string IReduce (-reduce [_ _] :q))
(is (= :q (test-reduceable "a"))))

(defprotocol Slashy (/ [_]))

(extend-type string
Slashy
(/ [_] "result"))

(deftest test-protocol-with-slash
(is (= "result" (/ ""))))

0 comments on commit bdbd6c5

Please sign in to comment.