diff --git a/src/clj/com/rpl/specter/impl.cljc b/src/clj/com/rpl/specter/impl.cljc index d3b6023..3634795 100644 --- a/src/clj/com/rpl/specter/impl.cljc +++ b/src/clj/com/rpl/specter/impl.cljc @@ -766,18 +766,32 @@ :else (coerce-nav o))) +(defn used-locals [locals-set form] + (let [used-locals-cell (mutable-cell [])] + (walk/postwalk + (fn [e] + (if (contains? locals-set e) + (update-cell! used-locals-cell #(conj % e)) + e)) + form) + (get-cell used-locals-cell))) -(defn magic-precompilation [path ns-str used-locals] +(defn magic-precompilation [path ns-str used-locals-list] ; (println "before magic-precompilation*:" path) - (let [path (magic-precompilation* path) + (let [used-locals-set (set used-locals-list) + path (magic-precompilation* path) ; _ (println "magic-precompilation*" path) ns (find-ns (symbol ns-str)) + final-code (resolve-magic-code (->DynamicPath path)) + ;; this handles the case where a dynamicnav ignores a dynamic arg and produces + ;; something static instead + static? (empty? (used-locals used-locals-set final-code)) maker (binding [*ns* ns] (eval+ ; (spy - `(fn [~@used-locals] - ~(resolve-magic-code (->DynamicPath path)))))] - (if (static-path? path) + `(fn [~@(if static? [] used-locals-list)] + ~final-code)))] + (if static? (->CachedPathInfo false (maker)) (->CachedPathInfo true maker)))) diff --git a/src/clj/com/rpl/specter/macros.clj b/src/clj/com/rpl/specter/macros.clj index 1f907f7..981c0f0 100644 --- a/src/clj/com/rpl/specter/macros.clj +++ b/src/clj/com/rpl/specter/macros.clj @@ -137,16 +137,6 @@ `(def ~name (dynamicnav ~@args)))) -(defn- used-locals [locals-set form] - (let [used-locals-cell (i/mutable-cell [])] - (cljwalk/postwalk - (fn [e] - (if (locals-set e) - (i/update-cell! used-locals-cell #(conj % e)) - e)) - form) - (i/get-cell used-locals-cell))) - (defn ^:no-doc ic-prepare-path [locals-set path] (cond (vector? path) @@ -174,7 +164,7 @@ :else - (if (empty? (used-locals locals-set path)) + (if (empty? (i/used-locals locals-set path)) path `(com.rpl.specter.impl/->DynamicVal (quote ~path))))) @@ -230,7 +220,7 @@ (-> &env :locals keys set) ;cljs (-> &env keys set)) ;clj - used-locals (used-locals local-syms path) + used-locals (i/used-locals local-syms path) ;; note: very important to use riddley's macroexpand-all here, so that ;; &env is preserved in any potential nested calls to select (like via diff --git a/test/com/rpl/specter/core_test.cljc b/test/com/rpl/specter/core_test.cljc index b221794..0c58eb6 100644 --- a/test/com/rpl/specter/core_test.cljc +++ b/test/com/rpl/specter/core_test.cljc @@ -9,7 +9,8 @@ nav declarepath providepath select select-one select-one! select-first transform setval replace-in select-any selected-any? collected? traverse - multi-transform path dynamicnav recursive-path]])) + multi-transform path dynamicnav recursive-path + defdynamicnav]])) (:use #?(:clj [clojure.test :only [deftest is]]) #?(:clj [clojure.test.check.clojure-test :only [defspec]]) @@ -19,7 +20,8 @@ nav declarepath providepath select select-one select-one! select-first transform setval replace-in select-any selected-any? collected? traverse - multi-transform path dynamicnav recursive-path]])) + multi-transform path dynamicnav recursive-path + defdynamicnav]])) @@ -1273,3 +1275,12 @@ [#(= 100 %) (s/terminal inc)] [#(= 101 %) (s/terminal inc)]) 1)))) + + +(defdynamicnav ignorer [a] + s/STAY) + +(deftest dynamic-nav-ignores-dynamic-arg + (let [a 1] + (is (= 1 (select-any (ignorer a) 1))) + (is (= 1 (select-any (ignorer :a) 1)))))