Permalink
Browse files

Allow loop/recur nested in catch and finally

Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
  • Loading branch information...
1 parent 7c9ff0a commit ddc65a96fdb1163b3c8cb112d565f06c4137b575 @jarpiain jarpiain committed with stuarthalloway Oct 31, 2010
Showing with 29 additions and 5 deletions.
  1. +3 −5 src/jvm/clojure/lang/Compiler.java
  2. +26 −0 test/clojure/test_clojure/compilation.clj
@@ -2133,7 +2133,7 @@ public Expr parse(C context, Object frm) {
if(bodyExpr == null)
try {
Var.pushThreadBindings(RT.map(NO_RECUR, true));
- bodyExpr = (new BodyExpr.Parser()).parse(context, RT.seq(body));
+ bodyExpr = (new BodyExpr.Parser()).parse(C.EXPRESSION, RT.seq(body));
} finally {
Var.popThreadBindings();
}
@@ -2159,7 +2159,7 @@ public Expr parse(C context, Object frm) {
(Symbol) (RT.second(f) instanceof Symbol ? RT.second(f)
: null),
null,false);
- Expr handler = (new BodyExpr.Parser()).parse(context, RT.next(RT.next(RT.next(f))));
+ Expr handler = (new BodyExpr.Parser()).parse(C.EXPRESSION, RT.next(RT.next(RT.next(f))));
catches = catches.cons(new CatchClause(c, lb, handler));
}
finally
@@ -2188,7 +2188,7 @@ public Expr parse(C context, Object frm) {
try
{
Var.pushThreadBindings(RT.map(NO_RECUR, true));
- bodyExpr = (new BodyExpr.Parser()).parse(context, RT.seq(body));
+ bodyExpr = (new BodyExpr.Parser()).parse(C.EXPRESSION, RT.seq(body));
}
finally
{
@@ -6144,8 +6144,6 @@ public Expr parse(C context, Object frm) {
IPersistentVector loopLocals = (IPersistentVector) LOOP_LOCALS.deref();
if(context != C.RETURN || loopLocals == null)
throw new UnsupportedOperationException("Can only recur from tail position");
- if(IN_CATCH_FINALLY.deref() != null)
- throw new UnsupportedOperationException("Cannot recur from catch/finally");
if(NO_RECUR.deref() != null)
throw new UnsupportedOperationException("Cannot recur across try");
PersistentVector args = PersistentVector.EMPTY;
@@ -61,6 +61,18 @@
(is (thrown? Compiler$CompilerException
(eval '(loop [x 5]
(try (recur 1)))))))
+ (testing "don't recur to loop from inside of catch inside of try"
+ (is (thrown? Compiler$CompilerException
+ (eval '(loop [x 5]
+ (try
+ (catch Exception e
+ (recur 1))))))))
+ (testing "don't recur to loop from inside of finally inside of try"
+ (is (thrown? Compiler$CompilerException
+ (eval '(loop [x 5]
+ (try
+ (finally
+ (recur 1))))))))
(testing "don't get confused about what the recur is targeting"
(is (thrown? Compiler$CompilerException
(eval '(loop [x 5]
@@ -71,6 +83,20 @@
(testing "allow loop/recur inside try"
(is (= 0 (eval '(try (loop [x 3]
(if (zero? x) x (recur (dec x)))))))))
+ (testing "allow loop/recur fully inside catch"
+ (is (= 3 (eval '(try
+ (throw (Exception.))
+ (catch Exception e
+ (loop [x 0]
+ (if (< x 3) (recur (inc x)) x))))))))
+ (testing "allow loop/recur fully inside finally"
+ (is (= "012" (eval '(with-out-str
+ (try
+ :return-val-discarded-because-of-with-out-str
+ (finally (loop [x 0]
+ (when (< x 3)
+ (print x)
+ (recur (inc x)))))))))))
(testing "allow fn/recur inside try"
(is (= 0 (eval '(try
((fn [x]

0 comments on commit ddc65a9

Please sign in to comment.