From dcd0d9ecce4f34e8bd2f00f8d46af1fbadfa4b77 Mon Sep 17 00:00:00 2001 From: Nikita Prokopov Date: Sun, 20 Sep 2015 02:31:52 +0600 Subject: [PATCH] =?UTF-8?q?datascript.shim=20=E2=86=92=20datascript.arrays?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 15 +- README.md | 2 +- src/datascript/{shim.cljc => arrays.cljc} | 41 +--- src/datascript/btset.cljc | 255 +++++++++++----------- src/datascript/db.cljc | 32 ++- src/datascript/parser.cljc | 5 +- src/datascript/query.cljc | 12 +- src/datascript/query_v3.cljc | 101 +++++---- test/datascript/test/explode.cljc | 4 +- 9 files changed, 237 insertions(+), 230 deletions(-) rename src/datascript/{shim.cljc => arrays.cljc} (79%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 023159d3..be2bc06e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,20 @@ # WIP -- [ BREAKING ] **Main namespace to include is now `datascript.core`**, not `datascript`. +- **[ BREAKING ] Main namespace to include is now `datascript.core`, not `datascript`** - [ BREAKING ] Old `datascript.core` (internal namespace) was renamed to `datascript.db` +- [ BREAKING ] `datascript.shim` (internal namespace) was renamed to `datascript.arrays` -Motivation: Usage of top-level namespaces is discouraged and even generates a warning in CLJS. This would’ve happen sooner or later anyways. 0.13 seems like a great number for this sort of release. +Motivations: -Migration path: just change `(require '[datascript :as d])` to `(require '[datascript.core :as d])` and you’re good to go. +- Usage of top-level namespaces is discouraged and even generates a warning in CLJS. +- Better sooner than later. +- 0.13 seems like a great number for this sort of release. -Due to significance and impact of this release (100% user base), there’re no other changes in this release. +Migration procedure: + +- Just change `(require '[datascript :as d])` to `(require '[datascript.core :as d])` and you’re good to go. + +For the sake of easy migration, there’re no other changes in this release. Just renamings. # 0.12.2 diff --git a/README.md b/README.md index 92de77d6..f90737f0 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ Check out [test/js/tests.js](test/js/tests.js) for usage examples. ## Project status -Alpha quality. Half of the features done, a lot of cases where error reporting is missing, no docs (use examples & Datomic documentation). +Beta quality. Most of the features done, expecting some API polishing (breaking) and performance optimizations. No docs at the moment, use examples & Datomic documentation. The following features are supported: diff --git a/src/datascript/shim.cljc b/src/datascript/arrays.cljc similarity index 79% rename from src/datascript/shim.cljc rename to src/datascript/arrays.cljc index 506e7b13..3f93997f 100644 --- a/src/datascript/shim.cljc +++ b/src/datascript/arrays.cljc @@ -1,10 +1,13 @@ -(ns datascript.shim +(ns datascript.arrays (:require [clojure.string :as str]) - (:refer-clojure :exclude [make-array into-array array amap aget aset alength array? seqable? aclone]) - #?(:cljs (:require-macros datascript.shim)) + (:refer-clojure :exclude [make-array into-array array amap aget aset alength array? aclone]) + #?(:cljs (:require-macros datascript.arrays)) #?(:clj (:import [java.util Arrays]))) +(defn- if-cljs [env then else] + (if (:ns env) then else)) + #?(:cljs (def make-array cljs.core/make-array) :clj (defn make-array ^{:tag "[[Ljava.lang.Object;"} [size] @@ -15,9 +18,6 @@ [aseq] (clojure.core/into-array java.lang.Object aseq))) -(defn- if-cljs [env then else] - (if (:ns env) then else)) - #?(:clj (defmacro aget [arr i] (if-cljs &env @@ -83,32 +83,3 @@ (def array? #?(:cljs cljs.core/array? :clj (fn array? [^Object x] (-> x .getClass .isArray)))) - -(def seqable? - #?(:cljs cljs.core/seqable? - :clj (fn seqable? [x] - (or (seq? x) - (instance? clojure.lang.Seqable x) - (nil? x) - (instance? Iterable x) - (array? x) - (string? x) - (instance? java.util.Map x))))) - -(def neg-number? (every-pred number? neg?)) - -#?(:clj - (defmacro half [x] - `(unsigned-bit-shift-right ~x 1))) - -#?(:clj - (defmacro not== [x y] - `(not (== ~x ~y)))) - -(defn zip - ([a b] (map vector a b)) - ([a b & rest] (apply map vector a b rest))) - -(defn has? [coll el] - (some #(= el %) coll)) - diff --git a/src/datascript/btset.cljc b/src/datascript/btset.cljc index 2b373d19..6d1ea8d0 100644 --- a/src/datascript/btset.cljc +++ b/src/datascript/btset.cljc @@ -33,12 +33,21 @@ datascript.btset (:refer-clojure :exclude [iter]) (:require - [datascript.shim :as shim]) - #?(:clj (:import [java.util Arrays]))) + [datascript.arrays :as da]) + #?(:clj (:import [java.util Arrays])) + #?(:cljs (:require-macros [datascript.btset :refer [half not==]]))) + +#?(:clj + (defmacro half [x] + `(unsigned-bit-shift-right ~x 1))) + +#?(:clj + (defmacro not== [x y] + `(not (== ~x ~y)))) (def ^:const min-len 16) (def ^:const max-len 32) -(def ^:const avg-len (shim/half (+ max-len min-len))) +(def ^:const avg-len (half (+ max-len min-len))) (def ^:const level-shift (->> (range 31 -1 -1) (filter #(bit-test max-len %)) first @@ -58,8 +67,8 @@ (loop [l 0 r (long r)] (if (<= l r) - (let [m (shim/half (+ l r)) - mk (shim/aget arr m)] + (let [m (half (+ l r)) + mk (da/aget arr m)] (if (neg? (cmp mk k)) (recur (inc m) r) (recur l (dec m)))) @@ -70,23 +79,23 @@ (loop [l 0 r (long r)] (if (<= l r) - (let [m (shim/half (+ l r)) - mk (shim/aget arr m)] + (let [m (half (+ l r)) + mk (da/aget arr m)] (if (pos? (cmp mk k)) (recur l (dec m)) (recur (inc m) r))) l))) (defn lookup-exact ^long [cmp arr key] - (let [arr-l (shim/alength arr) + (let [arr-l (da/alength arr) idx (binary-search-l cmp arr (dec arr-l) key)] (if (and (< idx arr-l) - (== 0 (cmp (shim/aget arr idx) key))) + (== 0 (cmp (da/aget arr idx) key))) idx -1))) (defn lookup-range ^long [cmp arr key] - (let [arr-l (shim/alength arr) + (let [arr-l (da/alength arr) idx (binary-search-l cmp arr (dec arr-l) key)] (if (== idx arr-l) -1 @@ -95,17 +104,17 @@ ;; Array operations (defn alast [arr] - (shim/aget arr (dec (shim/alength arr)))) + (da/aget arr (dec (da/alength arr)))) (defn cut-n-splice [arr cut-from cut-to splice-from splice-to xs] - (let [xs-l (shim/alength xs) + (let [xs-l (da/alength xs) l1 (- splice-from cut-from) l2 (- cut-to splice-to) l1xs (+ l1 xs-l) - new-arr (shim/make-array (+ l1 xs-l l2))] - (shim/acopy arr cut-from splice-from new-arr 0) - (shim/acopy xs 0 xs-l new-arr l1) - (shim/acopy arr splice-to cut-to new-arr l1xs) + new-arr (da/make-array (+ l1 xs-l l2))] + (da/acopy arr cut-from splice-from new-arr 0) + (da/acopy xs 0 xs-l new-arr l1) + (da/acopy arr splice-to cut-to new-arr l1xs) new-arr)) (defn cut @@ -113,7 +122,7 @@ #?(:cljs (.slice arr cut-from) :clj (Arrays/copyOfRange ^{:tag "[[Ljava.lang.Object;"} arr (int cut-from) - (shim/alength arr)))) + (da/alength arr)))) ([arr cut-from cut-to] #?(:cljs (.slice arr cut-from cut-to) :clj (Arrays/copyOfRange ^{:tag "[[Ljava.lang.Object;"} arr @@ -121,29 +130,29 @@ (int cut-to))))) (defn splice [arr splice-from splice-to xs] - (cut-n-splice arr 0 (shim/alength arr) splice-from splice-to xs)) + (cut-n-splice arr 0 (da/alength arr) splice-from splice-to xs)) (defn insert [arr idx xs] - (cut-n-splice arr 0 (shim/alength arr) idx idx xs)) + (cut-n-splice arr 0 (da/alength arr) idx idx xs)) (defn merge-n-split [a1 a2] - (let [a1-l (shim/alength a1) - a2-l (shim/alength a2) + (let [a1-l (da/alength a1) + a2-l (da/alength a2) total-l (+ a1-l a2-l) - r1-l (shim/half total-l) + r1-l (half total-l) r2-l (- total-l r1-l) - r1 (shim/make-array r1-l) - r2 (shim/make-array r2-l)] + r1 (da/make-array r1-l) + r2 (da/make-array r2-l)] (if (<= a1-l r1-l) (do - (shim/acopy a1 0 a1-l r1 0) - (shim/acopy a2 0 (- r1-l a1-l) r1 a1-l) - (shim/acopy a2 (- r1-l a1-l) a2-l r2 0)) + (da/acopy a1 0 a1-l r1 0) + (da/acopy a2 0 (- r1-l a1-l) r1 a1-l) + (da/acopy a2 (- r1-l a1-l) a2-l r2 0)) (do - (shim/acopy a1 0 r1-l r1 0) - (shim/acopy a1 r1-l a1-l r2 0) - (shim/acopy a2 0 a2-l r2 (- a1-l r1-l)))) - (shim/array r1 r2))) + (da/acopy a1 0 r1-l r1 0) + (da/acopy a1 r1-l a1-l r2 0) + (da/acopy a2 0 a2-l r2 (- a1-l r1-l)))) + (da/array r1 r2))) (defn ^boolean eq-arr [cmp a1 a1-from a1-to a2 a2-from a2-to] @@ -154,22 +163,22 @@ (cond (== i len) true - (shim/not== 0 (cmp (shim/aget a1 (+ i a1-from)) - (shim/aget a2 (+ i a2-from)))) + (not== 0 (cmp (da/aget a1 (+ i a1-from)) + (da/aget a2 (+ i a2-from)))) false :else (recur (inc i))))))) (defn check-n-splice [cmp arr from to new-arr] - (if (eq-arr cmp arr from to new-arr 0 (shim/alength new-arr)) + (if (eq-arr cmp arr from to new-arr 0 (da/alength new-arr)) arr (splice arr from to new-arr))) (defn arr-map-inplace [f arr] - (let [len (shim/alength arr)] + (let [len (da/alength arr)] (loop [i 0] (when (< i len) - (shim/aset arr i (f (shim/aget arr i))) + (da/aset arr i (f (da/aget arr i))) (recur (inc i)))) arr)) @@ -178,7 +187,7 @@ trying to stick to (min+max)/2" [min-len max-len arr] (let [chunk-len avg-len - len (shim/alength arr) + len (da/alength arr) acc (transient [])] (when (pos? len) (loop [pos 0] @@ -191,20 +200,20 @@ (conj! acc (cut arr pos (+ pos chunk-len))) (recur (+ pos chunk-len))) :else - (let [piece-len (shim/half rest)] + (let [piece-len (half rest)] (conj! acc (cut arr pos (+ pos piece-len))) (recur (+ pos piece-len))))))) (to-array (persistent! acc)))) ;; TODO avoid persistent? (defn- sorted-arr-distinct? [arr cmp] - (let [al (shim/alength arr)] + (let [al (da/alength arr)] (if (<= al 1) true (loop [i 1 - p (shim/aget arr 0)] + p (da/aget arr 0)] (if (>= i al) true - (let [e (shim/aget arr i)] + (let [e (da/aget arr i)] (if (== 0 (cmp e p)) false (recur (inc i) e)))))))) @@ -215,13 +224,13 @@ [arr cmp] (if (sorted-arr-distinct? arr cmp) arr - (let [al (shim/alength arr)] - (loop [acc (transient [(shim/aget arr 0)]) + (let [al (da/alength arr)] + (loop [acc (transient [(da/aget arr 0)]) i 1 - p (shim/aget arr 0)] + p (da/aget arr 0)] (if (>= i al) (into-array (persistent! acc)) ;; TODO avoid persistent? - (let [e (shim/aget arr i)] + (let [e (da/aget arr i)] (if (== 0 (cmp e p)) (recur acc (inc i) e) (recur (conj! acc e) (inc i) e)))))))) @@ -229,27 +238,27 @@ (defn return-array "Drop non-nil references and return array of arguments" ([a1] - (shim/array a1)) + (da/array a1)) ([a1 a2] (if a1 (if a2 - (shim/array a1 a2) - (shim/array a1)) - (shim/array a2))) + (da/array a1 a2) + (da/array a1)) + (da/array a2))) ([a1 a2 a3] (if a1 (if a2 (if a3 - (shim/array a1 a2 a3) - (shim/array a1 a2)) + (da/array a1 a2 a3) + (da/array a1 a2)) (if a3 - (shim/array a1 a3) - (shim/array a1))) + (da/array a1 a3) + (da/array a1))) (if a2 (if a3 - (shim/array a2 a3) - (shim/array a2)) - (shim/array a3))))) + (da/array a2 a3) + (da/array a2)) + (da/array a3))))) ;; @@ -284,12 +293,12 @@ (and left (or (nil? right) (< (node-len left) (node-len right)))) (let [nodes (node-merge-n-split left node)] - (return-array (shim/aget nodes 0) (shim/aget nodes 1) right)) + (return-array (da/aget nodes 0) (da/aget nodes 1) right)) ;; right has fewer nodes, redestribute with it :else (let [nodes (node-merge-n-split node right)] - (return-array left (shim/aget nodes 0) (shim/aget nodes 1))))) + (return-array left (da/aget nodes 0) (da/aget nodes 1))))) (deftype Node [keys pointers] INode @@ -297,35 +306,35 @@ (alast keys)) (node-len [_] - (shim/alength keys)) + (da/alength keys)) (node-merge [_ next] - (Node. (shim/aconcat keys (.-keys ^Node next)) - (shim/aconcat pointers (.-pointers ^Node next)))) + (Node. (da/aconcat keys (.-keys ^Node next)) + (da/aconcat pointers (.-pointers ^Node next)))) (node-merge-n-split [_ next] (let [ks (merge-n-split keys (.-keys ^Node next)) ps (merge-n-split pointers (.-pointers ^Node next))] - (return-array (Node. (shim/aget ks 0) (shim/aget ps 0)) - (Node. (shim/aget ks 1) (shim/aget ps 1))))) + (return-array (Node. (da/aget ks 0) (da/aget ps 0)) + (Node. (da/aget ks 1) (da/aget ps 1))))) (node-lookup [_ cmp key] (let [idx (lookup-range cmp keys key)] (when-not (== -1 idx) - (node-lookup (shim/aget pointers idx) cmp key)))) + (node-lookup (da/aget pointers idx) cmp key)))) (node-conj [_ cmp key] - (let [idx (binary-search-l cmp keys (- (shim/alength keys) 2) key) - nodes (node-conj (shim/aget pointers idx) cmp key)] + (let [idx (binary-search-l cmp keys (- (da/alength keys) 2) key) + nodes (node-conj (da/aget pointers idx) cmp key)] (when nodes - (let [new-keys (check-n-splice cmp keys idx (inc idx) (shim/amap node-lim-key nodes)) + (let [new-keys (check-n-splice cmp keys idx (inc idx) (da/amap node-lim-key nodes)) new-pointers (splice pointers idx (inc idx) nodes)] - (if (<= (shim/alength new-pointers) max-len) + (if (<= (da/alength new-pointers) max-len) ;; ok as is - (shim/array (Node. new-keys new-pointers)) + (da/array (Node. new-keys new-pointers)) ;; gotta split it up - (let [middle (shim/half (shim/alength new-pointers))] - (shim/array + (let [middle (half (da/alength new-pointers))] + (da/array (Node. (cut new-keys 0 middle) (cut new-pointers 0 middle)) (Node. (cut new-keys middle) @@ -334,16 +343,16 @@ (node-disj [_ cmp key root? left right] (let [idx (lookup-range cmp keys key)] (when-not (== -1 idx) ;; short-circuit, key not here - (let [child (shim/aget pointers idx) + (let [child (da/aget pointers idx) left-child (when (>= (dec idx) 0) - (shim/aget pointers (dec idx))) - right-child (when (< (inc idx) (shim/alength pointers)) - (shim/aget pointers (inc idx))) + (da/aget pointers (dec idx))) + right-child (when (< (inc idx) (da/alength pointers)) + (da/aget pointers (inc idx))) disjned (node-disj child cmp key false left-child right-child)] (when disjned ;; short-circuit, key not here (let [left-idx (if left-child (dec idx) idx) right-idx (if right-child (+ 2 idx) (+ 1 idx)) - new-keys (check-n-splice cmp keys left-idx right-idx (shim/amap node-lim-key disjned)) + new-keys (check-n-splice cmp keys left-idx right-idx (da/amap node-lim-key disjned)) new-pointers (splice pointers left-idx right-idx disjned)] (rotate (Node. new-keys new-pointers) root? left right)))))))) @@ -355,51 +364,51 @@ ;; (toString [_] (pr-str* (vec keys))) (node-len [_] - (shim/alength keys)) + (da/alength keys)) (node-merge [_ next] - (Leaf. (shim/aconcat keys (.-keys ^Leaf next)))) + (Leaf. (da/aconcat keys (.-keys ^Leaf next)))) (node-merge-n-split [_ next] (let [ks (merge-n-split keys (.-keys ^Leaf next))] - (return-array (Leaf. (shim/aget ks 0)) - (Leaf. (shim/aget ks 1))))) + (return-array (Leaf. (da/aget ks 0)) + (Leaf. (da/aget ks 1))))) (node-lookup [_ cmp key] (let [idx (lookup-exact cmp keys key)] (when-not (== -1 idx) - (shim/aget keys idx)))) + (da/aget keys idx)))) (node-conj [_ cmp key] - (let [idx (binary-search-l cmp keys (dec (shim/alength keys)) key) - keys-l (shim/alength keys)] + (let [idx (binary-search-l cmp keys (dec (da/alength keys)) key) + keys-l (da/alength keys)] (cond ;; element already here (and (< idx keys-l) - (== 0 (cmp key (shim/aget keys idx)))) + (== 0 (cmp key (da/aget keys idx)))) nil ;; splitting (== keys-l max-len) - (let [middle (shim/half (inc keys-l))] + (let [middle (half (inc keys-l))] (if (> idx middle) ;; new key goes to the second half - (shim/array + (da/array (Leaf. (cut keys 0 middle)) - (Leaf. (cut-n-splice keys middle keys-l idx idx (shim/array key)))) + (Leaf. (cut-n-splice keys middle keys-l idx idx (da/array key)))) ;; new key goes to the first half - (shim/array - (Leaf. (cut-n-splice keys 0 middle idx idx (shim/array key))) + (da/array + (Leaf. (cut-n-splice keys 0 middle idx idx (da/array key))) (Leaf. (cut keys middle keys-l))))) ;; ok as is :else - (shim/array (Leaf. (splice keys idx idx (shim/array key))))))) + (da/array (Leaf. (splice keys idx idx (da/array key))))))) (node-disj [_ cmp key root? left right] (let [idx (lookup-exact cmp keys key)] (when-not (== -1 idx) ;; key is here - (let [new-keys (splice keys idx (inc idx) (shim/array))] + (let [new-keys (splice keys idx (inc idx) (da/array))] (rotate (Leaf. new-keys) root? left right)))))) ;; BTSet @@ -424,7 +433,7 @@ (-meta [_] meta) IEmptyableCollection - (-empty [_] (BTSet. (Leaf. (shim/array)) 0 0 comparator meta uninitialized-hash)) + (-empty [_] (BTSet. (Leaf. (da/array)) 0 0 comparator meta uninitialized-hash)) IEquiv (-equiv [this other] @@ -501,7 +510,7 @@ start)) clojure.lang.IPersistentCollection - (empty [_] (BTSet. (Leaf. (shim/array)) 0 0 comparator meta uninitialized-hash)) + (empty [_] (BTSet. (Leaf. (da/array)) 0 0 comparator meta uninitialized-hash)) (cons [this key] (btset-conj this key comparator)) (equiv [this other] (and @@ -559,7 +568,7 @@ node (.-root set)] (if (pos? level) (recur (- level level-shift) - (shim/aget (.-pointers ^Node node) + (da/aget (.-pointers ^Node node) (path-get path level))) (.-keys ^Leaf node)))) @@ -571,16 +580,16 @@ set ;; keeping single root - (== (shim/alength roots) 1) + (== (da/alength roots) 1) (alter-btset set - (shim/aget roots 0) + (da/aget roots 0) (.-shift set) (inc (.-cnt set))) ;; introducing new root :else (alter-btset set - (Node. (shim/amap node-lim-key roots) roots) + (Node. (da/amap node-lim-key roots) roots) (+ (.-shift set) level-shift) (inc (.-cnt set)))))) @@ -588,13 +597,13 @@ (let [new-roots (node-disj (.-root set) cmp key true nil nil)] (if (nil? new-roots) ;; nothing changed, key wasn't in the set set - (let [new-root (shim/aget new-roots 0)] + (let [new-root (da/aget new-roots 0)] (if (and (instance? Node new-root) - (== 1 (shim/alength (.-pointers ^Node new-root)))) + (== 1 (da/alength (.-pointers ^Node new-root)))) ;; root has one child, make him new root (alter-btset set - (shim/aget (.-pointers ^Node new-root) 0) + (da/aget (.-pointers ^Node new-root) 0) (- (.-shift set) level-shift) (dec (.-cnt set))) @@ -611,10 +620,10 @@ (let [idx (path-get path level)] (if (pos? level) ;; inner node - (let [sub-path (-next-path (shim/aget (.-pointers ^Node node) idx) path (- level level-shift))] + (let [sub-path (-next-path (da/aget (.-pointers ^Node node) idx) path (- level level-shift))] (if (== -1 sub-path) ;; nested node overflow - (if (< (inc idx) (shim/alength (.-pointers ^Node node))) + (if (< (inc idx) (da/alength (.-pointers ^Node node))) ;; advance current node idx, reset subsequent indexes (path-set empty-path level (inc idx)) ;; current node overflow @@ -622,7 +631,7 @@ ;; keep current idx (path-set sub-path level idx))) ;; leaf - (if (< (inc idx) (shim/alength (.-keys ^Leaf node))) + (if (< (inc idx) (da/alength (.-keys ^Leaf node))) ;; advance leaf idx (path-set empty-path 0 (inc idx)) ;; leaf overflow @@ -643,23 +652,23 @@ (if (pos? level) ;; inner node (recur (alast (.-pointers ^Node node)) - (path-set path level (dec (shim/alength (.-pointers ^Node node)))) + (path-set path level (dec (da/alength (.-pointers ^Node node)))) (- level level-shift)) ;; leaf - (path-set path 0 (dec (shim/alength (.-keys ^Leaf node))))))) + (path-set path 0 (dec (da/alength (.-keys ^Leaf node))))))) (defn -prev-path ^long [node ^long path ^long level] (let [idx (path-get path level)] (if (pos? level) ;; inner node (let [sub-level (- level level-shift) - sub-path (-prev-path (shim/aget (.-pointers ^Node node) idx) path sub-level)] + sub-path (-prev-path (da/aget (.-pointers ^Node node) idx) path sub-level)] (if (== -1 sub-path) ;; nested node overflow (if (>= (dec idx) 0) ;; advance current node idx, reset subsequent indexes (let [idx (dec idx) - sub-path (-rpath (shim/aget (.-pointers ^Node node) idx) sub-level)] + sub-path (-rpath (da/aget (.-pointers ^Node node) idx) sub-level)] (path-set sub-path level idx)) ;; current node overflow -1) @@ -748,7 +757,7 @@ (defn iter-first [^Iter iter] (when (.-keys iter) - (shim/aget (.-keys iter) (.-idx iter)))) + (da/aget (.-keys iter) (.-idx iter)))) (defn iter-next [^Iter iter] (let [set (.-set iter) @@ -757,7 +766,7 @@ keys (.-keys iter) idx (.-idx iter)] (when keys - (if (< (inc idx) (shim/alength keys)) + (if (< (inc idx) (da/alength keys)) ;; can use cached array to move forward (when (< (inc left) right) (Iter. set (inc left) right keys (inc idx))) @@ -773,7 +782,7 @@ end-idx (if (= (bit-or left path-mask) (bit-or right path-mask)) (bit-and right path-mask) - (shim/alength keys))] + (da/alength keys))] (#?(:clj clojure.lang.ArrayChunk. :cljs array-chunk) keys idx end-idx))) @@ -783,7 +792,7 @@ right (.-right iter) keys (.-keys iter) idx (.-idx iter)] - (let [left (next-path set (+ left (- (shim/alength keys) idx 1)))] + (let [left (next-path set (+ left (- (da/alength keys) idx 1)))] (when (and (not= -1 left) (< left right)) (datascript.btset/iter set left right))))) @@ -814,14 +823,14 @@ (reduced? acc) @acc (nil? keys) acc :else - (let [new-acc (f acc (shim/aget keys idx))] - (if (< (inc idx) (shim/alength keys)) + (let [new-acc (f acc (da/aget keys idx))] + (if (< (inc idx) (da/alength keys)) ;; can use cached array to move forward (if (< (inc left) right) (recur (inc left) keys (inc idx) new-acc) new-acc) (let [new-left (next-path set left)] - (if (and (shim/not== -1 new-left) (< new-left right)) + (if (and (not== -1 new-left) (< new-left right)) (recur new-left (keys-for set new-left) (path-get new-left 0) new-acc) new-acc))))))))) @@ -871,7 +880,7 @@ (defn riter-first [^ReverseIter riter] (when (.-keys riter) - (shim/aget (.-keys riter) (.-idx riter)))) + (da/aget (.-keys riter) (.-idx riter)))) (defn riter-next [^ReverseIter ri] (let [set (.-set ri) @@ -907,7 +916,7 @@ (if (pos? level) ;; inner node (if (== idx-l idx-r) - (-distance (shim/aget (.-pointers ^Node node) idx-l) left right (- level level-shift)) + (-distance (da/aget (.-pointers ^Node node) idx-l) left right (- level level-shift)) (loop [level level res (- idx-r idx-l)] (if (== 0 level) @@ -942,7 +951,7 @@ (if (== keys-l idx) -1 (path-set path 0 idx))) (let [keys (.-keys ^Node node) idx (binary-search-l (.-comparator set) keys (- keys-l 2) key)] - (recur (shim/aget (.-pointers ^Node node) idx) + (recur (da/aget (.-pointers ^Node node) idx) (path-set path level idx) (- level level-shift))))))) @@ -961,7 +970,7 @@ (path-set path 0 idx)) (let [keys (.-keys ^Node node) idx (binary-search-r (.-comparator set) keys (- keys-l 2) key)] - (recur (shim/aget (.-pointers ^Node node) idx) + (recur (da/aget (.-pointers ^Node node) idx) (path-set path level idx) (- level level-shift))))))) @@ -988,19 +997,19 @@ (loop [current-level leafs shift 0] (case (count current-level) - 0 (BTSet. (Leaf. (shim/array)) 0 0 cmp nil uninitialized-hash) - 1 (BTSet. (first current-level) shift (shim/alength arr) cmp nil uninitialized-hash) + 0 (BTSet. (Leaf. (da/array)) 0 0 cmp nil uninitialized-hash) + 1 (BTSet. (first current-level) shift (da/alength arr) cmp nil uninitialized-hash) (recur (->> current-level (arr-partition-approx min-len max-len) - (arr-map-inplace #(Node. (shim/amap node-lim-key %) %))) + (arr-map-inplace #(Node. (da/amap node-lim-key %) %))) (+ shift level-shift)))))) (defn -btset-from-seq [seq cmp] ;; TODO avoid array? - (let [arr (-> seq into-array (shim/asort cmp) (sorted-arr-distinct cmp))] + (let [arr (-> seq into-array (da/asort cmp) (sorted-arr-distinct cmp))] (-btset-from-sorted-arr arr cmp))) (defn btset-by - ([cmp] (BTSet. (Leaf. (shim/array)) 0 0 cmp nil uninitialized-hash)) + ([cmp] (BTSet. (Leaf. (da/array)) 0 0 cmp nil uninitialized-hash)) ([cmp & keys] (-btset-from-seq keys cmp))) diff --git a/src/datascript/db.cljc b/src/datascript/db.cljc index 868c7b22..615cfacf 100644 --- a/src/datascript/db.cljc +++ b/src/datascript/db.cljc @@ -1,10 +1,11 @@ (ns datascript.db - #?(:cljs (:require-macros [datascript.db :refer [case-tree combine-cmp raise defrecord-updatable]])) (:require #?(:cljs [goog.array :as garray]) clojure.walk - [datascript.shim :as shim] - [datascript.btset :as btset])) + [datascript.arrays :as da] + [datascript.btset :as btset]) + #?(:cljs (:require-macros [datascript.db :refer [case-tree combine-cmp raise defrecord-updatable]])) + (:refer-clojure :exclude [seqable?])) ;; ---------------------------------------------------------------------------- @@ -25,6 +26,19 @@ data (last fragments)] `(throw (ex-info (str ~@(map (fn [m#] (if (string? m#) m# (list 'pr-str m#))) msgs)) ~data))))) +(def seqable? + #?(:cljs cljs.core/seqable? + :clj (fn seqable? [x] + (or (seq? x) + (instance? clojure.lang.Seqable x) + (nil? x) + (instance? Iterable x) + (da/array? x) + (string? x) + (instance? java.util.Map x))))) + +(def neg-number? (every-pred number? neg?)) + ;; ---------------------------------------------------------------------------- ;; macros and funcs to support writing defrecords and updating ;; (replacing) builtins, i.e., Object/hashCode, IHashEq hasheq, etc. @@ -559,7 +573,7 @@ rschema (rschema schema) indexed (:db/index rschema) #?@(:cljs - [ds-arr (shim/into-array datoms) + [ds-arr (da/into-array datoms) eavt (btset/-btset-from-sorted-arr (.sort ds-arr cmp-datoms-eavt-quick) cmp-datoms-eavt) aevt (btset/-btset-from-sorted-arr (.sort ds-arr cmp-datoms-aevt-quick) cmp-datoms-aevt) avet-datoms (-> (reduce (fn [arr d] @@ -860,7 +874,7 @@ [vs] ;; not a collection at all, so definitely a single value - (not (or (shim/array? vs) + (not (or (da/array? vs) (and (coll? vs) (not (map? vs))))) [vs] @@ -934,7 +948,7 @@ (let [old-eid (:db/id entity) known-eid (->> (cond - (shim/neg-number? old-eid) (get-in report [:tempids old-eid]) + (neg-number? old-eid) (get-in report [:tempids old-eid]) (tx-id? old-eid) (current-tx report) :else old-eid) (entid-some db)) @@ -943,7 +957,7 @@ new-entity (assoc upserted :db/id new-eid) new-report (cond (nil? old-eid) (allocate-eid report new-eid) - (shim/neg-number? old-eid) (allocate-eid report old-eid new-eid) + (neg-number? old-eid) (allocate-eid report old-eid new-eid) (and (number? old-eid) (> old-eid (:max-eid db))) (allocate-eid report old-eid) :else report)] @@ -982,12 +996,12 @@ (and (ref? db a) (tx-id? v)) (recur report (concat [[op e a (current-tx report)]] entities)) - (shim/neg-number? e) + (neg-number? e) (if-let [eid (get-in report [:tempids e])] (recur report (concat [[op eid a v]] entities)) (recur (allocate-eid report e (next-eid db)) es)) - (and (ref? db a) (shim/neg-number? v)) + (and (ref? db a) (neg-number? v)) (if-let [vid (get-in report [:tempids v])] (recur report (concat [[op e a vid]] entities)) (recur (allocate-eid report v (next-eid db)) es)) diff --git a/src/datascript/parser.cljc b/src/datascript/parser.cljc index c1e4c5ec..70a03539 100644 --- a/src/datascript/parser.cljc +++ b/src/datascript/parser.cljc @@ -3,8 +3,7 @@ #?(:cljs (:require-macros [datascript.parser :refer [deftrecord]])) (:require [clojure.set :as set] - [datascript.shim :as shim] - [datascript.db #?(:cljs :refer-macros :clj :refer) [raise]])) + [datascript.db :as db #?(:cljs :refer-macros :clj :refer) [raise]])) ;; utils @@ -53,7 +52,7 @@ (cond (pred form) (conj acc form) (satisfies? ITraversable form) (-collect form pred acc) - (shim/seqable? form) (reduce (fn [acc form] (collect pred form acc)) acc form) + (db/seqable? form) (reduce (fn [acc form] (collect pred form acc)) acc form) :else acc))) (defn distinct? [coll] diff --git a/src/datascript/query.cljc b/src/datascript/query.cljc index 37839ee3..cc0407e5 100644 --- a/src/datascript/query.cljc +++ b/src/datascript/query.cljc @@ -4,7 +4,7 @@ [clojure.set :as set] [clojure.walk :as walk] [datascript.db :as db #?(:cljs :refer-macros :clj :refer) [raise]] - [datascript.shim :as shim] + [datascript.arrays :as da] [datascript.lru] [datascript.impl.entity :as de] [datascript.parser :as dp #?@(:cljs [:refer [BindColl BindIgnore BindScalar BindTuple Constant @@ -84,7 +84,7 @@ :clj ^{:tag "[[Ljava.lang.Object;"} idxs2)] (let [l1 (alength idxs1) l2 (alength idxs2) - res (shim/make-array (+ l1 l2))] + res (da/make-array (+ l1 l2))] (dotimes [i l1] (aset res i (#?(:cljs aget :clj get) t1 (aget idxs1 i)))) ;; FIXME aget (dotimes [i l2] @@ -95,7 +95,7 @@ (Relation. (:attrs a) (concat (:tuples a) (:tuples b)))) (defn prod-rel - ([] (Relation. {} [(shim/make-array 0)])) + ([] (Relation. {} [(da/make-array 0)])) ([rel1 rel2] (let [attrs1 (keys (:attrs rel1)) attrs2 (keys (:attrs rel2)) @@ -218,7 +218,7 @@ (group-by ffirst rules))) (defn bindable-to-seq? [x] - (or (shim/seqable? x) (shim/array? x))) + (or (db/seqable? x) (da/array? x))) (defn empty-rel [binding] (let [vars (->> (dp/collect-vars-distinct binding) @@ -299,7 +299,7 @@ (let [getters (to-array getters)] (fn [tuple] (list* #?(:cljs (.map getters #(% tuple)) - :clj (shim/into-array (map #(% tuple) getters)))))))) + :clj (da/into-array (map #(% tuple) getters)))))))) (defn hash-attrs [key-fn tuples] (loop [tuples tuples @@ -604,7 +604,7 @@ (defn -collect ([context symbols] (let [rels (:rels context)] - (-collect [(shim/make-array (count symbols))] rels symbols))) + (-collect [(da/make-array (count symbols))] rels symbols))) ([acc rels symbols] (if-let [rel (first rels)] (let [keep-attrs (select-keys (:attrs rel) symbols)] diff --git a/src/datascript/query_v3.cljc b/src/datascript/query_v3.cljc index 5026ade8..fae8630c 100644 --- a/src/datascript/query_v3.cljc +++ b/src/datascript/query_v3.cljc @@ -5,7 +5,7 @@ [datascript.db :as db] [datascript.query :as dq] [datascript.lru :as lru] - [datascript.shim :as shim] + [datascript.arrays :as da] [datascript.parser :as dp #?@(:cljs [:refer [BindColl BindIgnore BindScalar BindTuple Constant DefaultSrc Pattern RulesVar SrcVar Variable Not Or And Predicate PlainSymbol]])] @@ -26,17 +26,24 @@ (def ^:const lru-cache-size 100) (defn mapa [f coll] - (shim/into-array (map f coll))) + (da/into-array (map f coll))) (defn arange [start end] - (shim/into-array (range start end))) + (da/into-array (range start end))) (defn subarr [arr start end] - (shim/acopy arr start end (shim/make-array (- end start)) 0)) + (da/acopy arr start end (da/make-array (- end start)) 0)) (defn concatv [& xs] (into [] cat xs)) +(defn zip + ([a b] (map vector a b)) + ([a b & rest] (apply map vector a b rest))) + +(defn has? [coll el] + (some #(= el %) coll)) + (defprotocol NativeColl (-native-coll [_])) @@ -96,7 +103,7 @@ (recur (inc i) (f res (.get l i))) res))))) :cljs - (let [arr (shim/array)] + (let [arr (da/array)] (reify NativeColl (-native-coll [_] arr) @@ -167,7 +174,7 @@ ;; (defn- #?@(:clj [^long hash-arr] ;; :cljs [^number hash-arr]) [arr] -;; (let [count (int (shim/alength arr))] +;; (let [count (int (da/alength arr))] ;; (loop [n (int 0) ;; hash-code (int 1)] ;; (if (== n count) @@ -175,9 +182,9 @@ ;; (recur (inc n) ;; #?(:clj (unchecked-add-int ;; (unchecked-multiply-int 31 hash-code) -;; (hash (shim/aget arr n))) +;; (hash (da/aget arr n))) ;; :cljs (bit-or (+ (imul 31 hash-code) -;; (hash (shim/aget arr n))) +;; (hash (da/aget arr n))) ;; 0))))))) ;; (declare equiv-tuple) @@ -200,12 +207,12 @@ ;; (defn equiv-tuple [^Tuple t ^Tuple o] ;; (boolean ;; (and -;; (== (shim/alength (.-arr t)) -;; (shim/alength (.-arr o))) +;; (== (da/alength (.-arr t)) +;; (da/alength (.-arr o))) ;; (loop [i 0] ;; (cond -;; (== i (shim/alength (.-arr t))) true -;; (not= (shim/aget (.-arr t) i) (shim/aget (.-arr o) i)) false +;; (== i (da/alength (.-arr t))) true +;; (not= (da/aget (.-arr t) i) (da/aget (.-arr o) i)) false ;; :else (recur (inc i))))))) ;; (defn tuple [arr] @@ -237,12 +244,12 @@ (-getter [_ symbol] (let [idx (offset-map symbol)] (fn [tuple] - (shim/aget tuple idx)))) + (da/aget tuple idx)))) (-indexes [_ syms] (mapa offset-map syms)) (-copy-tuple [_ tuple idxs target target-idxs] - (dotimes [i (shim/alength idxs)] - (shim/aset target (shim/aget target-idxs i) (shim/aget tuple (shim/aget idxs i))))) + (dotimes [i (da/alength idxs)] + (da/aset target (da/aget target-idxs i) (da/aget tuple (da/aget idxs i))))) (-union [_ rel] (assert (instance? ArrayRelation rel)) (assert (= offset-map (:offset-map rel))) @@ -277,8 +284,8 @@ (-indexes [_ syms] (mapa offset-map syms)) (-copy-tuple [_ tuple idxs target target-idxs] - (dotimes [i (shim/alength idxs)] - (shim/aset target (shim/aget target-idxs i) (nth tuple (shim/aget idxs i))))) + (dotimes [i (da/alength idxs)] + (da/aset target (da/aget target-idxs i) (nth tuple (da/aget idxs i))))) (-union [_ rel] (assert (instance? CollRelation rel)) (assert (= offset-map (:offset-map rel))) @@ -316,7 +323,7 @@ ;; (fn [acc t1] ;; (-fold rel2 ;; (fn [acc t2] -;; (f acc (shim/array t1 t2))) +;; (f acc (da/array t1 t2))) ;; acc)) ;; init)) @@ -326,10 +333,10 @@ ;; (if (some #{symbol} (-symbols rel1)) ;; (let [getter (-getter rel1 symbol)] ;; (fn [tuple] -;; (getter (shim/aget tuple 0)))) +;; (getter (da/aget tuple 0)))) ;; (let [getter (-getter rel2 symbol)] ;; (fn [tuple] -;; (getter (shim/aget tuple 1)))))) +;; (getter (da/aget tuple 1)))))) ;; (-indexes [_ syms] ;; (let [[syms1 syms2] (split-with (set (-symbols rel1)) syms)] ;; [(-indexes rel1 syms1) @@ -339,9 +346,9 @@ ;; (-copy-tuple [_ tuple idxs target target-idxs] ;; (let [[idxs1 arity1 idxs2 arity2] idxs ;; target-idxs1 (subarr target-idxs 0 arity1) -;; target-idxs2 (subarr target-idxs arity1 (shim/alength target-idxs))] -;; (-copy-tuple rel1 (shim/aget tuple 0) idxs1 target target-idxs1) -;; (-copy-tuple rel2 (shim/aget tuple 1) idxs2 target target-idxs2)))) +;; target-idxs2 (subarr target-idxs arity1 (da/alength target-idxs))] +;; (-copy-tuple rel1 (da/aget tuple 0) idxs1 target target-idxs1) +;; (-copy-tuple rel2 (da/aget tuple 1) idxs2 target target-idxs2)))) ;; (def prod-rel ->ProdRelation) @@ -352,9 +359,9 @@ IRelation (-symbols [_] []) (-arity [_] 0) - (-fold [_ f init] (f init (shim/into-array []))) + (-fold [_ f init] (f init (da/into-array []))) (-size [_] 1) - (-indexes [_ _] (shim/into-array [])) + (-indexes [_ _] (da/into-array [])) (-copy-tuple [_ _ _ _ _])) (def singleton-rel ->SingletonRelation) @@ -365,7 +372,7 @@ rel2 t2 idxs2 arity target-idxs1 target-idxs2] - (let [arr (shim/make-array arity)] + (let [arr (da/make-array arity)] (-copy-tuple rel1 t1 idxs1 arr target-idxs1) (-copy-tuple rel2 t2 idxs2 arr target-idxs2) arr)) @@ -410,7 +417,7 @@ (let [idxs (-indexes rel syms) target-idxs (arange 0 arity)] (fn [t] - (let [arr (shim/make-array arity)] + (let [arr (da/make-array arity)] (-copy-tuple rel t idxs arr target-idxs) (vec arr))))))) @@ -463,7 +470,7 @@ (defn- bindable-to-seq? [x] - (or (shim/seqable? x) (shim/array? x))) + (or (db/seqable? x) (da/array? x))) (defn- bind! [tuples binding source indexes] @@ -475,7 +482,7 @@ BindScalar (let [symbol (get-in binding [:variable :symbol]) idx (get indexes symbol)] - (run! #(shim/aset % idx source) tuples) + (run! #(da/aset % idx source) tuples) tuples) BindColl @@ -489,7 +496,7 @@ (into [] ;; TODO fast-arr (comp (map #(bind! tuples inner-binding % indexes)) cat - (map shim/aclone)) + (map da/aclone)) source)))) BindTuple @@ -503,7 +510,7 @@ (reduce (fn [ts [b s]] (bind! ts b s indexes)) tuples - (shim/zip bindings source))) + (zip bindings source))) :else (db/raise "Unknown binding form " (dp/source binding) @@ -513,7 +520,7 @@ (defn bind [binding source] (let [syms (map :symbol (dp/collect-vars-distinct binding)) indexes (zipmap syms (range)) - tuples (bind! [(shim/make-array (count syms))] binding source indexes)] + tuples (bind! [(da/make-array (count syms))] binding source indexes)] (array-rel syms tuples))) @@ -542,7 +549,7 @@ (db/raise "Wrong number of arguments for bindings " (mapv dp/source bindings) ", " (count bindings) " required, " (count values) " provided" {:error :query/binding, :binding (mapv dp/source bindings)})) - (reduce resolve-in context (shim/zip bindings values))) + (reduce resolve-in context (zip bindings values))) ;;; Resolution @@ -803,19 +810,19 @@ (defn collect-args! [context args target form] (let [consts (:consts context) sources (:sources context)] - (doseq [[arg i] (shim/zip args (range)) + (doseq [[arg i] (zip args (range)) :let [sym (:symbol arg)]] (cond (instance? Variable arg) (when (contains? consts sym) - (shim/aset target i (get consts sym))) + (da/aset target i (get consts sym))) (instance? SrcVar arg) (if (contains? sources sym) - (shim/aset target i (get sources sym)) + (da/aset target i (get sources sym)) (throw (ex-info (str "Unbound source variable: " sym " in " form) { :error :query/where, :form form, :var sym }))) (instance? Constant arg) - (shim/aset target i (:value arg)))))) + (da/aset target i (:value arg)))))) (defn get-f [context fun form] @@ -834,10 +841,10 @@ (let [{fun :fn, args :args} clause form (dp/source clause) f (get-f context fun form) - args-arr (shim/make-array (count args)) + args-arr (da/make-array (count args)) _ (collect-args! context args args-arr form) consts (:consts context) - sym+idx (for [[arg i] (shim/zip args (range)) + sym+idx (for [[arg i] (zip args (range)) :when (instance? Variable arg) :let [sym (:symbol arg)] :when (not (contains? consts sym))] @@ -859,7 +866,7 @@ rel* (-alter-coll rel #(filterv pred %))] (join-unrelated context* rel*)) (let [prod-syms (mapcat -symbols rels) - prod-sym+idx (shim/zip prod-syms (range)) + prod-sym+idx (zip prod-syms (range)) xfs (map #(collect-rel-xf prod-sym+idx %) rels) prod-rel (array-rel prod-syms []) @@ -870,7 +877,7 @@ array (into (fast-arr) (apply comp (concat xfs [(filter pred)])) - [(shim/make-array (count prod-syms))]) + [(da/make-array (count prod-syms))]) prod-rel* (array-rel prod-syms array)] (join-unrelated context* prod-rel*)))))) "resolve-predicate" (dp/source clause))) @@ -919,12 +926,12 @@ (doseq [[sym i] syms-indexed] (when (contains? consts sym) (let [val (get consts sym)] - (shim/aset specimen i val))))) + (da/aset specimen i val))))) (defn collect-rel-xf [syms-indexed rel] (let [sym+idx (for [[sym i] syms-indexed - :when (shim/has? (-symbols rel) sym)] + :when (has? (-symbols rel) sym)] [sym i]) idxs (-indexes rel (map first sym+idx)) target-idxs (mapa second sym+idx)] @@ -936,7 +943,7 @@ ([result specimen] (-fold rel (fn [acc tuple] - (let [t (shim/aclone specimen)] + (let [t (da/aclone specimen)] (-copy-tuple rel tuple idxs t target-idxs) (rf acc t))) result)))))) @@ -944,15 +951,15 @@ (defn collect-to ([context syms acc] - (collect-to context syms acc [] (shim/make-array (count syms)))) + (collect-to context syms acc [] (da/make-array (count syms)))) ([context syms acc xfs] - (collect-to context syms acc xfs (shim/make-array (count syms)))) + (collect-to context syms acc xfs (da/make-array (count syms)))) ([context syms acc xfs specimen] ;; TODO don't collect if array-rel and matches symbols (perf/measure (if (:empty? context) acc - (let [syms-indexed (vec (shim/zip syms (range))) + (let [syms-indexed (vec (zip syms (range))) _ (collect-consts syms-indexed specimen (:consts context)) related-rels (related-rels context syms) xfs (-> (map #(collect-rel-xf syms-indexed %) related-rels) diff --git a/test/datascript/test/explode.cljc b/test/datascript/test/explode.cljc index f084762b..7c33bf6e 100644 --- a/test/datascript/test/explode.cljc +++ b/test/datascript/test/explode.cljc @@ -3,7 +3,7 @@ #?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]] :clj [clojure.test :as t :refer [is are deftest testing]]) [datascript.core :as d] - [datascript.shim :as shim] + [datascript.arrays :as da] [datascript.db :as db] [datascript.test.core :as tdc])) @@ -14,7 +14,7 @@ (doseq [coll [["Devil" "Tupen"] #{"Devil" "Tupen"} '("Devil" "Tupen") - (shim/into-array ["Devil" "Tupen"])]] + (da/into-array ["Devil" "Tupen"])]] (testing coll (let [conn (d/create-conn { :aka { :db/cardinality :db.cardinality/many } :also { :db/cardinality :db.cardinality/many} })]