diff --git a/project.clj b/project.clj index 19116a8..ef036a1 100644 --- a/project.clj +++ b/project.clj @@ -7,8 +7,7 @@ :test-paths ["test", "target/test-classes"] :jar-exclusions [#"\.cljx"] :auto-clean false - :dependencies [[org.clojure/tools.macro "0.1.2"] - [riddley "0.1.12"]] + :dependencies [[riddley "0.1.12"]] :profiles {:provided {:dependencies [[org.clojure/clojure "1.6.0"] [org.clojure/clojurescript "0.0-3211"]]} diff --git a/src/clj/com/rpl/specter/impl.cljx b/src/clj/com/rpl/specter/impl.cljx index 9da2099..2c36661 100644 --- a/src/clj/com/rpl/specter/impl.cljx +++ b/src/clj/com/rpl/specter/impl.cljx @@ -11,11 +11,44 @@ #+clj [clojure.core.reducers :as r] [clojure.string :as s] #+clj [com.rpl.specter.defhelpers :as dh] + #+clj [riddley.walk :as riddley] ) #+clj (:import [com.rpl.specter Util]) ) +;; these macroexpand functions are for path macro in bootstrap cljs +;; environment +#+cljs +(defn macroexpand' + [form] + (binding [cljs/*eval-fn* cljs/js-eval] + (cljs/eval (cljs/empty-state) + `(macroexpand (quote ~form)) + identity))) + +#+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 do-macroexpand-all [form] + (riddley/macroexpand-all form)) + +#+cljs +(defn gen-uuid-str [] + (apply str (repeatedly 50 #(rand-int 9))) + ) + +#+clj +(defn gen-uuid-str [] + (str (java.util.UUID/randomUUID))) (defn spy [e] (println "SPY:") @@ -435,8 +468,9 @@ )) (defn fn-invocation? [f] - (or (instance? clojure.lang.Cons f) - (instance? clojure.lang.LazySeq f) + (or #+clj (instance? clojure.lang.Cons f) + #+clj (instance? clojure.lang.LazySeq f) + #+cljs (instance? cljs.core.LazySeq f) (list? f))) (defn codewalk-until [pred on-match-fn structure] diff --git a/src/clj/com/rpl/specter/macros.clj b/src/clj/com/rpl/specter/macros.clj index 483bfa2..61ac9a6 100644 --- a/src/clj/com/rpl/specter/macros.clj +++ b/src/clj/com/rpl/specter/macros.clj @@ -1,7 +1,5 @@ (ns com.rpl.specter.macros - (:require [com.rpl.specter.impl :as i] - [clojure.tools.macro :as m] - [riddley.walk :as walk]) + (:require [com.rpl.specter.impl :as i]) ) (defn gensyms [amt] @@ -314,12 +312,38 @@ (defmacro extend-protocolpath [protpath & extensions] `(i/extend-protocolpath* ~protpath ~(protpath-sym protpath) ~(vec extensions))) +;; copied from tools.macro to avoid the dependency +(defn name-with-attributes + "To be used in macro definitions. + Handles optional docstrings and attribute maps for a name to be defined + in a list of macro arguments. If the first macro argument is a string, + it is added as a docstring to name and removed from the macro argument + list. If afterwards the first macro argument is a map, its entries are + added to the name's metadata map and the map is removed from the + macro argument list. The return value is a vector containing the name + with its extended metadata map and the list of unprocessed macro + arguments." + [name macro-args] + (let [[docstring macro-args] (if (string? (first macro-args)) + [(first macro-args) (next macro-args)] + [nil macro-args]) + [attr macro-args] (if (map? (first macro-args)) + [(first macro-args) (next macro-args)] + [{} macro-args]) + attr (if docstring + (assoc attr :doc docstring) + attr) + attr (if (meta name) + (conj (meta name) attr) + attr)] + [(with-meta name attr) macro-args])) + (defmacro defpathedfn [name & args] - (let [[name args] (m/name-with-attributes name args)] + (let [[name args] (name-with-attributes name args)] `(def ~name (vary-meta (fn ~@args) assoc :pathedfn true)))) (defmacro defnavconstructor [name & args] - (let [[name [[csym anav] & body-or-bodies]] (m/name-with-attributes name args) + (let [[name [[csym anav] & body-or-bodies]] (name-with-attributes name args) bodies (if (-> body-or-bodies first vector?) [body-or-bodies] body-or-bodies) checked-code @@ -402,7 +426,7 @@ ;; 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 (walk/macroexpand-all (vec path)) + expanded (i/do-macroexpand-all (vec path)) prepared-path (ic-prepare-path local-syms expanded) possible-params (vec (ic-possible-params expanded)) @@ -415,7 +439,7 @@ ;; - with invokedynamic here, could go directly to the code ;; to invoke and/or parameterize the precompiled path without ;; a bunch of checks beforehand - cache-id (str (java.util.UUID/randomUUID)) + cache-id (i/gen-uuid-str) precompiled-sym (gensym "precompiled") params-maker-sym (gensym "params-maker")