Skip to content

Commit

Permalink
Support try without catch (#258)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenchy64 authored Feb 11, 2025
1 parent 56f1417 commit 7dddb3e
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 36 deletions.
7 changes: 5 additions & 2 deletions compiler+runtime/include/cpp/jank/analyze/expr/try.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ namespace jank::analyze::expr
struct try_ : expression_base
{
do_<E> body{};
catch_<E> catch_body{};
option<catch_<E>> catch_body{};
option<do_<E>> finally_body{};

void propagate_position(expression_position const pos)
{
position = pos;
body.propagate_position(pos);
catch_body.propagate_position(pos);
if(catch_body)
{
catch_body.unwrap().propagate_position(pos);
}
if(finally_body)
{
finally_body.unwrap().propagate_position(pos);
Expand Down
10 changes: 4 additions & 6 deletions compiler+runtime/src/cpp/jank/analyze/processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1116,14 +1116,12 @@ namespace jank::analyze
}
}

if(!has_catch)
{
return err(error{ "each try must have a catch clause" });
}

ret.body.frame = try_frame;
ret.body.propagate_position(position);
ret.catch_body.body.frame = catch_frame;
if(ret.catch_body.is_some())
{
ret.catch_body.unwrap().body.frame = catch_frame;
}
if(ret.finally_body.is_some())
{
ret.finally_body.unwrap().frame = finally_frame;
Expand Down
4 changes: 2 additions & 2 deletions compiler+runtime/src/cpp/jank/analyze/step/force_boxed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ namespace jank::analyze::step
{
boost::apply_visitor(f, typed_expr.body.values.back()->data);
}
if(!typed_expr.catch_body.body.values.empty())
if(typed_expr.catch_body && !typed_expr.catch_body.unwrap().body.values.empty())
{
boost::apply_visitor(f, typed_expr.catch_body.body.values.back()->data);
boost::apply_visitor(f, typed_expr.catch_body.unwrap().body.values.back()->data);
}
}
else
Expand Down
8 changes: 6 additions & 2 deletions compiler+runtime/src/cpp/jank/c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,14 +850,18 @@ extern "C"
}
} };

auto const try_fn_obj(reinterpret_cast<object *>(try_fn));
auto const catch_fn_obj(reinterpret_cast<object *>(catch_fn));
if(catch_fn_obj == obj::nil::nil_const())
{
return dynamic_call(try_fn_obj);
}
try
{
auto const try_fn_obj(reinterpret_cast<object *>(try_fn));
return dynamic_call(try_fn_obj);
}
catch(object_ptr const e)
{
auto const catch_fn_obj(reinterpret_cast<object *>(catch_fn));
return dynamic_call(catch_fn_obj, e);
}
}
Expand Down
20 changes: 12 additions & 8 deletions compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,15 +923,18 @@ namespace jank::codegen
{
auto const wrapped_body(
evaluate::wrap_expression(make_box<expression>(expr.body), "try_body", {}));
auto const wrapped_catch(evaluate::wrap_expression(make_box<expression>(expr.catch_body.body),
"catch",
{ expr.catch_body.sym }));
auto const wrapped_catch(expr.catch_body.map([](auto const &catch_body) {
return evaluate::wrap_expression(make_box<expression>(catch_body.body),
"catch",
{ catch_body.sym });
}));
auto const wrapped_finally(expr.finally_body.map([](auto const &finally) {
return evaluate::wrap_expression(make_box<expression>(finally), "finally", {});
}));

auto const body(gen(wrapped_body, arity));
auto const catch_(gen(wrapped_catch, arity));
auto const catch_(
wrapped_catch.map([&](auto const &catch_body) { return gen(catch_body, arity); }));
auto const finally(
wrapped_finally.map([&](auto const &finally) { return gen(finally, arity); }));

Expand All @@ -941,10 +944,11 @@ namespace jank::codegen
false));
auto const fn(ctx->module->getOrInsertFunction("jank_try", fn_type));

llvm::SmallVector<llvm::Value *, 3> const args{ body,
catch_,
finally.unwrap_or(
gen_global(obj::nil::nil_const())) };
llvm::SmallVector<llvm::Value *, 3> const args{
body,
catch_.unwrap_or(gen_global(obj::nil::nil_const())),
finally.unwrap_or(gen_global(obj::nil::nil_const()))
};
auto const call(ctx->builder->CreateCall(fn, args));

