erlang: try/catch/of/after, Phase 4 complete (+19 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-25 03:26:01 +00:00
parent 1a5a2e8982
commit 882205aa70
6 changed files with 257 additions and 7 deletions

View File

@@ -561,6 +561,79 @@
(nm (ev "P = spawn(fun () -> exit(boom) end), monitor(process, P), receive {'DOWN', _, _, _, _} -> alive end"))
"alive")
;; ── try / catch / of / after ─────────────────────────────────
(er-eval-test "try plain"
(ev "try 1 + 2 catch _ -> oops end") 3)
(er-eval-test "try throw caught"
(nm (ev "try throw(boom) catch throw:X -> X end")) "boom")
(er-eval-test "try error caught"
(nm (ev "try error(crash) catch error:X -> X end")) "crash")
(er-eval-test "try exit caught"
(nm (ev "try exit(quit) catch exit:X -> X end")) "quit")
(er-eval-test "default class is throw"
(nm (ev "try throw(bye) catch X -> X end")) "bye")
(er-eval-test "default class doesn't catch error"
(do
(ev "P = spawn(fun () -> try error(crash) catch X -> X end end), receive after 0 -> ok end")
(nm (er-proc-field (er-mk-pid 1) :exit-reason)))
"crash")
;; of clauses
(er-eval-test "try of single"
(ev "try 42 of N -> N * 2 catch _ -> 0 end") 84)
(er-eval-test "try of multi"
(nm (ev "try ok of ok -> matched; _ -> nope catch _ -> oops end"))
"matched")
(er-eval-test "try of fallthrough"
(nm (ev "try x of ok -> a; error -> b; _ -> default catch _ -> oops end"))
"default")
(er-eval-test "try of with guard"
(nm (ev "try 5 of N when N > 0 -> pos; _ -> nonneg catch _ -> oops end"))
"pos")
;; after clause
(er-eval-test "after on success"
(do (er-io-flush!)
(ev "try 7 after io:format(\"a\") end")
(er-io-buffer-content))
"a")
(er-eval-test "after on caught"
(do (er-io-flush!)
(ev "try throw(b) catch throw:_ -> caught after io:format(\"x\") end")
(er-io-buffer-content))
"x")
(er-eval-test "after returns body value"
(ev "try 99 after 0 end") 99)
(er-eval-test "try preserves catch result"
(nm (ev "try throw(x) catch throw:_ -> recovered after 0 end"))
"recovered")
;; nested try
(er-eval-test "try nested catch outer"
(nm (ev "try (try throw(inner) catch error:_ -> bad end) catch throw:X -> X end"))
"inner")
(er-eval-test "try nested catch inner"
(nm (ev "try (try throw(inner) catch throw:X -> X end) catch _ -> outer end"))
"inner")
;; class re-raise on no-match
(er-eval-test "throw without catch-throw escapes"
(do
(ev "P = spawn(fun () -> try throw(bye) catch error:_ -> nope end end), receive after 0 -> ok end")
(let ((reason (er-proc-field (er-mk-pid 1) :exit-reason)))
(and (er-tuple? reason) (nm (nth (get reason :elements) 0)))))
"nocatch")
;; multi-clause catch
(er-eval-test "multi-clause catch picks throw"
(nm (ev "try throw(a) catch error:X -> e; throw:X -> t; exit:X -> x end"))
"t")
(er-eval-test "multi-clause catch picks exit"
(nm (ev "try exit(a) catch error:X -> e; throw:X -> t; exit:X -> x end"))
"x")
(define
er-eval-test-summary
(str "eval " er-eval-test-pass "/" er-eval-test-count))