ocaml: phase 2 try/with + raise (+6 tests, 204 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s

Parser: try EXPR with | pat -> handler | ... -> (:try EXPR CLAUSES).
Eval delegates to SX guard with else matching the raised value against
clause patterns; re-raises on no-match. raise/failwith/invalid_arg
shipped as builtins. failwith "msg" raises ("Failure" msg) so
| Failure msg -> ... patterns match.
This commit is contained in:
2026-05-08 08:20:11 +00:00
parent 937342bbf0
commit 6a1f63f0d1
4 changed files with 82 additions and 2 deletions

View File

@@ -41,7 +41,13 @@
(list "ignore" (fn (x) nil))
;; References. A ref cell is a one-element list; ! reads it and
;; := mutates it via set-nth!.
(list "ref" (fn (x) (list x))))))
(list "ref" (fn (x) (list x)))
;; Exceptions: `raise e` invokes the host-SX raise; values are
;; tagged like other ctors so `try ... with | Exn x -> handler`
;; can pattern-match them.
(list "raise" (fn (e) (raise e)))
(list "failwith" (fn (msg) (raise (list "Failure" msg))))
(list "invalid_arg" (fn (msg) (raise (list "Invalid_argument" msg)))))))
(define ocaml-env-lookup
(fn (env name)
@@ -342,6 +348,28 @@
(loop)))))
(loop)))))
nil)))
((= tag "try")
;; (:try EXPR CLAUSES) — evaluate EXPR; if it raises, match the
;; raised value against CLAUSES. Re-raise on no-match.
(let ((expr (nth ast 1)) (clauses (nth ast 2)) (env-cap env))
(guard (e
(else
(begin
(define try-clauses
(fn (cs)
(cond
((empty? cs) (raise e))
(else
(let ((clause (first cs)))
(let ((pat (nth clause 1))
(body (nth clause 2)))
(let ((env2 (ocaml-match-pat pat e env-cap)))
(cond
((= env2 ocaml-match-fail)
(try-clauses (rest cs)))
(else (ocaml-eval body env2))))))))))
(try-clauses clauses))))
(ocaml-eval expr env-cap))))
((= tag "while")
(let ((cond-ast (nth ast 1)) (body (nth ast 2)))
(begin