From 3fef7ccdd28db8b2cf7da71277582fa79c09fbe5 Mon Sep 17 00:00:00 2001 From: butterunderflow Date: Fri, 23 Aug 2024 23:03:05 +0800 Subject: [PATCH] translate assert expression & wrap main body with a try-catch --- lib/back/closure_translator.ml | 24 +++++++- lib/clos/closure.ml | 1 + lib/clos/lift.ml | 4 +- runtime/include/fun_rt_core.hpp | 2 + runtime/src/fun_rt_core.cpp | 9 +++ tests/cram/test_dirs/assert.t/run.t | 58 +++++++++++++++++++ tests/cram/test_dirs/assert.t/test_assert.fun | 7 +++ tests/cram/test_dirs/equality.t/run.t | 14 ++++- tests/cram/test_dirs/external.t/run.t | 28 +++++++-- tests/cram/test_dirs/hello.t/run.t | 14 ++++- tests/cram/test_dirs/interval_functor.t/run.t | 14 ++++- tests/cram/test_dirs/literal.t/run.t | 14 ++++- tests/cram/test_dirs/match.t/run.t | 14 ++++- tests/cram/test_dirs/simple.t/run.t | 14 ++++- tests/cram/test_dirs/simple_functor.t/run.t | 14 ++++- tests/cram/test_dirs/wildcard.t/run.t | 14 ++++- tests/regular/lift_test.ml | 11 ++++ tests/regular/lower_test.ml | 8 ++- tests/regular/typing_test.ml | 8 +++ 19 files changed, 237 insertions(+), 35 deletions(-) create mode 100644 tests/cram/test_dirs/assert.t/run.t create mode 100644 tests/cram/test_dirs/assert.t/test_assert.fun diff --git a/lib/back/closure_translator.ml b/lib/back/closure_translator.ml index f157dba..01b21e9 100644 --- a/lib/back/closure_translator.ml +++ b/lib/back/closure_translator.ml @@ -52,6 +52,8 @@ let ff_is_equal_aux = C.VARIABLE "ff_is_equal_aux" let ff_is_zero = C.VARIABLE "ff_is_zero" +let ff_assert = C.VARIABLE "ff_assert" + let ff_is_not_equal = C.VARIABLE "ff_is_not_equal" let ff_get_mem = C.VARIABLE "ff_get_member" @@ -73,8 +75,9 @@ let ff_match_constr = C.VARIABLE "ff_match_constr" let ff_match_tuple = C.VARIABLE "ff_match_tuple" let header = {| -#include"fun_rt.hpp" -#include +#include "fun_rt.hpp" +#include +#include |} @@ -332,6 +335,14 @@ and trans_expr ctx e = let _e0_v, e0_stmts = trans_expr ctx e0 in let e1_v, e1_stmts = trans_expr ctx e1 in (e1_v, e0_stmts @ e1_stmts) + | EAssert e0 -> + let e0_v, e0_stmts = trans_expr ctx e0 in + let is_true_v = create_decl "is_true" ctx in + let assert_stmt = + make_assign (VARIABLE is_true_v) + (CALL (ff_assert, [ VARIABLE e0_v ])) + in + (is_true_v, e0_stmts @ [ assert_stmt ]) | EStruct _ -> ("todo", []) and trans_const (c : S.constant) = @@ -518,7 +529,14 @@ let translate (main, (fns : func list)) = Printf.sprintf {| int main() { - %s(nullptr); + try + { + %s(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %%s", error.what()); + } } |} main_name in diff --git a/lib/clos/closure.ml b/lib/clos/closure.ml index 5f6d8c1..07bdc84 100644 --- a/lib/clos/closure.ml +++ b/lib/clos/closure.ml @@ -24,6 +24,7 @@ type expr = | EField of expr * string | ECmp of T.cmp_op * expr * expr | ESeq of expr * expr + | EAssert of expr and pattern = L.pattern diff --git a/lib/clos/lift.ml b/lib/clos/lift.ml index 38e9e85..ba67c9f 100644 --- a/lib/clos/lift.ml +++ b/lib/clos/lift.ml @@ -87,7 +87,9 @@ let rec lift ?(hint = "temp") (e : L.expr) (vars : string list) : | L.EField (e, name) -> let e', fns = lift e vars ~hint in (C.EField (e', name), fns) - | L.EAssert _ -> failwith "todo" + | L.EAssert e -> + let e', fns = lift e vars ~hint in + (C.EAssert e', fns) and lift_letrec binds vars = let xs = List.map fst binds in diff --git a/runtime/include/fun_rt_core.hpp b/runtime/include/fun_rt_core.hpp index 85d93c6..df7cb46 100644 --- a/runtime/include/fun_rt_core.hpp +++ b/runtime/include/fun_rt_core.hpp @@ -185,4 +185,6 @@ ff_obj_t ff_is_not_equal(ff_obj_t x, ff_obj_t y); bool ff_is_zero(ff_obj_t x); +ff_obj_t ff_assert(ff_obj_t x); + #endif diff --git a/runtime/src/fun_rt_core.cpp b/runtime/src/fun_rt_core.cpp index 85d96c0..14ea378 100644 --- a/runtime/src/fun_rt_core.cpp +++ b/runtime/src/fun_rt_core.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -200,3 +201,11 @@ bool ff_is_zero(ff_obj_t x) { auto val = ff_get_int(x); return val == 0; } + +ff_obj_t ff_assert(ff_obj_t x) { + auto val = ff_get_int(x); + if (val != 0) { + throw std::runtime_error("Assertion failed!"); + } + return ff_make_int(0); +} diff --git a/tests/cram/test_dirs/assert.t/run.t b/tests/cram/test_dirs/assert.t/run.t new file mode 100644 index 0000000..b210711 --- /dev/null +++ b/tests/cram/test_dirs/assert.t/run.t @@ -0,0 +1,58 @@ + + + $ ff test_assert.fun -o test_assert.cpp + + $ cat test_assert.cpp + + #include "fun_rt.hpp" + #include + #include + + ff_obj_t main_1__fn(ff_fvs_t fvs_1); + + ff_obj_t main_1__fn(ff_fvs_t fvs_1) + { + ff_obj_t mod_12; + ff_obj_t x_11; + ff_obj_t is_true_10; + ff_obj_t temp_9; + ff_obj_t x_8; + ff_obj_t temp_7; + ff_obj_t app_res_6; + ff_obj_t x_5; + ff_obj_t is_true_4; + ff_obj_t temp_3; + ff_obj_t println_str_2; + println_str_2 = ff_builtin_println_str; + temp_3 = ff_make_int(1); + is_true_4 = ff_assert(temp_3); + x_5 = is_true_4; + temp_7 = ff_make_str("A true asserted!"); + app_res_6 = ff_apply_generic(println_str_2, temp_7); + x_8 = app_res_6; + temp_9 = ff_make_int(0); + is_true_10 = ff_assert(temp_9); + x_11 = is_true_10; + mod_12 = ff_make_mod_obj(4, {"println_str", "x", "x", "x"}, + {println_str_2, x_5, x_8, x_11}); + return mod_12; + } + + + int main() + { + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } + } + + $ $FF test_assert.fun + + $ ./test_assert.fun.out + Runtime error: Assertion failed! + diff --git a/tests/cram/test_dirs/assert.t/test_assert.fun b/tests/cram/test_dirs/assert.t/test_assert.fun new file mode 100644 index 0000000..5d01e03 --- /dev/null +++ b/tests/cram/test_dirs/assert.t/test_assert.fun @@ -0,0 +1,7 @@ +external println_str : string -> unit = "ff_builtin_println_str" + +let x = assert true + +let x = println_str "A true asserted!" + +let x = assert false diff --git a/tests/cram/test_dirs/equality.t/run.t b/tests/cram/test_dirs/equality.t/run.t index 357997a..03210ef 100644 --- a/tests/cram/test_dirs/equality.t/run.t +++ b/tests/cram/test_dirs/equality.t/run.t @@ -2,8 +2,9 @@ $ cat test_equality.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); @@ -84,7 +85,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } $ ./test_equality.fun.out diff --git a/tests/cram/test_dirs/external.t/run.t b/tests/cram/test_dirs/external.t/run.t index 8247acc..34e87df 100644 --- a/tests/cram/test_dirs/external.t/run.t +++ b/tests/cram/test_dirs/external.t/run.t @@ -1,8 +1,9 @@ $ ff test_external.fun --stdout - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); @@ -18,7 +19,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } @@ -26,8 +34,9 @@ $ cat test_add_external.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); @@ -60,7 +69,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } $ ./test_add_external.fun.out diff --git a/tests/cram/test_dirs/hello.t/run.t b/tests/cram/test_dirs/hello.t/run.t index a1f9167..0a6c017 100644 --- a/tests/cram/test_dirs/hello.t/run.t +++ b/tests/cram/test_dirs/hello.t/run.t @@ -7,8 +7,9 @@ $ cat hello.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); @@ -33,5 +34,12 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } diff --git a/tests/cram/test_dirs/interval_functor.t/run.t b/tests/cram/test_dirs/interval_functor.t/run.t index 96f91a2..685661d 100644 --- a/tests/cram/test_dirs/interval_functor.t/run.t +++ b/tests/cram/test_dirs/interval_functor.t/run.t @@ -2,8 +2,9 @@ $ cat test_interval.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); ff_obj_t print_int_interval_14__fn(ff_fvs_t fvs_4, ff_obj_t interval_3); @@ -555,7 +556,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } $ $FF test_interval.fun diff --git a/tests/cram/test_dirs/literal.t/run.t b/tests/cram/test_dirs/literal.t/run.t index 1606633..0c37b9c 100644 --- a/tests/cram/test_dirs/literal.t/run.t +++ b/tests/cram/test_dirs/literal.t/run.t @@ -3,8 +3,9 @@ $ cat test_literal.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); @@ -34,6 +35,13 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } diff --git a/tests/cram/test_dirs/match.t/run.t b/tests/cram/test_dirs/match.t/run.t index 468b79e..4117759 100644 --- a/tests/cram/test_dirs/match.t/run.t +++ b/tests/cram/test_dirs/match.t/run.t @@ -4,8 +4,9 @@ $ cat test_match.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); ff_obj_t f_2__fn(ff_fvs_t fvs_3, ff_obj_t x_2); @@ -151,7 +152,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } $ ./test_match.fun.out diff --git a/tests/cram/test_dirs/simple.t/run.t b/tests/cram/test_dirs/simple.t/run.t index d16a290..ae0a2fd 100644 --- a/tests/cram/test_dirs/simple.t/run.t +++ b/tests/cram/test_dirs/simple.t/run.t @@ -12,8 +12,9 @@ $ ff simple.fun $ ff simple.fun --stdout - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); ff_obj_t m_4__fn(ff_fvs_t fvs_3, ff_obj_t x_2); @@ -76,7 +77,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } $ ff simple.fun -o simple1.out --debug diff --git a/tests/cram/test_dirs/simple_functor.t/run.t b/tests/cram/test_dirs/simple_functor.t/run.t index 38357be..0f5d315 100644 --- a/tests/cram/test_dirs/simple_functor.t/run.t +++ b/tests/cram/test_dirs/simple_functor.t/run.t @@ -11,8 +11,9 @@ $ cat test_increment_functor.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); ff_obj_t Increment_2__fn(ff_fvs_t fvs_3, ff_obj_t M_2); @@ -124,5 +125,12 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } diff --git a/tests/cram/test_dirs/wildcard.t/run.t b/tests/cram/test_dirs/wildcard.t/run.t index 0c53aff..ff4b206 100644 --- a/tests/cram/test_dirs/wildcard.t/run.t +++ b/tests/cram/test_dirs/wildcard.t/run.t @@ -3,8 +3,9 @@ $ cat test_wildcard.fun.cpp - #include"fun_rt.hpp" - #include + #include "fun_rt.hpp" + #include + #include ff_obj_t main_1__fn(ff_fvs_t fvs_1); @@ -33,7 +34,14 @@ int main() { - main_1__fn(nullptr); + try + { + main_1__fn(nullptr); + } + catch (const std::runtime_error& error) + { + printf("Runtime error: %s", error.what()); + } } $ ./test_wildcard.fun.out diff --git a/tests/regular/lift_test.ml b/tests/regular/lift_test.ml index a88e53f..b41b2eb 100644 --- a/tests/regular/lift_test.ml +++ b/tests/regular/lift_test.ml @@ -122,4 +122,15 @@ let z = fun z -> x = y (sum/2 (sum) (x) (EIf (ECmp Eq (EVar x) (EConst (CInt 0))) (EConst (CInt 1)) (EConst (CInt 2)))) + |}]; + print_lifted + {| +let x = assert true + |}; + [%expect {| + Main function name: + main/1 + Global C functions: + (main/1 () () (EModObject ((FSimple x (EAssert (EConst (CBool true))))))) |}] + diff --git a/tests/regular/lower_test.ml b/tests/regular/lower_test.ml index 6b351b2..623279d 100644 --- a/tests/regular/lower_test.ml +++ b/tests/regular/lower_test.ml @@ -288,4 +288,10 @@ let z = x = y ((even ((x) (EApp (EVar odd) ((EConst (CInt 1)))) (odd))) (odd ((x) (EApp (EVar even) ((EConst (CInt 1)))) (even)))) (EVar even))))) - |}] + |}]; + print_lowered + {| + let x = assert true + |}; + [%expect {| (EModObject ((FSimple x (EAssert (EConst (CBool true)))))) |}] + diff --git a/tests/regular/typing_test.ml b/tests/regular/typing_test.ml index b7214b5..bbc8d29 100644 --- a/tests/regular/typing_test.ml +++ b/tests/regular/typing_test.ml @@ -1244,6 +1244,14 @@ let x = Closure ("x", Nil) ((TCons (0 string) ()) (TCons (0 list) ((TVar (Link (TCons (0 int) ())))))))) (TVar (Link (TCons (0 t) ())))))) + |}]; + + print_typed {| +let x = assert true +|}; + [%expect {| + ((TopLet x + (EAssert (EConst (CBool true) (TCons (0 bool) ())) (TCons (0 unit) ())))) |}] let%expect_test "Error reporting test" =