aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonrad Hinsen <konrad.hinsen@fastmail.net>2010-09-03 21:32:12 +0200
committerKonrad Hinsen <konrad.hinsen@fastmail.net>2010-09-03 21:32:12 +0200
commit67fccc60f2a547f272df858c7367ef805d123ffc (patch)
tree76b1538ea7687f223d0140962528e2772dc3f2da
parent330807c6d93f9a3c2bad4c8f4dd6295b6cf2053e (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.clj29
-rw-r--r--modules/macro-utils/src/test/clojure/clojure/contrib/test_macro_utils.clj5
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)))))