higher order parameterized builder working, implemented filterer

This commit is contained in:
Nathan Marz 2015-09-10 17:09:16 -04:00
parent 56ba5a5b8d
commit efd4f2ee9a
2 changed files with 71 additions and 94 deletions

View file

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

View file

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