if(expr.position == expression_position::tail)
Expand Down
13 changes: 10 additions & 3 deletions compiler+runtime/src/cpp/jank/evaluate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ namespace jank::evaluate
else if constexpr(std::same_as<T, expr::try_<expression>>)
{
walk(expr.body, f);
walk(expr.catch_body.body, f);
if(expr.catch_body.is_some())
{
walk(expr.catch_body.unwrap().body, f);
}
if(expr.finally_body.is_some())
{
walk(expr.finally_body.unwrap(), f);
Expand Down Expand Up @@ -627,15 +630,19 @@ namespace jank::evaluate
}
} };

if(!expr.catch_body)
{
return eval(expr.body);
}
try
{
return eval(expr.body);
}
catch(object_ptr const e)
{
return dynamic_call(eval(wrap_expression(make_box<expression>(expr.catch_body.body),
return dynamic_call(eval(wrap_expression(make_box<expression>(expr.catch_body.unwrap().body),
"catch",
{ expr.catch_body.sym })),
{ expr.catch_body.unwrap().sym })),
e);
}
}
Expand Down
19 changes: 7 additions & 12 deletions compiler+runtime/src/jank/clojure/core.jank
Original file line number Diff line number Diff line change
Expand Up @@ -1884,9 +1884,9 @@
(push-thread-bindings bindings)
(try
...
(finally
(pop-thread-bindings)))"
...
(finally
(pop-thread-bindings)))"
clojure.core-native/push-thread-bindings)

(def pop-thread-bindings
Expand Down Expand Up @@ -1921,9 +1921,7 @@
`(do
(push-thread-bindings (hash-map ~@(->var-pairs bindings)))
(try
~@body
(catch e#
(throw e#))
(do ~@body)
(finally
(pop-thread-bindings))))))

Expand Down Expand Up @@ -3656,8 +3654,6 @@
(try
(root-bind binding-map)
(fun)
(catch e
(throw e))
(finally
(root-bind old-vals)))))

Expand Down Expand Up @@ -4393,7 +4389,7 @@
(let [locklocal# lockee#]
(monitor-enter locklocal#)
(try
~@body
(do ~@body)
(finally
(monitor-exit locklocal#)))))))

Expand Down Expand Up @@ -4431,7 +4427,6 @@
binding-map))
(try
(apply f args)
(catch e (throw e))
(finally
(pop-thread-bindings))))

Expand Down Expand Up @@ -5550,7 +5545,7 @@
;; (repeat '(.. clojure.lang.Var create setDynamic)))]
;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec)))
;; (try
;; ~@body
;; (do ~@body)
;; (finally (. clojure.lang.Var (popThreadBindings)))))
(throw "TODO: port with-local-vars"))

Expand Down Expand Up @@ -6329,7 +6324,7 @@
;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER
;; (.getClassLoader (.getClass ^Object loading#))}))
;; (try
;; ~@body
;; (do ~@body)
;; (finally
;; (. clojure.lang.Var (popThreadBindings))))))
(throw "TODO: port with-loading-context"))
Expand Down
1 change: 0 additions & 1 deletion compiler+runtime/test/jank/form/try/fail-no-catch.jank

This file was deleted.

21 changes: 21 additions & 0 deletions compiler+runtime/test/jank/form/try/pass-finally-no-catch.jank
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(let [a (atom [])]
(assert (= [:try]
(try
(swap! a conj :try)
(finally
(swap! a conj :finally)))))
(assert (= [:try :finally] @a) (pr-str @a)))

(let [a (atom [])]
(try (try
(swap! a conj :inner-try)
(throw "skip finally")
(swap! a conj :inner-try-after-throw)
(finally
(swap! a conj :inner-finally)))
(catch e
(swap! a conj [:outer-catch e])))
(assert (= [:inner-try :inner-finally [:outer-catch "skip finally"]] @a)
(pr-str @a)))

:success
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(try :success)

0 comments on commit 7dddb3e

Please sign in to comment.