Skip to content

Commit 0cf28f8

Browse files
committed
Allow only non-qualified symbols in macrolet and symbol-macrolet
1 parent 891aba1 commit 0cf28f8

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/main/clojure/clojure/tools/macro.clj

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
Local macros are most useful in the definition of the expansion
2323
of another macro, they may be used anywhere. Global symbol
2424
macros can be used only inside a with-symbol-macros form."}
25-
clojure.tools.macro)
25+
clojure.tools.macro
26+
[:require clojure.string])
2627

2728
; A set of all special forms. Special forms are not macro-expanded, making
2829
; it impossible to shadow them by macro definitions. For most special
@@ -197,11 +198,21 @@
197198
(map? exp) (into {} (map expand-all (seq exp)))
198199
:else exp)))
199200

201+
(defn- check-not-qualified
202+
"Verify that none of the supplied symbols are namespace-qualified"
203+
[symbols]
204+
(when (not-every? nil? (map namespace symbols))
205+
(throw (Exception.
206+
(str "Can't macrolet qualified symbol(s): "
207+
(clojure.string/join ", "
208+
(map str (filter namespace symbols)))))))
209+
symbols)
210+
200211
(defmacro macrolet
201212
"Define local macros that are used in the expansion of exprs. The
202213
syntax is the same as for letfn forms."
203214
[fn-bindings & exprs]
204-
(let [names (map first fn-bindings)
215+
(let [names (check-not-qualified (map first fn-bindings))
205216
name-map (into {} (map (fn [n] [(list 'quote n) n]) names))
206217
macro-map (eval `(letfn ~fn-bindings ~name-map))]
207218
(binding [macro-fns (merge macro-fns macro-map)
@@ -213,7 +224,7 @@
213224
The syntax is the same as for let forms."
214225
[symbol-bindings & exprs]
215226
(let [symbol-map (into {} (map vec (partition 2 symbol-bindings)))
216-
names (keys symbol-map)]
227+
names (check-not-qualified (keys symbol-map))]
217228
(binding [macro-fns (apply dissoc macro-fns names)
218229
macro-symbols (merge macro-symbols symbol-map)]
219230
`(do ~@(doall (map expand-all exprs))))))

src/test/clojure/clojure/tools/test_macro.clj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@
5454
'(macro/symbol-macrolet [x foo z bar]
5555
(fn f ([x y] [x y z]) ([x y z] [x y z]))))
5656
'(do (fn* f ([x y] [x y bar]) ([x y z] [x y z])))))
57+
(is (thrown? Exception
58+
(macroexpand-1
59+
'(macro/symbol-macrolet [user/bar 42]
60+
(+ (- bar 2) (* bar 3))))))
61+
(is (= (macroexpand-1
62+
'(macro/symbol-macrolet [bar 42]
63+
(+ (- bar 2) (* bar 3))))
64+
'(do (+ (- 42 2) (* 42 3)))))
5765
(comment
5866
(is (= (nth (second (macroexpand-1
5967
'(macro/symbol-macrolet [x xx y yy z zz]

0 commit comments

Comments
 (0)