From 916da1962bc452a97e0140f0815dd30a71899566 Mon Sep 17 00:00:00 2001 From: Gary Fredericks Date: Tue, 2 Jul 2013 21:48:39 -0500 Subject: [PATCH] CLJ-1184: Don't compile [do ...] or #{do ...} The compiler should only treat do as a special form when it is in the call position of an ISeq, not a vector or set. Signed-off-by: Stuart Halloway --- src/jvm/clojure/lang/Compiler.java | 4 ++-- test/clojure/test_clojure/compilation.clj | 24 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 026de05861..49d01e774b 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -6603,7 +6603,7 @@ public static Object eval(Object form, boolean freshLoader) { try { form = macroexpand(form); - if(form instanceof IPersistentCollection && Util.equals(RT.first(form), DO)) + if(form instanceof ISeq && Util.equals(RT.first(form), DO)) { ISeq s = RT.next(form); for(; RT.next(s) != null; s = RT.next(s)) @@ -7138,7 +7138,7 @@ static void compile1(GeneratorAdapter gen, ObjExpr objx, Object form) { try { form = macroexpand(form); - if(form instanceof IPersistentCollection && Util.equals(RT.first(form), DO)) + if(form instanceof ISeq && Util.equals(RT.first(form), DO)) { for(ISeq s = RT.next(form); s != null; s = RT.next(s)) { diff --git a/test/clojure/test_clojure/compilation.clj b/test/clojure/test_clojure/compilation.clj index 55b23cc071..99eedbbea8 100644 --- a/test/clojure/test_clojure/compilation.clj +++ b/test/clojure/test_clojure/compilation.clj @@ -199,3 +199,27 @@ (doseq [f (.listFiles (java.io.File. "test")) :when (re-find #"dummy.clj" (str f))] (.delete f))))) + +(deftest CLJ-1184-do-in-non-list-test + (testing "do in a vector throws an exception" + (is (thrown? Compiler$CompilerException + (eval '[do 1 2 3])))) + (testing "do in a set throws an exception" + (is (thrown? Compiler$CompilerException + (eval '#{do})))) + + ;; compile uses a separate code path so we have to call it directly + ;; to test it + (letfn [(compile [s] + (spit "test/clojure/bad_def_test.clj" (str "(ns clojure.bad-def-test)\n" s)) + (try + (binding [*compile-path* "test"] + (clojure.core/compile 'clojure.bad-def-test)) + (finally + (doseq [f (.listFiles (java.io.File. "test/clojure")) + :when (re-find #"bad_def_test" (str f))] + (.delete f)))))] + (testing "do in a vector throws an exception in compilation" + (is (thrown? Compiler$CompilerException (compile "[do 1 2 3]")))) + (testing "do in a set throws an exception in compilation" + (is (thrown? Compiler$CompilerException (compile "#{do}"))))))