Compare commits

...

2 commits

7 changed files with 177 additions and 105 deletions

View file

@ -1,8 +1,8 @@
(def VERSION (.trim (slurp "VERSION"))) (def VERSION (.trim (slurp "VERSION")))
(defproject com.rpl/specter VERSION (defproject com.rpl/specter VERSION
:jvm-opts ["-XX:-OmitStackTraceInFastThrow"] ; this prevents JVM from doing optimizations which can remove stack traces from NPE and other exceptions :jvm-opts ["-XX:-OmitStackTraceInFastThrow" ; this prevents JVM from doing optimizations which can remove stack traces from NPE and other exceptions
;"-agentpath:/Applications/YourKit_Java_Profiler_2015_build_15056.app/Contents/Resources/bin/mac/libyjpagent.jnilib"] "-agentpath:/Applications/YourKit_Java_Profiler_2015_build_15056.app/Contents/Resources/bin/mac/libyjpagent.jnilib"]
:source-paths ["src/clj"] :source-paths ["src/clj"]
:java-source-paths ["src/java"] :java-source-paths ["src/java"]

View file

@ -175,9 +175,9 @@
needed (i/num-needed-params params-path)] needed (i/num-needed-params params-path)]
(richnav 0 (richnav 0
(select* [this params params-idx vals structure next-fn] (select* [this params params-idx vals structure next-fn]
(i/exec-rich-select* nav params (- params-idx needed) vals structure next-fn)) (i/exec-rich_select nav params (- params-idx needed) vals structure next-fn))
(transform* [this params params-idx vals structure next-fn] (transform* [this params params-idx vals structure next-fn]
(i/exec-rich-transform* nav params (- params-idx needed) vals structure next-fn))))) (i/exec-rich_transform nav params (- params-idx needed) vals structure next-fn)))))
;; Built-in pathing and context operations ;; Built-in pathing and context operations
@ -328,6 +328,7 @@
In a transform, that subset in the original set is changed to the In a transform, that subset in the original set is changed to the
new value of the subset."} new value of the subset."}
subset subset
{:inline-next-fn true}
[aset] [aset]
(select* [this structure next-fn] (select* [this structure next-fn]
(next-fn (set/intersection structure aset))) (next-fn (set/intersection structure aset)))
@ -344,6 +345,7 @@
In a transform, that submap in the original map is changed to the new In a transform, that submap in the original map is changed to the new
value of the submap."} value of the submap."}
submap submap
{:inline-next-fn true}
[m-keys] [m-keys]
(select* [this structure next-fn] (select* [this structure next-fn]
(next-fn (select-keys structure m-keys))) (next-fn (select-keys structure m-keys)))
@ -371,7 +373,7 @@
(select* [this structure next-fn] (select* [this structure next-fn]
(n/walk-select afn next-fn structure)) (n/walk-select afn next-fn structure))
(transform* [this structure next-fn] (transform* [this structure next-fn]
(n/codewalk-until afn next-fn structure))) (i/codewalk-until afn next-fn structure)))
(defpathedfn subselect (defpathedfn subselect
"Navigates to a sequence that contains the results of (select ...), "Navigates to a sequence that contains the results of (select ...),
@ -397,6 +399,7 @@
(defnav (defnav
^{:doc "Navigates to the specified key, navigating to nil if it does not exist."} ^{:doc "Navigates to the specified key, navigating to nil if it does not exist."}
keypath keypath
{:inline-next-fn true}
[key] [key]
(select* [this structure next-fn] (select* [this structure next-fn]
(next-fn (get structure key))) (next-fn (get structure key)))
@ -407,6 +410,7 @@
(defnav (defnav
^{:doc "Navigates to the key only if it exists in the map."} ^{:doc "Navigates to the key only if it exists in the map."}
must must
{:inline-next-fn true}
[k] [k]
(select* [this structure next-fn] (select* [this structure next-fn]
(if (contains? structure k) (if (contains? structure k)
@ -421,6 +425,7 @@
(defnav (defnav
^{:doc "Navigates to result of running `afn` on the currently navigated value."} ^{:doc "Navigates to result of running `afn` on the currently navigated value."}
view view
{:inline-next-fn true}
[afn] [afn]
(select* [this structure next-fn] (select* [this structure next-fn]
(next-fn (afn structure))) (next-fn (afn structure)))
@ -433,6 +438,7 @@
transforms, the transformed value then has `unparse-fn` run on transforms, the transformed value then has `unparse-fn` run on
it to get the final value at this point."} it to get the final value at this point."}
parser parser
{:inline-next-fn true}
[parse-fn unparse-fn] [parse-fn unparse-fn]
(select* [this structure next-fn] (select* [this structure next-fn]
(next-fn (parse-fn structure))) (next-fn (parse-fn structure)))
@ -518,6 +524,7 @@
^{:doc "Keeps the element only if it matches the supplied predicate. This is the ^{:doc "Keeps the element only if it matches the supplied predicate. This is the
late-bound parameterized version of using a function directly in a path."} late-bound parameterized version of using a function directly in a path."}
pred pred
{:inline-next-fn true}
[afn] [afn]
(select* [this structure next-fn] (select* [this structure next-fn]
(if (afn structure) (next-fn structure) NONE)) (if (afn structure) (next-fn structure) NONE))
@ -546,6 +553,7 @@
^{:doc "Navigates to the provided val if the structure is nil. Otherwise it stays ^{:doc "Navigates to the provided val if the structure is nil. Otherwise it stays
navigated at the structure."} navigated at the structure."}
nil->val nil->val
{:inline-next-fn true}
[v] [v]
(select* [this structure next-fn] (select* [this structure next-fn]
(next-fn (if (nil? structure) v structure))) (next-fn (if (nil? structure) v structure)))
@ -717,15 +725,15 @@
(richnav (+ comp1-needed (i/num-needed-params comp2)) (richnav (+ comp1-needed (i/num-needed-params comp2))
(select* [this params params-idx vals structure next-fn] (select* [this params params-idx vals structure next-fn]
(let [res1 (i/exec-rich-select* nav1 params params-idx vals structure next-fn) (let [res1 (i/exec-rich_select nav1 params params-idx vals structure next-fn)
res2 (i/exec-rich-select* nav2 params (+ params-idx comp1-needed) vals structure next-fn)] res2 (i/exec-rich_select nav2 params (+ params-idx comp1-needed) vals structure next-fn)]
(if (identical? NONE res2) (if (identical? NONE res2)
res1 res1
res2))) res2)))
(transform* [this params params-idx vals structure next-fn] (transform* [this params params-idx vals structure next-fn]
(let [s1 (i/exec-rich-transform* nav1 params params-idx vals structure next-fn)] (let [s1 (i/exec-rich_transform nav1 params params-idx vals structure next-fn)]
(i/exec-rich-transform* nav2 params (+ params-idx comp1-needed) vals s1 next-fn)))))) (i/exec-rich_transform nav2 params (+ params-idx comp1-needed) vals s1 next-fn))))))
([path1 path2 & paths] ([path1 path2 & paths]
(reduce multi-path (multi-path path1 path2) paths))) (reduce multi-path (multi-path path1 path2) paths)))

View file

@ -1,13 +1,13 @@
(ns com.rpl.specter.defnavhelpers (ns com.rpl.specter.defnavhelpers
(:require [com.rpl.specter.impl :as i])) (:require [com.rpl.specter.impl :as i]))
(defn param-delta [i] (defn param-delta [^long i]
(fn [^objects params params-idx] (fn [^objects params ^long params-idx]
(aget params (+ params-idx i)))) (aget params (+ params-idx i))))
(defn bound-params [path start-delta] (defn bound-params [path ^long start-delta]
(fn [^objects params params-idx] (fn [^objects params ^long params-idx]
(if (i/params-needed-path? path) (if (i/params-needed-path? path)
(i/bind-params* path params (+ params-idx start-delta)) (i/bind-params* path params (+ params-idx start-delta))
path))) path)))

View file

@ -1,14 +1,15 @@
(ns com.rpl.specter.impl (ns com.rpl.specter.impl
#?(:cljs (:require-macros #?(:cljs (:require-macros
[com.rpl.specter.defhelpers :refer [define-ParamsNeededPath]] [com.rpl.specter.defhelpers :refer [define-ParamsNeededPath]]
[com.rpl.specter.util-macros :refer [doseqres]])) [com.rpl.specter.util-macros :refer [doseqres definterface+]]))
(:use [com.rpl.specter.protocols :only (:use [com.rpl.specter.protocols :only
[select* transform* collect-val Navigator]] [select* transform* collect-val Navigator]]
#?(:clj [com.rpl.specter.util-macros :only [doseqres]])) #?(:clj [com.rpl.specter.util-macros :only [doseqres definterface+]]))
(:require [com.rpl.specter.protocols :as p] (:require [com.rpl.specter.protocols :as p]
[clojure.string :as s] [clojure.string :as s]
[clojure.walk :as walk]
#?(:clj [com.rpl.specter.defhelpers :as dh]) #?(:clj [com.rpl.specter.defhelpers :as dh])
#?(:clj [riddley.walk :as riddley])) #?(:clj [riddley.walk :as riddley]))
@ -103,35 +104,35 @@
(deftype ExecutorFunctions [traverse-executor transform-executor]) (deftype ExecutorFunctions [traverse-executor transform-executor])
(deftype ParameterizedRichNav [rich-nav params params-idx]) (deftype ParameterizedRichNav [rich-nav params ^long params-idx])
(defprotocol RichNavigator (definterface+ RichNavigator
(rich-select* [this params params-idx vals structure next-fn]) (rich_select [this params ^long params-idx vals structure next-fn])
(rich-transform* [this params params-idx vals structure next-fn])) (rich_transform [this params ^long params-idx vals structure next-fn]))
#?( #?(
:clj :clj
(defmacro exec-rich-select* [this & args] (defmacro exec-rich_select [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})] (let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})]
`(.rich-select* ~hinted ~@args))) `(.rich_select ~hinted ~@args)))
:cljs :cljs
(defn exec-rich-select* [this params params-idx vals structure next-fn] (defn exec-rich_select [this params params-idx vals structure next-fn]
(rich-select* ^not-native this params params-idx vals structure next-fn))) (rich_select ^not-native this params params-idx vals structure next-fn)))
#?( #?(
:clj :clj
(defmacro exec-rich-transform* [this & args] (defmacro exec-rich_transform [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})] (let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})]
`(.rich-transform* ~hinted ~@args))) `(.rich_transform ~hinted ~@args)))
:cljs :cljs
(defn exec-rich-transform* [this params params-idx vals structure next-fn] (defn exec-rich_transform [this params params-idx vals structure next-fn]
(rich-transform* ^not-native this params params-idx vals structure next-fn))) (rich_transform ^not-native this params params-idx vals structure next-fn)))
#?( #?(
@ -161,7 +162,7 @@
(def RichPathExecutor (def RichPathExecutor
(->ExecutorFunctions (->ExecutorFunctions
(fn [^ParameterizedRichNav richnavp result-fn structure] (fn [^ParameterizedRichNav richnavp result-fn structure]
(exec-rich-select* (.-rich-nav richnavp) (exec-rich_select (.-rich-nav richnavp)
(.-params richnavp) (.-params-idx richnavp) (.-params richnavp) (.-params-idx richnavp)
[] structure [] structure
(fn [_ _ vals structure] (fn [_ _ vals structure]
@ -170,7 +171,7 @@
structure structure
(conj vals structure)))))) (conj vals structure))))))
(fn [^ParameterizedRichNav richnavp transform-fn structure] (fn [^ParameterizedRichNav richnavp transform-fn structure]
(exec-rich-transform* (.-rich-nav richnavp) (exec-rich_transform (.-rich-nav richnavp)
(.-params richnavp) (.-params-idx richnavp) (.-params richnavp) (.-params-idx richnavp)
[] structure [] structure
(fn [_ _ vals structure] (fn [_ _ vals structure]
@ -325,22 +326,30 @@
(coerce-path [this] (coerce-path [this]
(coerce-object this))) (coerce-object this)))
#?(:clj
(defn rich-nav? [o]
(instance? RichNavigator o))
:cljs
(defn rich-nav? [o]
(satisfies? RichNavigator o)))
(defn- combine-same-types [[n & _ :as all]] (defn- combine-same-types [[n & _ :as all]]
(let [combiner (let [combiner
(if (satisfies? RichNavigator n) (if (rich-nav? n)
(fn [curr next] (fn [curr next]
(reify RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(exec-rich-select* curr params params-idx vals structure (exec-rich_select curr params params-idx vals structure
(fn [params-next params-idx-next vals-next structure-next] (fn [params-next params-idx-next vals-next structure-next]
(exec-rich-select* next params-next params-idx-next (exec-rich_select next params-next params-idx-next
vals-next structure-next next-fn)))) vals-next structure-next next-fn))))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(exec-rich-transform* curr params params-idx vals structure (exec-rich_transform curr params params-idx vals structure
(fn [params-next params-idx-next vals-next structure-next] (fn [params-next params-idx-next vals-next structure-next]
(exec-rich-transform* next params-next params-idx-next (exec-rich_transform next params-next params-idx-next
vals-next structure-next next-fn)))))) vals-next structure-next next-fn))))))
(fn [curr next] (fn [curr next]
@ -356,13 +365,13 @@
(reduce combiner all))) (reduce combiner all)))
(defn coerce-rich-navigator [nav] (defn coerce-rich-navigator [nav]
(if (satisfies? RichNavigator nav) (if (rich-nav? nav)
nav nav
(reify RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(exec-select* nav structure (fn [structure] (next-fn params params-idx vals structure)))) (exec-select* nav structure (fn [structure] (next-fn params params-idx vals structure))))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(exec-transform* nav structure (fn [structure] (next-fn params params-idx vals structure))))))) (exec-transform* nav structure (fn [structure] (next-fn params params-idx vals structure)))))))
@ -386,13 +395,13 @@
path path
(no-params-rich-compiled-path (no-params-rich-compiled-path
(reify RichNavigator (reify RichNavigator
(rich-select* [this params2 params-idx2 vals structure next-fn] (rich_select [this params2 params-idx2 vals structure next-fn]
(exec-rich-select* rich-nav params params-idx vals structure (exec-rich_select rich-nav params params-idx vals structure
(fn [_ _ vals-next structure-next] (fn [_ _ vals-next structure-next]
(next-fn params2 params-idx2 vals-next structure-next)))) (next-fn params2 params-idx2 vals-next structure-next))))
(rich-transform* [this params2 params-idx2 vals structure next-fn] (rich_transform [this params2 params-idx2 vals structure next-fn]
(exec-rich-transform* rich-nav params params-idx vals structure (exec-rich_transform rich-nav params params-idx vals structure
(fn [_ _ vals-next structure-next] (fn [_ _ vals-next structure-next]
(next-fn params2 params-idx2 vals-next structure-next)))))))))) (next-fn params2 params-idx2 vals-next structure-next))))))))))
@ -401,7 +410,7 @@
(capture-params-internally (comp-paths* path))) (capture-params-internally (comp-paths* path)))
(defn nav-type [n] (defn nav-type [n]
(if (satisfies? RichNavigator n) (if (rich-nav? n)
:rich :rich
:lean)) :lean))
@ -652,6 +661,14 @@
#?(:cljs (instance? cljs.core.LazySeq f)) #?(:cljs (instance? cljs.core.LazySeq f))
(list? f))) (list? f)))
(defn codewalk-until [pred on-match-fn structure]
(if (pred structure)
(on-match-fn structure)
(let [ret (walk/walk (partial codewalk-until pred on-match-fn) identity structure)]
(if (and (fn-invocation? structure) (fn-invocation? ret))
(with-meta ret (meta structure))
ret))))
(defrecord LayeredNav [underlying]) (defrecord LayeredNav [underlying])
(defn layered-nav? [o] (instance? LayeredNav o)) (defn layered-nav? [o] (instance? LayeredNav o))
@ -766,13 +783,13 @@
(def pred* (def pred*
(->ParamsNeededPath (->ParamsNeededPath
(reify RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(let [afn (aget ^objects params params-idx)] (let [afn (aget ^objects params params-idx)]
(if (afn structure) (if (afn structure)
(next-fn params (inc params-idx) vals structure) (next-fn params (inc params-idx) vals structure)
NONE))) NONE)))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(let [afn (aget ^objects params params-idx)] (let [afn (aget ^objects params params-idx)]
(if (afn structure) (if (afn structure)
(next-fn params (inc params-idx) vals structure) (next-fn params (inc params-idx) vals structure)
@ -784,13 +801,13 @@
(def collected?* (def collected?*
(->ParamsNeededPath (->ParamsNeededPath
(reify RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(let [afn (aget ^objects params params-idx)] (let [afn (aget ^objects params params-idx)]
(if (afn vals) (if (afn vals)
(next-fn params (inc params-idx) vals structure) (next-fn params (inc params-idx) vals structure)
NONE))) NONE)))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(let [afn (aget ^objects params params-idx)] (let [afn (aget ^objects params params-idx)]
(if (afn vals) (if (afn vals)
(next-fn params (inc params-idx) vals structure) (next-fn params (inc params-idx) vals structure)
@ -802,11 +819,11 @@
(def rich-compiled-path-proxy (def rich-compiled-path-proxy
(->ParamsNeededPath (->ParamsNeededPath
(reify RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(let [apath ^CompiledPath (aget ^objects params params-idx) (let [apath ^CompiledPath (aget ^objects params params-idx)
pnav ^ParameterizedRichNav (.-nav apath) pnav ^ParameterizedRichNav (.-nav apath)
nav (.-rich-nav pnav)] nav (.-rich-nav pnav)]
(exec-rich-select* (exec-rich_select
nav nav
(.-params pnav) (.-params pnav)
(.-params-idx pnav) (.-params-idx pnav)
@ -815,11 +832,11 @@
(fn [_ _ vals-next structure-next] (fn [_ _ vals-next structure-next]
(next-fn params params-idx vals-next structure-next))))) (next-fn params params-idx vals-next structure-next)))))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(let [apath ^CompiledPath (aget ^objects params params-idx) (let [apath ^CompiledPath (aget ^objects params params-idx)
pnav ^ParameterizedRichNav (.-nav apath) pnav ^ParameterizedRichNav (.-nav apath)
nav (.-rich-nav pnav)] nav (.-rich-nav pnav)]
(exec-rich-transform* (exec-rich_transform
nav nav
(.-params pnav) (.-params pnav)
(.-params-idx pnav) (.-params-idx pnav)
@ -834,7 +851,7 @@
(def lean-compiled-path-proxy (def lean-compiled-path-proxy
(->ParamsNeededPath (->ParamsNeededPath
(reify RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(let [^CompiledPath apath (aget ^objects params params-idx) (let [^CompiledPath apath (aget ^objects params params-idx)
^Navigator nav (.-nav apath)] ^Navigator nav (.-nav apath)]
(exec-select* (exec-select*
@ -843,7 +860,7 @@
(fn [structure-next] (fn [structure-next]
(next-fn params params-idx vals structure-next))))) (next-fn params params-idx vals structure-next)))))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(let [^CompiledPath apath (aget ^objects params params-idx) (let [^CompiledPath apath (aget ^objects params params-idx)
^Navigator nav (.-nav apath)] ^Navigator nav (.-nav apath)]
(exec-transform* (exec-transform*

View file

@ -1,9 +1,9 @@
(ns com.rpl.specter.macros (ns com.rpl.specter.macros
(:use [com.rpl.specter.protocols :only [Navigator]] (:use [com.rpl.specter.protocols :only [Navigator]])
[com.rpl.specter.impl :only [RichNavigator]])
(:require [com.rpl.specter.impl :as i] (:require [com.rpl.specter.impl :as i]
[clojure.walk :as cljwalk] [clojure.walk :as cljwalk]
[com.rpl.specter.defnavhelpers :as dnh])) [com.rpl.specter.defnavhelpers :as dnh])
(:import [com.rpl.specter.impl RichNavigator]))
(defn ^:no-doc gensyms [amt] (defn ^:no-doc gensyms [amt]
@ -34,10 +34,10 @@
`(let [num-params# ~num-params `(let [num-params# ~num-params
nav# (reify RichNavigator nav# (reify RichNavigator
(~'rich-select* ~s-params (~'rich_select ~s-params
(let [~s-next-fn-sym (i/mk-jump-next-fn ~s-next-fn-sym ~s-pidx-sym num-params#)] (let [~s-next-fn-sym (i/mk-jump-next-fn ~s-next-fn-sym ~s-pidx-sym num-params#)]
~@s-body)) ~@s-body))
(~'rich-transform* ~t-params (~'rich_transform ~t-params
(let [~t-next-fn-sym (i/mk-jump-next-fn ~t-next-fn-sym ~t-pidx-sym num-params#)] (let [~t-next-fn-sym (i/mk-jump-next-fn ~t-next-fn-sym ~t-pidx-sym num-params#)]
~@t-body)))] ~@t-body)))]
@ -62,20 +62,20 @@
`(let [~@binding-fn-declarations] `(let [~@binding-fn-declarations]
~body))) ~body)))
(defmacro ^:no-doc rich-nav-with-bindings [num-params-code bindings & impls]
(defn- rich-nav-with-bindings-not-inlined [num-params-code bindings impls]
(let [{[[_ s-structure-sym s-next-fn-sym] & s-body] 'select* (let [{[[_ s-structure-sym s-next-fn-sym] & s-body] 'select*
[[_ t-structure-sym t-next-fn-sym] & t-body] 'transform*} [[_ t-structure-sym t-next-fn-sym] & t-body] 'transform*}
(determine-params-impls impls) (determine-params-impls impls)
params-sym (gensym "params") params-sym (gensym "params")
params-idx-sym (gensym "params-idx")] params-idx-sym (gensym "params-idx")]
(operation-with-bindings (operation-with-bindings
bindings bindings
params-sym params-sym
params-idx-sym params-idx-sym
(fn [binding-declarations] (fn [binding-declarations]
`(reify RichNavigator `(reify RichNavigator
(~'rich-select* [this# ~params-sym ~params-idx-sym vals# ~s-structure-sym next-fn#] (~'rich_select [this# ~params-sym ~params-idx-sym vals# ~s-structure-sym next-fn#]
(let [~@binding-declarations (let [~@binding-declarations
next-params-idx# (+ ~params-idx-sym ~num-params-code) next-params-idx# (+ ~params-idx-sym ~num-params-code)
~s-next-fn-sym (fn [structure#] ~s-next-fn-sym (fn [structure#]
@ -85,7 +85,7 @@
structure#))] structure#))]
~@s-body)) ~@s-body))
(~'rich-transform* [this# ~params-sym ~params-idx-sym vals# ~t-structure-sym next-fn#] (~'rich_transform [this# ~params-sym ~params-idx-sym vals# ~t-structure-sym next-fn#]
(let [~@binding-declarations (let [~@binding-declarations
next-params-idx# (+ ~params-idx-sym ~num-params-code) next-params-idx# (+ ~params-idx-sym ~num-params-code)
~t-next-fn-sym (fn [structure#] ~t-next-fn-sym (fn [structure#]
@ -95,6 +95,44 @@
structure#))] structure#))]
~@t-body))))))) ~@t-body)))))))
(defn inline-next-fn [body next-fn-sym extra-params]
(i/codewalk-until
#(and (i/fn-invocation? %) (= next-fn-sym (first %)))
(fn [code]
(let [code (map #(inline-next-fn % next-fn-sym extra-params) code)]
(concat [next-fn-sym] extra-params (rest code))))
body))
(defn- rich-nav-with-bindings-inlined [num-params-code bindings impls]
(let [{[[_ s-structure-sym s-next-fn-sym] & s-body] 'select*
[[_ t-structure-sym t-next-fn-sym] & t-body] 'transform*}
(determine-params-impls impls)
params-sym (gensym "params")
params-idx-sym (gensym "params-idx")
vals-sym (gensym "vals")
next-params-idx-sym (gensym "next-params-idx")
s-body (inline-next-fn s-body s-next-fn-sym [params-sym next-params-idx-sym vals-sym])
t-body (inline-next-fn t-body t-next-fn-sym [params-sym next-params-idx-sym vals-sym])]
(operation-with-bindings
bindings
params-sym
params-idx-sym
(fn [binding-declarations]
`(reify RichNavigator
(~'rich_select [this# ~params-sym ~params-idx-sym ~vals-sym ~s-structure-sym ~s-next-fn-sym]
(let [~@binding-declarations
~next-params-idx-sym (+ ~params-idx-sym ~num-params-code)]
~@s-body))
(~'rich_transform [this# ~params-sym ~params-idx-sym ~vals-sym ~t-structure-sym ~t-next-fn-sym]
(let [~@binding-declarations
~next-params-idx-sym (+ ~params-idx-sym ~num-params-code)]
~@t-body)))))))
(defmacro ^:no-doc rich-nav-with-bindings [opts num-params-code bindings & impls]
(if (:inline-next-fn opts)
(rich-nav-with-bindings-inlined num-params-code bindings impls)
(rich-nav-with-bindings-not-inlined num-params-code bindings impls)))
(defmacro ^:no-doc collector-with-bindings [num-params-code bindings impl] (defmacro ^:no-doc collector-with-bindings [num-params-code bindings impl]
@ -112,9 +150,9 @@
(next-fn# ~params-sym (+ ~params-idx-sym num-params#) (conj vals# (do ~@body)) ~structure-sym)))] (next-fn# ~params-sym (+ ~params-idx-sym num-params#) (conj vals# (do ~@body)) ~structure-sym)))]
(reify RichNavigator (reify RichNavigator
(~'rich-select* [this# params# params-idx# vals# structure# next-fn#] (~'rich_select [this# params# params-idx# vals# structure# next-fn#]
(cfn# params# params-idx# vals# structure# next-fn#)) (cfn# params# params-idx# vals# structure# next-fn#))
(~'rich-transform* [this# params# params-idx# vals# structure# next-fn#] (~'rich_transform [this# params# params-idx# vals# structure# next-fn#]
(cfn# params# params-idx# vals# structure# next-fn#)))))))) (cfn# params# params-idx# vals# structure# next-fn#))))))))
@ -130,21 +168,25 @@
with other navigators without knowing the parameters. When precompiled with other with other navigators without knowing the parameters. When precompiled with other
navigators, the resulting path takes in parameters for all navigators in the path navigators, the resulting path takes in parameters for all navigators in the path
that needed parameters (in the order in which they were declared)." that needed parameters (in the order in which they were declared)."
[params & impls] [& impl]
(if (empty? params) (let [[opts params & impls] (if (map? (first impl))
`(i/lean-compiled-path (lean-nav* ~@impls)) impl
`(vary-meta (cons {} impl))]
(fn ~params (i/lean-compiled-path (lean-nav* ~@impls))) (if (empty? params)
assoc `(i/lean-compiled-path (lean-nav* ~@impls))
:highernav `(vary-meta
{:type :lean (fn ~params (i/lean-compiled-path (lean-nav* ~@impls)))
:params-needed-path assoc
(i/->ParamsNeededPath :highernav
(rich-nav-with-bindings ~(count params) {:type :lean
~(delta-param-bindings params) :params-needed-path
~@impls) (i/->ParamsNeededPath
(rich-nav-with-bindings ~opts
~(count params)
~(delta-param-bindings params)
~@impls)
~(count params))}))) ~(count params))}))))
(defmacro collector (defmacro collector
@ -214,7 +256,8 @@
(i/lean-compiled-path (lean-nav* ~@impls))) (i/lean-compiled-path (lean-nav* ~@impls)))
(i/->ParamsNeededPath (i/->ParamsNeededPath
(rich-nav-with-bindings ~total-params-sym (rich-nav-with-bindings {}
~total-params-sym
~runtime-bindings ~runtime-bindings
~@impls) ~@impls)
@ -297,13 +340,13 @@
`(do `(do
(defprotocol ~prot-name (~m [structure#])) (defprotocol ~prot-name (~m [structure#]))
(let [nav# (reify RichNavigator (let [nav# (reify RichNavigator
(~'rich-select* [this# ~@rargs] (~'rich_select [this# ~@rargs]
(let [inav# ~retrieve] (let [inav# ~retrieve]
(i/exec-rich-select* inav# ~@rargs))) (i/exec-rich_select inav# ~@rargs)))
(~'rich-transform* [this# ~@rargs] (~'rich_transform [this# ~@rargs]
(let [inav# ~retrieve] (let [inav# ~retrieve]
(i/exec-rich-transform* inav# ~@rargs))))] (i/exec-rich_transform inav# ~@rargs))))]
(def ~name (def ~name
(if (= ~num-params 0) (if (= ~num-params 0)
@ -325,11 +368,11 @@
([name params] ([name params]
(let [platform (if (contains? &env :locals) :cljs :clj) (let [platform (if (contains? &env :locals) :cljs :clj)
select-exec (if (= platform :clj) select-exec (if (= platform :clj)
`i/exec-rich-select* `i/exec-rich_select
`i/rich-select*) `i/rich_select)
transform-exec (if (= platform :clj) transform-exec (if (= platform :clj)
`i/exec-rich-transform* `i/exec-rich_transform
`i/rich-transform*) `i/rich_transform)
num-params (count params) num-params (count params)
declared (declared-name name) declared (declared-name name)
rargs [(gensym "params") (gensym "pidx") (gensym "vals") rargs [(gensym "params") (gensym "pidx") (gensym "vals")
@ -338,9 +381,9 @@
(declare ~declared) (declare ~declared)
(def ~name (def ~name
(let [nav# (reify RichNavigator (let [nav# (reify RichNavigator
(~'rich-select* [this# ~@rargs] (~'rich_select [this# ~@rargs]
(~select-exec ~declared ~@rargs)) (~select-exec ~declared ~@rargs))
(~'rich-transform* [this# ~@rargs] (~'rich_transform [this# ~@rargs]
(~transform-exec ~declared ~@rargs)))] (~transform-exec ~declared ~@rargs)))]
(if (= ~num-params 0) (if (= ~num-params 0)

View file

@ -14,11 +14,14 @@
[doseqres]])) [doseqres]]))
(:use #?(:clj [com.rpl.specter macros]) (:use #?(:clj [com.rpl.specter macros])
#?(:clj [com.rpl.specter.util-macros :only [doseqres]])) #?(:clj [com.rpl.specter.util-macros :only [doseqres]])
#?(:cljs [com.rpl.specter.impl :only [RichNavigator]]))
(:require [com.rpl.specter.impl :as i] (:require [com.rpl.specter.impl :as i]
[clojure.walk :as walk] [clojure.walk :as walk]
#?(:clj [clojure.core.reducers :as r]) #?(:clj [clojure.core.reducers :as r])
[com.rpl.specter.defnavhelpers])) ; so that for cljs it's loaded as macros expand to this ; so that for cljs it's loaded as macros expand to this
[com.rpl.specter.defnavhelpers])
#?(:clj (:import [com.rpl.specter.impl RichNavigator])))
@ -293,7 +296,7 @@
then-nav then-nav
else-nav) else-nav)
idx (if test? params-idx (+ params-idx then-params))] idx (if test? params-idx (+ params-idx then-params))]
(i/exec-rich-select* (i/exec-rich_select
sel sel
params params
idx idx
@ -309,7 +312,7 @@
then-nav then-nav
else-nav) else-nav)
idx (if test? params-idx (+ params-idx then-params))] idx (if test? params-idx (+ params-idx then-params))]
(i/exec-rich-transform* (i/exec-rich_transform
tran tran
params params
idx idx
@ -460,19 +463,11 @@
(walk/walk (partial walk-until pred on-match-fn) identity structure))) (walk/walk (partial walk-until pred on-match-fn) identity structure)))
(defn codewalk-until [pred on-match-fn structure]
(if (pred structure)
(on-match-fn structure)
(let [ret (walk/walk (partial codewalk-until pred on-match-fn) identity structure)]
(if (and (i/fn-invocation? structure) (i/fn-invocation? ret))
(with-meta ret (meta structure))
ret))))
(def DISPENSE* (def DISPENSE*
(i/no-params-rich-compiled-path (i/no-params-rich-compiled-path
(reify i/RichNavigator (reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn] (rich_select [this params params-idx vals structure next-fn]
(next-fn params params-idx [] structure)) (next-fn params params-idx [] structure))
(rich-transform* [this params params-idx vals structure next-fn] (rich_transform [this params params-idx vals structure next-fn]
(next-fn params params-idx [] structure))))) (next-fn params params-idx [] structure)))))

View file

@ -10,3 +10,12 @@
~backup-res ~backup-res
~aseq)) ~aseq))
(defmacro definterface+ [name & methods]
(let [platform (if (contains? &env :locals) :cljs :clj)]
(if (= platform :cljs)
`(defprotocol ~name ~@methods)
(let [methods (for [[n p & body] methods]
(concat [n (-> p next vec)] body))]
`(definterface ~name ~@methods)))))