higher order parameterized builder working, implemented filterer
This commit is contained in:
parent
56ba5a5b8d
commit
efd4f2ee9a
2 changed files with 71 additions and 94 deletions
|
|
@ -128,31 +128,11 @@
|
|||
`(def ~name (paramspath ~@body)))
|
||||
|
||||
(defmacro params-paramspath [bindings & impls]
|
||||
(let [quoted-bindings (->> bindings
|
||||
(partition 2)
|
||||
(map (fn [[sym path-sym]]
|
||||
[`(quote ~sym) `(quote ~(gensym "path")) path-sym]
|
||||
)))]
|
||||
`(i/params-paramspath* ~quoted-bindings (quote ~impls))
|
||||
))
|
||||
(i/params-paramspath* (partition 2 bindings) impls))
|
||||
|
||||
|
||||
(defn filterer [& path]
|
||||
(let [path (i/comp-paths* path)]
|
||||
(params-paramspath [late path]
|
||||
(select* [this structure next-fn]
|
||||
;; same code
|
||||
)
|
||||
(transform* [this structure next-fn]
|
||||
;; same code
|
||||
))))
|
||||
|
||||
|
||||
;;TODO: figure out how to express higher order selectors like filterer, selected?, cond-path
|
||||
;; - if keep params-idx in compiledpath too, then:
|
||||
;; - needs to emit paramsneeded if it needs params
|
||||
;; - at runtime, it converts internal selector into CompiledPath with
|
||||
;; the current params/params-idx
|
||||
;;TODO: needs to parameterize if necessary according to its path
|
||||
;; same for selected?, not-selected?, transformed, collect, collect-one,
|
||||
;; cond-path, multi-path
|
||||
;;TODO: figure out how to express srange in terms of srange-dynamic
|
||||
;; - will need selector and transformer to call into shared functions
|
||||
;;TODO: get rid of KeyPath
|
||||
|
|
@ -181,26 +161,21 @@
|
|||
|
||||
(defn codewalker [afn] (i/->CodeWalkerStructurePath afn))
|
||||
|
||||
;;TODO: needs to parameterize if necessary according to its path
|
||||
;; same for selected?, not-selected?, transformed, collect, collect-one,
|
||||
;; cond-path, multi-path
|
||||
;; TODO: but should only become a late bound object if its internal path
|
||||
;; is parameterized
|
||||
;; want an interface that gives regular structure path interface but
|
||||
;; creates the right thing
|
||||
(defn filterer [& path]
|
||||
(params-paramspath [late (i/comp-paths* path)]
|
||||
(select* [this structure next-fn]
|
||||
(->> structure (filter #(i/selected?* late %)) doall next-fn))
|
||||
(transform* [this structure next-fn]
|
||||
(let [[filtered ancestry] (i/filter+ancestry late structure)
|
||||
;; the vec is necessary so that we can get by index later
|
||||
;; (can't get by index for cons'd lists)
|
||||
next (vec (next-fn filtered))]
|
||||
(reduce (fn [curr [newi oldi]]
|
||||
(assoc curr oldi (get next newi)))
|
||||
(vec structure)
|
||||
ancestry))
|
||||
)))
|
||||
|
||||
; (higherorderparamspath [late1 path1
|
||||
; late2 path2
|
||||
; late3 path3]
|
||||
; (select* [this structure next-fn]
|
||||
; (compiled-select late1 ...)
|
||||
; ;;TODO: if its multiple paths... where to do the index manipulation...?
|
||||
; ;;could take in another arg of "latebound paths" that can then be used internally...
|
||||
; ;; but if nothing was higher order, then its just direct
|
||||
; ;; this never directly accesses params
|
||||
; ))
|
||||
|
||||
(defn filterer [& path] (i/->FilterStructurePath (i/comp-paths* path)))
|
||||
|
||||
(defparamspath keypath [key]
|
||||
(select* [this structure next-fn]
|
||||
|
|
|
|||
|
|
@ -9,13 +9,6 @@
|
|||
[clojure.string :as s])
|
||||
)
|
||||
|
||||
(def ^:dynamic *tmp-closure*)
|
||||
(defn closed-code [closure body]
|
||||
(let [lv (mapcat #(vector % `(*tmp-closure* '~%))
|
||||
(keys closure))]
|
||||
(binding [*tmp-closure* closure]
|
||||
(eval `(let [~@lv] ~body)))))
|
||||
|
||||
(defprotocol PathComposer
|
||||
(comp-paths* [paths]))
|
||||
|
||||
|
|
@ -335,10 +328,7 @@
|
|||
(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)
|
||||
|
||||
params-sym (gensym "params")
|
||||
params-idx-sym (gensym "params-idx")]
|
||||
(determine-params-impls impl1 impl2)]
|
||||
`(->ParamsNeededPath
|
||||
(->TransformFunctions
|
||||
RichPathExecutor
|
||||
|
|
@ -371,28 +361,57 @@
|
|||
(:num-needed-params path)))
|
||||
|
||||
(defn params-paramspath* [bindings impls]
|
||||
(let [num-params-seq (->> bindings
|
||||
(map last)
|
||||
(map num-needed-params)
|
||||
(reductions +)
|
||||
(cons 0))
|
||||
num-params (last num-params-seq)
|
||||
closure (->> bindings (map rest) (into {}))
|
||||
make-paths (->> bindings
|
||||
(map (fn [offset [late-sym path-sym path]]
|
||||
[late-sym
|
||||
(if (instance? CompiledPath path)
|
||||
path-sym
|
||||
`(bind-params ~path-sym ~PARAMS-SYM (+ ~PARAMS-IDX-SYM ~offset))
|
||||
)
|
||||
])
|
||||
num-params-seq)
|
||||
(apply concat))
|
||||
params-needed-path (closed-code closure (paramspath* make-paths num-params impls))]
|
||||
(if (= num-params 0)
|
||||
(bind-params params-needed-path nil 0)
|
||||
params-needed-path)
|
||||
))
|
||||
(let [bindings (->> bindings
|
||||
(map (fn [[late-sym path]]
|
||||
{:late-sym late-sym
|
||||
:path path
|
||||
:path-sym (gensym "path")
|
||||
:offset-sym (gensym "offset")
|
||||
:latebind-sym (gensym "latebind")}))
|
||||
(reduce
|
||||
(fn [bindings binding]
|
||||
(if (empty? bindings)
|
||||
[(assoc binding :offset 0)]
|
||||
(let [last-binding (last bindings)]
|
||||
(conj bindings
|
||||
(assoc binding
|
||||
:offset
|
||||
`(+ ~(:offset-sym last-binding)
|
||||
(num-needed-params ~(:path-sym last-binding)))
|
||||
))
|
||||
)))
|
||||
[]))
|
||||
binding-decls (mapcat (fn [b] [(:path-sym b) (:path b)]) bindings)
|
||||
offset-decls (mapcat (fn [b] [(:offset-sym b) (:offset b)]) bindings)
|
||||
needed-params (map (fn [b] `(num-needed-params ~(:path-sym b))) bindings)
|
||||
latefn-decls (mapcat
|
||||
(fn [b]
|
||||
[(:latebind-sym b)
|
||||
`(if (instance? CompiledPath ~(:path-sym b))
|
||||
(fn [params# params-idx#] ~(:path-sym b))
|
||||
(fn [params# params-idx#]
|
||||
(bind-params ~(:path-sym b)
|
||||
params#
|
||||
(+ params-idx#
|
||||
~(:offset-sym b)))
|
||||
))
|
||||
])
|
||||
bindings)
|
||||
|
||||
num-params-sym (gensym "num-params")
|
||||
latebindings (mapcat
|
||||
(fn [b]
|
||||
[(:late-sym b) `(~(:latebind-sym b) ~PARAMS-SYM ~PARAMS-IDX-SYM)])
|
||||
bindings)]
|
||||
`(let [~@binding-decls
|
||||
~@offset-decls
|
||||
~num-params-sym (+ ~@needed-params)
|
||||
~@latefn-decls
|
||||
ret# ~(paramspath* latebindings num-params-sym impls)]
|
||||
(if (= 0 ~num-params-sym)
|
||||
(bind-params ret# nil 0)
|
||||
ret#
|
||||
))))
|
||||
|
||||
;; cell implementation idea taken from prismatic schema library
|
||||
(defprotocol PMutableCell
|
||||
|
|
@ -502,7 +521,7 @@
|
|||
(get-cell ret)
|
||||
))
|
||||
|
||||
(defn- filter+ancestry [path aseq]
|
||||
(defn filter+ancestry [path aseq]
|
||||
(let [aseq (vec aseq)]
|
||||
(reduce (fn [[s m :as orig] i]
|
||||
(let [e (get aseq i)
|
||||
|
|
@ -573,23 +592,6 @@
|
|||
(transform* [^CodeWalkerStructurePath this structure next-fn]
|
||||
(codewalk-until (.-afn this) next-fn structure)))
|
||||
|
||||
|
||||
(deftype FilterStructurePath [path])
|
||||
|
||||
(extend-protocol p/StructurePath
|
||||
FilterStructurePath
|
||||
(select* [^FilterStructurePath this structure next-fn]
|
||||
(->> structure (filter #(selected?* (.-path this) %)) doall next-fn))
|
||||
(transform* [^FilterStructurePath this structure next-fn]
|
||||
(let [[filtered ancestry] (filter+ancestry (.-path this) structure)
|
||||
;; the vec is necessary so that we can get by index later
|
||||
;; (can't get by index for cons'd lists)
|
||||
next (vec (next-fn filtered))]
|
||||
(reduce (fn [curr [newi oldi]]
|
||||
(assoc curr oldi (get next newi)))
|
||||
(vec structure)
|
||||
ancestry))))
|
||||
|
||||
(deftype SelectCollector [sel-fn selector])
|
||||
|
||||
(extend-protocol p/Collector
|
||||
|
|
|
|||
Loading…
Reference in a new issue