diff --git a/src/clj/com/rpl/specter/impl.cljx b/src/clj/com/rpl/specter/impl.cljx index 10aad44..4d21127 100644 --- a/src/clj/com/rpl/specter/impl.cljx +++ b/src/clj/com/rpl/specter/impl.cljx @@ -48,28 +48,29 @@ (defn throw-illegal [& args] (throw (js/Error. (apply str args)))) -;; these macroexpand functions are for path macro in bootstrap cljs environment -#+cljs -(defn macroexpand' - [form] - (let [orig-eval-fn ^:cljs.analyzer/no-resolve cljs.js/*eval-fn*] - (try - (set! ^:cljs.analyzer/no-resolve cljs.js/*eval-fn* ^:cljs.analyzer/no-resolve cljs.js/js-eval) - (^:cljs.analyzer/no-resolve cljs.js/eval (^:cljs.analyzer/no-resolve cljs.js/empty-state) - `(macroexpand (quote ~form)) - identity) - (finally - (set! ^:cljs.analyzer/no-resolve cljs.js/*eval-fn* orig-eval-fn))))) -#+cljs -(defn do-macroexpand-all - "Recursively performs all possible macroexpansions in form." - {:added "1.1"} - [form] - (walk/prewalk (fn [x] - (if (seq? x) - (macroexpand' x) - x)) form)) +;; these macroexpand functions are for path macro in bootstrap cljs environment +; #+cljs +; (defn macroexpand' +; [form] +; (let [orig-eval-fn ^:cljs.analyzer/no-resolve cljs.js/*eval-fn*] +; (try +; (set! ^:cljs.analyzer/no-resolve cljs.js/*eval-fn* ^:cljs.analyzer/no-resolve cljs.js/js-eval) +; (^:cljs.analyzer/no-resolve cljs.js/eval (^:cljs.analyzer/no-resolve cljs.js/empty-state) +; `(macroexpand (quote ~form)) +; identity) +; (finally +; (set! ^:cljs.analyzer/no-resolve cljs.js/*eval-fn* orig-eval-fn))))) + +; #+cljs +; (defn do-macroexpand-all +; "Recursively performs all possible macroexpansions in form." +; {:added "1.1"} +; [form] +; (walk/prewalk (fn [x] +; (if (seq? x) +; (macroexpand' x) +; x)) form)) #+clj (defn intern* [ns name val] (intern ns name val)) @@ -78,10 +79,6 @@ (defn intern* [ns name val] (throw-illegal "intern not supported in ClojureScript")) -#+clj -(defn do-macroexpand-all [form] - (riddley/macroexpand-all form)) - ;; so that macros.clj compiles appropriately when ;; run in cljs (this code isn't called in that case) #+cljs diff --git a/src/clj/com/rpl/specter/macros.clj b/src/clj/com/rpl/specter/macros.clj index 972db0f..7174d72 100644 --- a/src/clj/com/rpl/specter/macros.clj +++ b/src/clj/com/rpl/specter/macros.clj @@ -1,6 +1,7 @@ (ns com.rpl.specter.macros (:require [com.rpl.specter.impl :as i] - [clojure.walk :as cljwalk]) + [clojure.walk :as cljwalk] + [riddley.walk :as riddley]) ) (defn ^:no-doc gensyms [amt] @@ -444,6 +445,27 @@ path ))) +(defn cljs-macroexpand [env form] + (require 'cljs.analyzer) + (let [expand-fn (eval 'cljs.analyzer/macroexpand-1) + mform (expand-fn env form)] + (cond (identical? form mform) mform + (and (seq? mform) (#{'js*} (first mform))) form + :else (cljs-macroexpand env mform)))) + +(defn cljs-macroexpand-all* [env form] + (if (and (seq? form) + (#{'fn 'fn* 'cljs.core/fn} (first form))) + form + (let [expanded (if (seq? form) (cljs-macroexpand env form) form)] + (cljwalk/walk #(cljs-macroexpand-all* env %) identity expanded) + ))) + +(defn cljs-macroexpand-all [env form] + (let [ret (cljs-macroexpand-all* env form)] + ret + )) + ;; still possible to mess this up with alter-var-root (defmacro path "Same as calling comp-paths, except it caches the composition of the static part @@ -470,7 +492,10 @@ ;; note: very important to use riddley's macroexpand-all here, so that ;; &env is preserved in any potential nested calls to select (like via ;; a view function) - expanded (i/do-macroexpand-all (vec path)) + expanded (if (= platform :clj) + (riddley/macroexpand-all (vec path)) + (cljs-macroexpand-all &env (vec path))) + prepared-path (ic-prepare-path local-syms expanded) possible-params (vec (ic-possible-params expanded)) @@ -624,11 +649,8 @@ "Creates a filter function navigator that takes in all the collected values as input. For arguments, can use `(collected? [a b] ...)` syntax to look at each collected value as individual arguments, or `(collected? v ...)` syntax - to capture all the collected values as a single vector. - - For ClojureScript, since can't use macros inside path when that path will be - inline factored/cached, to use collected? declare the logic in a global - variable such as (def my-collected (collected? [v] (= v 1)))" + to capture all the collected values as a single vector." [params & body] - `(i/collected?* (fn [~params] ~@body)) - ) + (let [platform (if (contains? &env :locals) :cljs :clj)] + `(i/collected?* (~'fn [~params] ~@body)) + )) diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index 81c02fd..ec8c48b 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -1224,10 +1224,6 @@ m) ))) - -;; clojure only because inability to use macroexpand inside path macro in -;; clojurescript makes it impossible to use macros inside the path -#+clj (deftest collected?-test (let [data {:active-id 1 :items [{:id 1 :name "a"} {:id 2 :name "b"}]}] (is (= {:id 1 :name "a"}