generate a real higher order function from defnav and defcollector that returns a lean compiled path when invoked but coerces to equivalent paramsneededpath when composed, change nav constructors to recognize this and use a lean proxy for this case
This commit is contained in:
parent
7bfad80e00
commit
56da47aca5
3 changed files with 78 additions and 33 deletions
|
|
@ -263,8 +263,12 @@
|
||||||
empty?
|
empty?
|
||||||
not))
|
not))
|
||||||
|
|
||||||
|
(defn root-params-nav? [o]
|
||||||
|
(and (fn? o) (-> o meta :highernav)))
|
||||||
|
|
||||||
(defn- coerce-object [this]
|
(defn- coerce-object [this]
|
||||||
(cond (satisfies? p/ImplicitNav this) (p/implicit-nav this)
|
(cond (root-params-nav? this) (-> this meta :highernav :params-needed-path)
|
||||||
|
(satisfies? p/ImplicitNav this) (p/implicit-nav this)
|
||||||
:else (throw-illegal "Not a navigator: " this)
|
:else (throw-illegal "Not a navigator: " this)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
@ -626,8 +630,9 @@
|
||||||
|
|
||||||
(defn verify-layerable! [anav]
|
(defn verify-layerable! [anav]
|
||||||
(if-not
|
(if-not
|
||||||
|
(or (root-params-nav? anav)
|
||||||
(and (instance? ParamsNeededPath anav)
|
(and (instance? ParamsNeededPath anav)
|
||||||
(> (:num-needed-params anav) 0))
|
(> (:num-needed-params anav) 0)))
|
||||||
(throw-illegal "defnavconstructor must be used on a navigator defined with
|
(throw-illegal "defnavconstructor must be used on a navigator defined with
|
||||||
defnav with at least one parameter")
|
defnav with at least one parameter")
|
||||||
))
|
))
|
||||||
|
|
@ -771,6 +776,30 @@
|
||||||
1
|
1
|
||||||
))
|
))
|
||||||
|
|
||||||
|
(def lean-compiled-path-proxy
|
||||||
|
(->ParamsNeededPath
|
||||||
|
(reify RichNavigator
|
||||||
|
(rich-select* [this params params-idx vals structure next-fn]
|
||||||
|
(let [^CompiledPath apath (aget ^objects params params-idx)
|
||||||
|
^Navigator nav (.-nav apath)]
|
||||||
|
(exec-select*
|
||||||
|
nav
|
||||||
|
structure
|
||||||
|
(fn [structure-next]
|
||||||
|
(next-fn params params-idx vals structure-next))
|
||||||
|
)))
|
||||||
|
(rich-transform* [this params params-idx vals structure next-fn]
|
||||||
|
(let [^CompiledPath apath (aget ^objects params params-idx)
|
||||||
|
^Navigator nav (.-nav apath)]
|
||||||
|
(exec-transform*
|
||||||
|
nav
|
||||||
|
structure
|
||||||
|
(fn [structure-next]
|
||||||
|
(next-fn params params-idx vals structure-next))
|
||||||
|
))))
|
||||||
|
1
|
||||||
|
))
|
||||||
|
|
||||||
(defn srange-transform* [structure start end next-fn]
|
(defn srange-transform* [structure start end next-fn]
|
||||||
(let [structurev (vec structure)
|
(let [structurev (vec structure)
|
||||||
newpart (next-fn (-> structurev (subvec start end)))
|
newpart (next-fn (-> structurev (subvec start end)))
|
||||||
|
|
@ -851,14 +880,14 @@
|
||||||
(if (-> v meta :dynamic)
|
(if (-> v meta :dynamic)
|
||||||
(magic-fail! "Var " (:sym op) " is dynamic")
|
(magic-fail! "Var " (:sym op) " is dynamic")
|
||||||
(cond
|
(cond
|
||||||
(instance? ParamsNeededPath vv)
|
(or (root-params-nav? vv) (instance? ParamsNeededPath vv))
|
||||||
;;TODO: if all params are constants, then just bind the path right here
|
;;TODO: if all params are constants, then just bind the path right here
|
||||||
;;otherwise, add the params
|
;;otherwise, add the params
|
||||||
;; - could extend this to see if it contains nested function calls which
|
;; - could extend this to see if it contains nested function calls which
|
||||||
;; are only on constants
|
;; are only on constants
|
||||||
(do
|
(do
|
||||||
(swap! params-atom #(vec (concat % ps)))
|
(swap! params-atom #(vec (concat % ps)))
|
||||||
vv
|
(coerce-path vv)
|
||||||
)
|
)
|
||||||
|
|
||||||
(and (fn? vv) (-> v meta :pathedfn))
|
(and (fn? vv) (-> v meta :pathedfn))
|
||||||
|
|
@ -899,9 +928,12 @@
|
||||||
|
|
||||||
(and (fn? vv) (-> vv meta :layerednav))
|
(and (fn? vv) (-> vv meta :layerednav))
|
||||||
(do
|
(do
|
||||||
|
;;TODO: if all args are constant then invoke it right here
|
||||||
(swap! params-atom conj (:code p))
|
(swap! params-atom conj (:code p))
|
||||||
|
(if (= (-> vv meta :layerednav) :lean)
|
||||||
|
lean-compiled-path-proxy
|
||||||
rich-compiled-path-proxy
|
rich-compiled-path-proxy
|
||||||
)
|
))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(magic-fail! "Var " (:sym op) " must be either a parameterized "
|
(magic-fail! "Var " (:sym op) " must be either a parameterized "
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,10 @@
|
||||||
(i/->ParamsNeededPath nav# num-params#)
|
(i/->ParamsNeededPath nav# num-params#)
|
||||||
))))
|
))))
|
||||||
|
|
||||||
(defmacro lean-nav* [& impls]
|
(defmacro ^:no-doc lean-nav* [& impls]
|
||||||
`(reify Navigator ~@impls))
|
`(reify Navigator ~@impls))
|
||||||
|
|
||||||
(defn operation-with-bindings [bindings params-sym params-idx-sym op-maker]
|
(defn ^:no-doc operation-with-bindings [bindings params-sym params-idx-sym op-maker]
|
||||||
(let [bindings (partition 2 bindings)
|
(let [bindings (partition 2 bindings)
|
||||||
binding-fn-syms (gensyms (count bindings))
|
binding-fn-syms (gensyms (count bindings))
|
||||||
binding-syms (map first bindings)
|
binding-syms (map first bindings)
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
~body
|
~body
|
||||||
)))
|
)))
|
||||||
|
|
||||||
(defmacro rich-nav-with-bindings [num-params-code bindings & impls]
|
(defmacro ^:no-doc rich-nav-with-bindings [num-params-code bindings & impls]
|
||||||
(let [[[[_ s-structure-sym s-next-fn-sym] & s-body]
|
(let [[[[_ s-structure-sym s-next-fn-sym] & s-body]
|
||||||
[[_ t-structure-sym t-next-fn-sym] & t-body]]
|
[[_ t-structure-sym t-next-fn-sym] & t-body]]
|
||||||
(apply determine-params-impls impls)
|
(apply determine-params-impls impls)
|
||||||
|
|
@ -97,7 +97,7 @@
|
||||||
))
|
))
|
||||||
)))))
|
)))))
|
||||||
|
|
||||||
(defmacro collector-with-bindings [num-params-code bindings impl]
|
(defmacro ^:no-doc collector-with-bindings [num-params-code bindings impl]
|
||||||
(let [[_ [_ structure-sym] & body] impl
|
(let [[_ [_ structure-sym] & body] impl
|
||||||
params-sym (gensym "params")
|
params-sym (gensym "params")
|
||||||
params-idx-sym (gensym "params")]
|
params-idx-sym (gensym "params")]
|
||||||
|
|
@ -133,13 +133,18 @@
|
||||||
[params & impls]
|
[params & impls]
|
||||||
(if (empty? params)
|
(if (empty? params)
|
||||||
`(i/lean-compiled-path (lean-nav* ~@impls))
|
`(i/lean-compiled-path (lean-nav* ~@impls))
|
||||||
`(i/->ParamsNeededPath
|
`(vary-meta
|
||||||
;(fn ~params (lean-nav* ~@body))
|
(fn ~params (i/lean-compiled-path (lean-nav* ~@impls)))
|
||||||
|
assoc
|
||||||
|
:highernav
|
||||||
|
{:type :lean
|
||||||
|
:params-needed-path
|
||||||
|
(i/->ParamsNeededPath
|
||||||
(rich-nav-with-bindings ~(count params)
|
(rich-nav-with-bindings ~(count params)
|
||||||
~(delta-param-bindings params)
|
~(delta-param-bindings params)
|
||||||
~@impls
|
~@impls
|
||||||
)
|
)
|
||||||
~(count params)
|
~(count params))}
|
||||||
)))
|
)))
|
||||||
|
|
||||||
(defmacro collector
|
(defmacro collector
|
||||||
|
|
@ -155,13 +160,20 @@
|
||||||
)]
|
)]
|
||||||
(if ~(empty? params)
|
(if ~(empty? params)
|
||||||
(i/no-params-rich-compiled-path rich-nav#)
|
(i/no-params-rich-compiled-path rich-nav#)
|
||||||
|
(vary-meta
|
||||||
|
(fn ~params
|
||||||
|
(i/no-params-rich-compiled-path
|
||||||
|
(collector-with-bindings 0 []
|
||||||
|
~body)))
|
||||||
|
assoc
|
||||||
|
:highernav
|
||||||
|
{:type :rich
|
||||||
|
:params-needed-path
|
||||||
(i/->ParamsNeededPath
|
(i/->ParamsNeededPath
|
||||||
; (fn ~params
|
|
||||||
; (collector-with-bindings 0
|
|
||||||
; ~impl-body))
|
|
||||||
rich-nav#
|
rich-nav#
|
||||||
~(count params))
|
~(count params)
|
||||||
)))
|
)}
|
||||||
|
))))
|
||||||
|
|
||||||
(defn ^:no-doc fixed-pathed-operation [bindings op-maker]
|
(defn ^:no-doc fixed-pathed-operation [bindings op-maker]
|
||||||
(let [bindings (partition 2 bindings)
|
(let [bindings (partition 2 bindings)
|
||||||
|
|
@ -413,7 +425,8 @@
|
||||||
(vary-meta
|
(vary-meta
|
||||||
(let [~csym (i/layered-wrapper ~anav)]
|
(let [~csym (i/layered-wrapper ~anav)]
|
||||||
(fn ~@checked-code))
|
(fn ~@checked-code))
|
||||||
assoc :layerednav true))
|
assoc :layerednav (or (-> ~anav meta :highernav :type) :rich)
|
||||||
|
))
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue