diff options
author | Konrad Hinsen <konrad.hinsen@fastmail.net> | 2010-09-03 21:32:12 +0200 |
---|---|---|
committer | Konrad Hinsen <konrad.hinsen@fastmail.net> | 2010-09-03 21:32:12 +0200 |
commit | 67fccc60f2a547f272df858c7367ef805d123ffc (patch) | |
tree | 76b1538ea7687f223d0140962528e2772dc3f2da | |
parent | 330807c6d93f9a3c2bad4c8f4dd6295b6cf2053e (diff) |
macro-utils: don't expand symbols bound in the surrounding lexical environment
-rw-r--r-- | modules/macro-utils/src/main/clojure/clojure/contrib/macro_utils.clj | 29 | ||||
-rw-r--r-- | modules/macro-utils/src/test/clojure/clojure/contrib/test_macro_utils.clj | 5 |
2 files changed, 22 insertions, 12 deletions
diff --git a/modules/macro-utils/src/main/clojure/clojure/contrib/macro_utils.clj b/modules/macro-utils/src/main/clojure/clojure/contrib/macro_utils.clj index e101f712..98180b3e 100644 --- a/modules/macro-utils/src/main/clojure/clojure/contrib/macro_utils.clj +++ b/modules/macro-utils/src/main/clojure/clojure/contrib/macro_utils.clj @@ -1,7 +1,7 @@ ;; Macrolet and symbol-macrolet ;; by Konrad Hinsen -;; last updated January 14, 2010 +;; last updated September 3, 2010 ;; Copyright (c) Konrad Hinsen, 2009-2010. All rights reserved. The use ;; and distribution terms for this software are covered by the Eclipse @@ -47,18 +47,19 @@ ; Symbols defined inside let forms or function arguments. (defvar- protected-symbols #{}) -(defn- reserved? +(defn- protected? [symbol] - "Return true if symbol is a reserved symbol (starting or ending with a dot)." - (let [s (str symbol)] - (or (= "." (subs s 0 1)) - (= "." (subs s (dec (count s))))))) + "Return true if symbol is a reserved symbol (starting or ending with a dot) + or a symbol bound in a surrounding let form or as a function argument." + (or (contains? protected-symbols symbol) + (let [s (str symbol)] + (or (= "." (subs s 0 1)) + (= "." (subs s (dec (count s)))))))) (defn- expand-symbol "Expand symbol macros" [symbol] - (cond (contains? protected-symbols symbol) symbol - (reserved? symbol) symbol + (cond (protected? symbol) symbol (contains? macro-symbols symbol) (get macro-symbols symbol) :else (let [v (resolve symbol) m (meta v)] @@ -74,10 +75,14 @@ (let [f (first form)] (cond (contains? special-forms f) form (contains? macro-fns f) (apply (get macro-fns f) (rest form)) - (symbol? f) (let [exp (expand-symbol f)] - (if (= exp f) - (clojure.core/macroexpand-1 form) - (cons exp (rest form)))) + (symbol? f) (cond + (protected? f) form + ; macroexpand-1 fails if f names a class + (class? (ns-resolve *ns* f)) form + :else (let [exp (expand-symbol f)] + (if (= exp f) + (clojure.core/macroexpand-1 form) + (cons exp (rest form))))) ; handle defmacro macros and Java method special forms :else (clojure.core/macroexpand-1 form))) (symbol? form) diff --git a/modules/macro-utils/src/test/clojure/clojure/contrib/test_macro_utils.clj b/modules/macro-utils/src/test/clojure/clojure/contrib/test_macro_utils.clj index 448898fa..d23c1ab9 100644 --- a/modules/macro-utils/src/test/clojure/clojure/contrib/test_macro_utils.clj +++ b/modules/macro-utils/src/test/clojure/clojure/contrib/test_macro_utils.clj @@ -64,3 +64,8 @@ '(do (+ 1 (clojure.core/+ 2 3))))) (ns-unmap *ns* 'sum-2-3)) +(deftest mexpand-all-test + (is (= (mexpand-all '(let [object (fn [] 3)] (object))) + '(let* [object (fn* ([] 3))] (object)))) + (is (= (mexpand-all '(let [or (fn [] 3)] (or))) + '(let* [or (fn* ([] 3))] (or))))) |