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
(:use [com.rpl.specter.protocols :only [StructurePath]])
(:require [com.rpl.specter.impl :as i])
(:use [com.rpl.specter.protocols :only [StructurePath]]
)
(:require [com.rpl.specter.impl :as i]
[com.rpl.specter.macros :as m])
)
(defn comp-paths [& paths]
@ -118,8 +120,8 @@
that needed parameters (in the order in which they were declared)."
[params & impls]
(let [num-params (count params)
retrieve-params (i/make-param-retrievers params)]
(i/paramspath* retrieve-params num-params impls)
retrieve-params (m/make-param-retrievers params)]
(m/paramspath* retrieve-params num-params impls)
))
(defmacro paramscollector
@ -130,8 +132,8 @@
"
[params impl]
(let [num-params (count params)
retrieve-params (i/make-param-retrievers params)]
(i/paramscollector* retrieve-params num-params impl)
retrieve-params (m/make-param-retrievers params)]
(m/paramscollector* retrieve-params num-params impl)
))
(defmacro defparamspath [name & body]
@ -150,13 +152,13 @@
paths (mapv second bindings)
names (mapv first bindings)
latefns-sym (gensym "latefns")
latefn-syms (vec (i/gensyms (count paths)))]
(i/pathed-path*
i/paramspath*
latefn-syms (vec (m/gensyms (count paths)))]
(m/pathed-path*
m/paramspath*
paths
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)))
(defmacro variable-pathed-path
@ -166,12 +168,12 @@
are required, then the result is executable."
[[latepaths-seq-sym paths-seq] & impls]
(let [latefns-sym (gensym "latefns")]
(i/pathed-path*
i/paramspath*
(m/pathed-path*
m/paramspath*
paths-seq
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)]
impls
)))
@ -184,12 +186,12 @@
[[name path] impl]
(let [latefns-sym (gensym "latefns")
latefn (gensym "latefn")]
(i/pathed-path*
i/paramscollector*
(m/pathed-path*
m/paramscollector*
[path]
latefns-sym
[[latefn] latefns-sym]
[name `(~latefn ~i/PARAMS-SYM ~i/PARAMS-IDX-SYM)]
[name `(~latefn ~m/PARAMS-SYM ~m/PARAMS-IDX-SYM)]
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
#?(:cljs (:require-macros [com.rpl.specter.prot-opt-invoke
:refer [mk-optimized-invocation]]))
#?(:cljs (:require-macros
[com.rpl.specter.prot-opt-invoke
:refer [mk-optimized-invocation]]
[com.rpl.specter.defhelpers :refer [define-ParamsNeededPath]]
))
(:use [com.rpl.specter.protocols :only
[select* transform* collect-val]])
(:require [com.rpl.specter.protocols :as p]
[clojure.walk :as walk]
[clojure.core.reducers :as r]
[clojure.string :as s])
[clojure.string :as s]
#?(:clj [com.rpl.specter.defhelpers :as dh])
)
)
(defn spy [e]
(println e)
e)
(defn gensyms [amt]
(vec (repeatedly amt gensym)))
(defprotocol PathComposer
(comp-paths* [paths]))
@ -70,31 +72,22 @@
(defrecord CompiledPath [transform-fns params params-idx])
(defn compiled-path? [o]
(instance? CompiledPath o))
(defn no-params-compiled-path [transform-fns]
(->CompiledPath transform-fns nil 0))
(declare bind-params*)
(defmacro define-ParamsNeededPath []
(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
(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))))))
#?(
:clj
(dh/define-ParamsNeededPath clojure.lang.IFn)
(define-ParamsNeededPath)
:cljs
(dh/define-ParamsNeededPath cljs.core/IFn)
)
(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]
(if (instance? CompiledPath path)
0
(: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
(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)))