partial refactoring to prepare for cljs compatibility
This commit is contained in:
parent
5aa3bc5da2
commit
7a4caa5b61
4 changed files with 153 additions and 131 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
(ns com.rpl.specter
|
(ns com.rpl.specter
|
||||||
(:use [com.rpl.specter.protocols :only [StructurePath]])
|
(:use [com.rpl.specter.protocols :only [StructurePath]]
|
||||||
(:require [com.rpl.specter.impl :as i])
|
)
|
||||||
|
(:require [com.rpl.specter.impl :as i]
|
||||||
|
[com.rpl.specter.macros :as m])
|
||||||
)
|
)
|
||||||
|
|
||||||
(defn comp-paths [& paths]
|
(defn comp-paths [& paths]
|
||||||
|
|
@ -118,8 +120,8 @@
|
||||||
that needed parameters (in the order in which they were declared)."
|
that needed parameters (in the order in which they were declared)."
|
||||||
[params & impls]
|
[params & impls]
|
||||||
(let [num-params (count params)
|
(let [num-params (count params)
|
||||||
retrieve-params (i/make-param-retrievers params)]
|
retrieve-params (m/make-param-retrievers params)]
|
||||||
(i/paramspath* retrieve-params num-params impls)
|
(m/paramspath* retrieve-params num-params impls)
|
||||||
))
|
))
|
||||||
|
|
||||||
(defmacro paramscollector
|
(defmacro paramscollector
|
||||||
|
|
@ -130,8 +132,8 @@
|
||||||
"
|
"
|
||||||
[params impl]
|
[params impl]
|
||||||
(let [num-params (count params)
|
(let [num-params (count params)
|
||||||
retrieve-params (i/make-param-retrievers params)]
|
retrieve-params (m/make-param-retrievers params)]
|
||||||
(i/paramscollector* retrieve-params num-params impl)
|
(m/paramscollector* retrieve-params num-params impl)
|
||||||
))
|
))
|
||||||
|
|
||||||
(defmacro defparamspath [name & body]
|
(defmacro defparamspath [name & body]
|
||||||
|
|
@ -150,13 +152,13 @@
|
||||||
paths (mapv second bindings)
|
paths (mapv second bindings)
|
||||||
names (mapv first bindings)
|
names (mapv first bindings)
|
||||||
latefns-sym (gensym "latefns")
|
latefns-sym (gensym "latefns")
|
||||||
latefn-syms (vec (i/gensyms (count paths)))]
|
latefn-syms (vec (m/gensyms (count paths)))]
|
||||||
(i/pathed-path*
|
(m/pathed-path*
|
||||||
i/paramspath*
|
m/paramspath*
|
||||||
paths
|
paths
|
||||||
latefns-sym
|
latefns-sym
|
||||||
[latefn-syms latefns-sym]
|
[latefn-syms latefns-sym]
|
||||||
(mapcat (fn [n l] [n `(~l ~i/PARAMS-SYM ~i/PARAMS-IDX-SYM)]) names latefn-syms)
|
(mapcat (fn [n l] [n `(~l ~m/PARAMS-SYM ~m/PARAMS-IDX-SYM)]) names latefn-syms)
|
||||||
impls)))
|
impls)))
|
||||||
|
|
||||||
(defmacro variable-pathed-path
|
(defmacro variable-pathed-path
|
||||||
|
|
@ -166,12 +168,12 @@
|
||||||
are required, then the result is executable."
|
are required, then the result is executable."
|
||||||
[[latepaths-seq-sym paths-seq] & impls]
|
[[latepaths-seq-sym paths-seq] & impls]
|
||||||
(let [latefns-sym (gensym "latefns")]
|
(let [latefns-sym (gensym "latefns")]
|
||||||
(i/pathed-path*
|
(m/pathed-path*
|
||||||
i/paramspath*
|
m/paramspath*
|
||||||
paths-seq
|
paths-seq
|
||||||
latefns-sym
|
latefns-sym
|
||||||
[]
|
[]
|
||||||
[latepaths-seq-sym `(map (fn [l#] (l# ~i/PARAMS-SYM ~i/PARAMS-IDX-SYM))
|
[latepaths-seq-sym `(map (fn [l#] (l# ~m/PARAMS-SYM ~m/PARAMS-IDX-SYM))
|
||||||
~latefns-sym)]
|
~latefns-sym)]
|
||||||
impls
|
impls
|
||||||
)))
|
)))
|
||||||
|
|
@ -184,12 +186,12 @@
|
||||||
[[name path] impl]
|
[[name path] impl]
|
||||||
(let [latefns-sym (gensym "latefns")
|
(let [latefns-sym (gensym "latefns")
|
||||||
latefn (gensym "latefn")]
|
latefn (gensym "latefn")]
|
||||||
(i/pathed-path*
|
(m/pathed-path*
|
||||||
i/paramscollector*
|
m/paramscollector*
|
||||||
[path]
|
[path]
|
||||||
latefns-sym
|
latefns-sym
|
||||||
[[latefn] latefns-sym]
|
[[latefn] latefns-sym]
|
||||||
[name `(~latefn ~i/PARAMS-SYM ~i/PARAMS-IDX-SYM)]
|
[name `(~latefn ~m/PARAMS-SYM ~m/PARAMS-IDX-SYM)]
|
||||||
impl
|
impl
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
|
||||||
21
src/com/rpl/specter/defhelpers.clj
Normal file
21
src/com/rpl/specter/defhelpers.clj
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
(ns com.rpl.specter.defhelpers)
|
||||||
|
|
||||||
|
(defn gensyms [amt]
|
||||||
|
(vec (repeatedly amt gensym)))
|
||||||
|
|
||||||
|
(defmacro define-ParamsNeededPath [fn-type]
|
||||||
|
(let [a (with-meta (gensym "array") {:tag 'objects})
|
||||||
|
impls (for [i (range 21)
|
||||||
|
:let [args (vec (gensyms i))
|
||||||
|
setters (for [j (range i)] `(aset ~a ~j ~(get args j)))]]
|
||||||
|
`(~'invoke [this# ~@args]
|
||||||
|
(let [~a (object-array ~i)]
|
||||||
|
~@setters
|
||||||
|
(com.rpl.specter.impl/bind-params* this# ~a 0)
|
||||||
|
)))]
|
||||||
|
`(defrecord ~'ParamsNeededPath [~'transform-fns ~'num-needed-params]
|
||||||
|
~fn-type
|
||||||
|
~@impls
|
||||||
|
(~'applyTo [this# args#]
|
||||||
|
(let [a# (object-array args#)]
|
||||||
|
(com.rpl.specter.impl/bind-params* this# a# 0))))))
|
||||||
|
|
@ -1,21 +1,23 @@
|
||||||
(ns com.rpl.specter.impl
|
(ns com.rpl.specter.impl
|
||||||
#?(:cljs (:require-macros [com.rpl.specter.prot-opt-invoke
|
#?(:cljs (:require-macros
|
||||||
:refer [mk-optimized-invocation]]))
|
[com.rpl.specter.prot-opt-invoke
|
||||||
|
:refer [mk-optimized-invocation]]
|
||||||
|
[com.rpl.specter.defhelpers :refer [define-ParamsNeededPath]]
|
||||||
|
))
|
||||||
(:use [com.rpl.specter.protocols :only
|
(:use [com.rpl.specter.protocols :only
|
||||||
[select* transform* collect-val]])
|
[select* transform* collect-val]])
|
||||||
(:require [com.rpl.specter.protocols :as p]
|
(:require [com.rpl.specter.protocols :as p]
|
||||||
[clojure.walk :as walk]
|
[clojure.walk :as walk]
|
||||||
[clojure.core.reducers :as r]
|
[clojure.core.reducers :as r]
|
||||||
[clojure.string :as s])
|
[clojure.string :as s]
|
||||||
|
#?(:clj [com.rpl.specter.defhelpers :as dh])
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
(defn spy [e]
|
(defn spy [e]
|
||||||
(println e)
|
(println e)
|
||||||
e)
|
e)
|
||||||
|
|
||||||
(defn gensyms [amt]
|
|
||||||
(vec (repeatedly amt gensym)))
|
|
||||||
|
|
||||||
(defprotocol PathComposer
|
(defprotocol PathComposer
|
||||||
(comp-paths* [paths]))
|
(comp-paths* [paths]))
|
||||||
|
|
||||||
|
|
@ -70,31 +72,22 @@
|
||||||
|
|
||||||
(defrecord CompiledPath [transform-fns params params-idx])
|
(defrecord CompiledPath [transform-fns params params-idx])
|
||||||
|
|
||||||
|
(defn compiled-path? [o]
|
||||||
|
(instance? CompiledPath o))
|
||||||
|
|
||||||
(defn no-params-compiled-path [transform-fns]
|
(defn no-params-compiled-path [transform-fns]
|
||||||
(->CompiledPath transform-fns nil 0))
|
(->CompiledPath transform-fns nil 0))
|
||||||
|
|
||||||
|
|
||||||
(declare bind-params*)
|
(declare bind-params*)
|
||||||
|
|
||||||
(defmacro define-ParamsNeededPath []
|
#?(
|
||||||
(let [a (with-meta (gensym "array") {:tag 'objects})
|
:clj
|
||||||
impls (for [i (range 21)
|
(dh/define-ParamsNeededPath clojure.lang.IFn)
|
||||||
:let [args (vec (gensyms i))
|
|
||||||
setters (for [j (range i)] `(aset ~a ~j ~(get args j)))]]
|
|
||||||
`(~'invoke [this# ~@args]
|
|
||||||
(let [~a (object-array ~i)]
|
|
||||||
~@setters
|
|
||||||
(bind-params* this# ~a 0)
|
|
||||||
)))]
|
|
||||||
`(defrecord ~'ParamsNeededPath [~'transform-fns ~'num-needed-params]
|
|
||||||
clojure.lang.IFn
|
|
||||||
~@impls
|
|
||||||
(~'applyTo [this# args#]
|
|
||||||
(let [a# (object-array args#)]
|
|
||||||
(bind-params* this# a# 0))))))
|
|
||||||
|
|
||||||
|
:cljs
|
||||||
(define-ParamsNeededPath)
|
(dh/define-ParamsNeededPath cljs.core/IFn)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
(defn bind-params* [^ParamsNeededPath params-needed-path params idx]
|
(defn bind-params* [^ParamsNeededPath params-needed-path params idx]
|
||||||
|
|
@ -340,102 +333,11 @@
|
||||||
))))
|
))))
|
||||||
|
|
||||||
|
|
||||||
;; parameterized path helpers
|
|
||||||
|
|
||||||
(defn determine-params-impls [[name1 & impl1] [name2 & impl2]]
|
|
||||||
(if (= name1 'select*)
|
|
||||||
[impl1 impl2]
|
|
||||||
[impl2 impl1]))
|
|
||||||
|
|
||||||
|
|
||||||
(def PARAMS-SYM (vary-meta (gensym "params") assoc :tag 'objects))
|
|
||||||
(def PARAMS-IDX-SYM (gensym "params-idx"))
|
|
||||||
|
|
||||||
(defn paramspath* [bindings num-params [impl1 impl2]]
|
|
||||||
(let [[[[_ s-structure-sym s-next-fn-sym] & select-body]
|
|
||||||
[[_ t-structure-sym t-next-fn-sym] & transform-body]]
|
|
||||||
(determine-params-impls impl1 impl2)]
|
|
||||||
`(->ParamsNeededPath
|
|
||||||
(->TransformFunctions
|
|
||||||
RichPathExecutor
|
|
||||||
(fn [~PARAMS-SYM ~PARAMS-IDX-SYM vals# ~s-structure-sym next-fn#]
|
|
||||||
(let [~s-next-fn-sym (fn [structure#]
|
|
||||||
(next-fn#
|
|
||||||
~PARAMS-SYM
|
|
||||||
(+ ~PARAMS-IDX-SYM ~num-params)
|
|
||||||
vals#
|
|
||||||
structure#))
|
|
||||||
~@bindings]
|
|
||||||
~@select-body
|
|
||||||
))
|
|
||||||
(fn [~PARAMS-SYM ~PARAMS-IDX-SYM vals# ~t-structure-sym next-fn#]
|
|
||||||
(let [~t-next-fn-sym (fn [structure#]
|
|
||||||
(next-fn#
|
|
||||||
~PARAMS-SYM
|
|
||||||
(+ ~PARAMS-IDX-SYM ~num-params)
|
|
||||||
vals#
|
|
||||||
structure#))
|
|
||||||
~@bindings]
|
|
||||||
~@transform-body
|
|
||||||
)))
|
|
||||||
~num-params
|
|
||||||
)))
|
|
||||||
|
|
||||||
(defn paramscollector* [post-bindings num-params [_ [_ structure-sym] & body]]
|
|
||||||
`(let [collector# (fn [~PARAMS-SYM ~PARAMS-IDX-SYM vals# ~structure-sym next-fn#]
|
|
||||||
(let [~@post-bindings ~@[] ; to avoid syntax highlighting issues
|
|
||||||
c# (do ~@body)]
|
|
||||||
(next-fn#
|
|
||||||
~PARAMS-SYM
|
|
||||||
(+ ~PARAMS-IDX-SYM ~num-params)
|
|
||||||
(conj vals# c#)
|
|
||||||
~structure-sym)
|
|
||||||
))]
|
|
||||||
(->ParamsNeededPath
|
|
||||||
(->TransformFunctions
|
|
||||||
RichPathExecutor
|
|
||||||
collector#
|
|
||||||
collector# )
|
|
||||||
~num-params
|
|
||||||
)))
|
|
||||||
|
|
||||||
(defn num-needed-params [path]
|
(defn num-needed-params [path]
|
||||||
(if (instance? CompiledPath path)
|
(if (instance? CompiledPath path)
|
||||||
0
|
0
|
||||||
(:num-needed-params path)))
|
(:num-needed-params path)))
|
||||||
|
|
||||||
(defn pathed-path* [builder paths-seq latefns-sym pre-bindings post-bindings impls]
|
|
||||||
(let [num-params-sym (gensym "num-params")]
|
|
||||||
`(let [paths# (map comp-paths* ~paths-seq)
|
|
||||||
needed-params# (map num-needed-params paths#)
|
|
||||||
offsets# (cons 0 (reductions + needed-params#))
|
|
||||||
~num-params-sym (last offsets#)
|
|
||||||
~latefns-sym (map
|
|
||||||
(fn [o# p#]
|
|
||||||
(if (instance? CompiledPath p#)
|
|
||||||
(fn [params# params-idx#]
|
|
||||||
p# )
|
|
||||||
(fn [params# params-idx#]
|
|
||||||
(bind-params* p# params# (+ params-idx# o#))
|
|
||||||
)))
|
|
||||||
offsets#
|
|
||||||
paths#)
|
|
||||||
~@pre-bindings
|
|
||||||
ret# ~(builder post-bindings num-params-sym impls)
|
|
||||||
]
|
|
||||||
(if (= 0 ~num-params-sym)
|
|
||||||
(bind-params* ret# nil 0)
|
|
||||||
ret#
|
|
||||||
))))
|
|
||||||
|
|
||||||
(defn make-param-retrievers [params]
|
|
||||||
(->> params
|
|
||||||
(map-indexed
|
|
||||||
(fn [i p]
|
|
||||||
[p `(aget ~PARAMS-SYM
|
|
||||||
(+ ~PARAMS-IDX-SYM ~i))]
|
|
||||||
))
|
|
||||||
(apply concat)))
|
|
||||||
|
|
||||||
;; cell implementation idea taken from prismatic schema library
|
;; cell implementation idea taken from prismatic schema library
|
||||||
(defprotocol PMutableCell
|
(defprotocol PMutableCell
|
||||||
|
|
|
||||||
97
src/com/rpl/specter/macros.clj
Normal file
97
src/com/rpl/specter/macros.clj
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
(ns com.rpl.specter.macros
|
||||||
|
(:use [com.rpl.specter impl])
|
||||||
|
)
|
||||||
|
|
||||||
|
(defn gensyms [amt]
|
||||||
|
(vec (repeatedly amt gensym)))
|
||||||
|
|
||||||
|
(defn determine-params-impls [[name1 & impl1] [name2 & impl2]]
|
||||||
|
(if (= name1 'select*)
|
||||||
|
[impl1 impl2]
|
||||||
|
[impl2 impl1]))
|
||||||
|
|
||||||
|
|
||||||
|
(def PARAMS-SYM (vary-meta (gensym "params") assoc :tag 'objects))
|
||||||
|
(def PARAMS-IDX-SYM (gensym "params-idx"))
|
||||||
|
|
||||||
|
(defn paramspath* [bindings num-params [impl1 impl2]]
|
||||||
|
(let [[[[_ s-structure-sym s-next-fn-sym] & select-body]
|
||||||
|
[[_ t-structure-sym t-next-fn-sym] & transform-body]]
|
||||||
|
(determine-params-impls impl1 impl2)]
|
||||||
|
`(->ParamsNeededPath
|
||||||
|
(->TransformFunctions
|
||||||
|
RichPathExecutor
|
||||||
|
(fn [~PARAMS-SYM ~PARAMS-IDX-SYM vals# ~s-structure-sym next-fn#]
|
||||||
|
(let [~s-next-fn-sym (fn [structure#]
|
||||||
|
(next-fn#
|
||||||
|
~PARAMS-SYM
|
||||||
|
(+ ~PARAMS-IDX-SYM ~num-params)
|
||||||
|
vals#
|
||||||
|
structure#))
|
||||||
|
~@bindings]
|
||||||
|
~@select-body
|
||||||
|
))
|
||||||
|
(fn [~PARAMS-SYM ~PARAMS-IDX-SYM vals# ~t-structure-sym next-fn#]
|
||||||
|
(let [~t-next-fn-sym (fn [structure#]
|
||||||
|
(next-fn#
|
||||||
|
~PARAMS-SYM
|
||||||
|
(+ ~PARAMS-IDX-SYM ~num-params)
|
||||||
|
vals#
|
||||||
|
structure#))
|
||||||
|
~@bindings]
|
||||||
|
~@transform-body
|
||||||
|
)))
|
||||||
|
~num-params
|
||||||
|
)))
|
||||||
|
|
||||||
|
(defn paramscollector* [post-bindings num-params [_ [_ structure-sym] & body]]
|
||||||
|
`(let [collector# (fn [~PARAMS-SYM ~PARAMS-IDX-SYM vals# ~structure-sym next-fn#]
|
||||||
|
(let [~@post-bindings ~@[] ; to avoid syntax highlighting issues
|
||||||
|
c# (do ~@body)]
|
||||||
|
(next-fn#
|
||||||
|
~PARAMS-SYM
|
||||||
|
(+ ~PARAMS-IDX-SYM ~num-params)
|
||||||
|
(conj vals# c#)
|
||||||
|
~structure-sym)
|
||||||
|
))]
|
||||||
|
(->ParamsNeededPath
|
||||||
|
(->TransformFunctions
|
||||||
|
RichPathExecutor
|
||||||
|
collector#
|
||||||
|
collector# )
|
||||||
|
~num-params
|
||||||
|
)))
|
||||||
|
|
||||||
|
(defn pathed-path* [builder paths-seq latefns-sym pre-bindings post-bindings impls]
|
||||||
|
(let [num-params-sym (gensym "num-params")]
|
||||||
|
`(let [paths# (map comp-paths* ~paths-seq)
|
||||||
|
needed-params# (map num-needed-params paths#)
|
||||||
|
offsets# (cons 0 (reductions + needed-params#))
|
||||||
|
~num-params-sym (last offsets#)
|
||||||
|
~latefns-sym (map
|
||||||
|
(fn [o# p#]
|
||||||
|
(if (compiled-path? p#)
|
||||||
|
(fn [params# params-idx#]
|
||||||
|
p# )
|
||||||
|
(fn [params# params-idx#]
|
||||||
|
(bind-params* p# params# (+ params-idx# o#))
|
||||||
|
)))
|
||||||
|
offsets#
|
||||||
|
paths#)
|
||||||
|
~@pre-bindings
|
||||||
|
ret# ~(builder post-bindings num-params-sym impls)
|
||||||
|
]
|
||||||
|
(if (= 0 ~num-params-sym)
|
||||||
|
(bind-params* ret# nil 0)
|
||||||
|
ret#
|
||||||
|
))))
|
||||||
|
|
||||||
|
(defn make-param-retrievers [params]
|
||||||
|
(->> params
|
||||||
|
(map-indexed
|
||||||
|
(fn [i p]
|
||||||
|
[p `(aget ~PARAMS-SYM
|
||||||
|
(+ ~PARAMS-IDX-SYM ~i))]
|
||||||
|
))
|
||||||
|
(apply concat)))
|
||||||
|
|
||||||
Loading…
Reference in a new issue