git.fiddlerwoaroof.com
Raw Blame History
(ns datascript.arrays
  (:require
    [clojure.string :as str])
  (: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 (defn ^array make-array [size] (js/Array. size))
   :clj  (defn make-array ^{:tag "[[Ljava.lang.Object;"}
           [size]
           (clojure.core/make-array java.lang.Object size)))

#?(:cljs (defn ^array into-array [aseq]
           (reduce (fn [a x] (.push a x) a) (js/Array.) aseq))
   :clj  (defn into-array ^{:tag "[[Ljava.lang.Object;"}
           [aseq]
           (clojure.core/into-array java.lang.Object aseq)))

#?(:clj
  (defmacro aget [arr i]
    (if-cljs &env
      (list 'js* "(~{}[~{}])" arr i)
     `(clojure.lang.RT/aget ~(vary-meta arr assoc :tag "[[Ljava.lang.Object;") (int ~i)))))

#?(:clj
  (defmacro alength [arr]
    (if-cljs &env
      (-> (list 'js* "~{}.length" arr)
          (vary-meta assoc :tag 'number))
     `(clojure.lang.RT/alength ~(vary-meta arr assoc :tag "[[Ljava.lang.Object;")))))

#?(:clj
  (defmacro aset [arr i v]
    (if-cljs &env
      (list 'js* "(~{}[~{}] = ~{})" arr i v)
     `(clojure.lang.RT/aset ~(vary-meta arr assoc :tag "[[Ljava.lang.Object;") (int ~i) ~v))))

#?(:clj
  (defmacro array [& args]
    (if-cljs &env
      (->
        (list* 'js* (str "[" (str/join "," (repeat (count args) "~{}")) "]") args)
        (vary-meta assoc :tag 'array))
      (let [len (count args)]
        (if (zero? len)
          'clojure.lang.RT/EMPTY_ARRAY
         `(let [arr# (clojure.core/make-array java.lang.Object ~len)]
            (doto ^{:tag "[[Ljava.lang.Object;"} arr#
            ~@(map #(list 'aset % (nth args %)) (range len)))))))))

#?(:clj
  (defmacro acopy [from from-start from-end to to-start]
    (if-cljs &env
     `(let [l# (- ~from-end ~from-start)]
        (dotimes [i# l#]
          (aset ~to (+ i# ~to-start) (aget ~from (+ i# ~from-start)))))
     `(let [l# (- ~from-end ~from-start)]
        (when (pos? l#)
          (System/arraycopy ~from ~from-start ~to ~to-start l#))))))

(defn aclone [from]
  #?(:clj  (Arrays/copyOf ^{:tag "[[Ljava.lang.Object;"} from (alength from))
     :cljs (.slice from 0)))

(defn aconcat [a b]
  #?(:cljs (.concat a b)
     :clj  (let [al  (alength a)
                 bl  (alength b)
                 res (Arrays/copyOf ^{:tag "[[Ljava.lang.Object;"} a (+ al bl))]
             (System/arraycopy ^{:tag "[[Ljava.lang.Object;"} b 0 res al bl)
             res)))

(defn amap [f arr]
  #?(:cljs (.map arr f)
     :clj  (clojure.core/amap ^{:tag "[[Ljava.lang.Object;"} arr i res (f (aget arr i)))))

(defn asort [arr cmp]
  #?(:cljs (.sort arr cmp)
     :clj  (doto arr (java.util.Arrays/sort cmp))))

#?(:cljs (defn ^boolean array? [x]
           (if (identical? *target* "nodejs")
             (.isArray js/Array x)
             (instance? js/Array x)))
   :clj  (defn array? [^Object x] (-> x .getClass .isArray)))