Skip to content

Commit 6b89ed4

Browse files
committed
fix(interp): eval_decl handles FnExtern (#328 build-failure root cause)
The `TopFn fd` arm of `eval_decl` matched `fd.fd_body` against only `FnBlock` and `FnExpr`, leaving `FnExtern` unmatched. Every prior interp test imported externs via `use effects::{…}` so the case never fired; the bug was latent. The STDLIB-04a (#328) hermetic tests are the first to include an inline `extern fn make_ref<T>(x: T) -> Ref<T> / Mut;` declaration in the source they hand to `Interp.eval_program`. That triggers the missing arm and raises "Pattern matching failed" at `lib/interp.ml:1010`, which is the "2 failures!" reported by `dune runtest` on every PR since #334. Fix: wrap the body lowering in an outer `match fd.fd_body with`. The `FnExtern` arm returns `Ok env` (externs are runtime-bound via `create_initial_env`'s `VBuiltin` table — `panic`/`error`/`make_ref`/ `get`/`set`/etc. — not via the AST). The inner `FnBlock|FnExpr` arm keeps the existing closure construction; an `FnExtern` fall-through is unreachable per the outer guard and asserted to make that explicit to the reader. This unbreaks main: the 2 failing tests (`#328 make_ref/set/get round-trip (Int)` and `(String)`) now have a defined evaluation path. The codegen-only test of the same trio already passed (it bypasses interp). Refs #328.
1 parent d4522e4 commit 6b89ed4

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

lib/interp.ml

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,14 +1027,25 @@ let create_initial_env () : env =
10271027
let eval_decl (env : env) (decl : top_level) : env result =
10281028
match decl with
10291029
| TopFn fd ->
1030-
let closure = VClosure {
1031-
cl_params = fd.fd_params;
1032-
cl_body = (match fd.fd_body with
1033-
| FnBlock blk -> ExprBlock blk
1034-
| FnExpr e -> e);
1035-
cl_env = env;
1036-
} in
1037-
Ok (extend_env fd.fd_name.name closure env)
1030+
(match fd.fd_body with
1031+
| FnExtern ->
1032+
(* Externs have no AST body to evaluate. Their runtime binding is
1033+
provided by [create_initial_env]'s builtin table (panic, error,
1034+
make_ref, …). Skip here so an inline `extern fn` declaration in
1035+
a test source (e.g. the STDLIB-04a Mut round-trip tests) doesn't
1036+
blow up the [FnBlock|FnExpr] match below.
1037+
Refs #328 root-cause for the interp pattern-match-failure. *)
1038+
Ok env
1039+
| FnBlock _ | FnExpr _ ->
1040+
let closure = VClosure {
1041+
cl_params = fd.fd_params;
1042+
cl_body = (match fd.fd_body with
1043+
| FnBlock blk -> ExprBlock blk
1044+
| FnExpr e -> e
1045+
| FnExtern -> assert false (* unreachable: outer match guards *));
1046+
cl_env = env;
1047+
} in
1048+
Ok (extend_env fd.fd_name.name closure env))
10381049

10391050
| TopConst tc ->
10401051
let* v = eval env tc.tc_value in

0 commit comments

Comments
 (0)