diff --git a/src/cljs/cljs/analyzer.cljs b/src/cljs/cljs/analyzer.cljs index 59cf8da5c1..aeb2bdc8ac 100644 --- a/src/cljs/cljs/analyzer.cljs +++ b/src/cljs/cljs/analyzer.cljs @@ -864,27 +864,20 @@ (assoc ret :op :var :info lb) (assoc ret :op :var :info (resolve-existing-var env sym))))) +(defn is-macro? [sym] + (let [var (resolve-existing-var (empty-env) sym) + ns (:ns var) + name (symbol (name (:name var)))] + (get-in @namespaces [:macros ns name]))) + (defn get-expander [sym env] - (let [mvar - (when-not (or (-> env :locals sym) ;locals hide macros - (and (or (-> env :ns :excludes sym) - (get-in @namespaces [(-> env :ns :name) :excludes sym])) - (not (or (-> env :ns :uses-macros sym) - (get-in @namespaces [(-> env :ns :name) :uses-macros sym]))))) - (if-let [nstr (namespace sym)] - (when-let [ns (cond - (= "clojure.core" nstr) (find-ns 'cljs.core) - (>= (.indexOf nstr ".") 0) (find-ns (symbol nstr)) - :else - (-> env :ns :requires-macros (get (symbol nstr))))] - (.findInternedVar ^clojure.lang.Namespace ns (symbol (name sym)))) - (if-let [nsym (-> env :ns :uses-macros sym)] - (.findInternedVar ^clojure.lang.Namespace (find-ns nsym) sym) - (.findInternedVar ^clojure.lang.Namespace (find-ns 'cljs.core) sym))))] - (when (and mvar (.isMacro ^clojure.lang.Var mvar)) - @mvar))) - -;; JOELM: we will need this eventually + (let [var (resolve-existing-var (empty-env) sym) + ns (:ns var) + name (symbol (name (:name var)))] + ;(println "// get-expander:" sym ns name) + (when (is-macro? sym) + (js/eval (str ns "." name))))) + (defn macroexpand-1 [env form] (let [op (first form)] (if (specials op) @@ -904,8 +897,6 @@ :else form)) form))))) -(defn macroexpand-1 [env form] form) - (defn analyze-seq [env form name] (let [env (assoc env :line diff --git a/src/cljs/cljs/core.cljs b/src/cljs/cljs/core.cljs index fe37b6841a..c669522cfe 100644 --- a/src/cljs/cljs/core.cljs +++ b/src/cljs/cljs/core.cljs @@ -7217,3 +7217,63 @@ reduces them without incurring seq initialization" (def namespaces (atom '{cljs.core {:name cljs.core} cljs.user {:name cljs.user}})) +(defn setMacro [sym] + (let [ns (symbol (or (namespace sym) + (try cljs.analyzer/*cljs-ns* + (catch js/Error e 'cljs.core)))) + name (symbol (name sym))] + (swap! namespaces assoc-in [:macros ns name] true)) + nil) + +(def + + ^{:doc "Like defn, but the resulting function name is declared as a + macro and will be used as a macro by the compiler when it is + called." + :arglists '([name doc-string? attr-map? [params*] body] + [name doc-string? attr-map? ([params*] body)+ attr-map?]) + :added "1.0"} + defmacro (fn [&form &env + name & args] + (let [prefix (loop [p (list name) args args] + (let [f (first args)] + (if (string? f) + (recur (cons f p) (next args)) + (if (map? f) + (recur (cons f p) (next args)) + p)))) + fdecl (loop [fd args] + (if (string? (first fd)) + (recur (next fd)) + (if (map? (first fd)) + (recur (next fd)) + fd))) + fdecl (if (vector? (first fdecl)) + (list fdecl) + fdecl) + add-implicit-args (fn [fd] + (let [args (first fd)] + (cons (vec (cons '&form (cons '&env args))) (next fd)))) + add-args (fn [acc ds] + (if (nil? ds) + acc + (let [d (first ds)] + (if (map? d) + (conj acc d) + (recur (conj acc (add-implicit-args d)) (next ds)))))) + fdecl (seq (add-args [] fdecl)) + decl (loop [p prefix d fdecl] + (if p + (recur (next p) (cons (first p) d)) + d))] + (prn "defmacro here1: ") + (list 'do + (list 'def (first decl) (cons `fn* (first (rest decl)))) + #_(cons `defn decl) + #_(list '. (list 'var name) '(setMacro)) + (list 'cljs.core/setMacro (list 'quote name)) + #_(list 'var name))))) + +#_(. (var defmacro) (setMacro)) +(setMacro 'cljs.core/defmacro) +