partial refactoring to prepare for cljs compatibility

This commit is contained in:
Nathan Marz 2015-09-11 16:06:31 -04:00
parent 5aa3bc5da2
commit 7a4caa5b61
4 changed files with 153 additions and 131 deletions

View file

@ -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
) )
)) ))

View 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))))))

View file

@ -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

View 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)))