ocaml: phase 5 HM type inference — closes lib-guest step 8 (+14 tests, 265 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s

OCaml-on-SX is the deferred second consumer for lib/guest/hm.sx step 8.
lib/ocaml/infer.sx assembles Algorithm W on top of the shipped algebra:

- Var: lookup + hm-instantiate.
- Fun: fresh-tv per param, auto-curried via recursion.
- App: unify against hm-arrow, fresh-tv for result.
- Let: generalize rhs over (ftv(t) - ftv(env)) — let-polymorphism.
- If: unify cond with Bool, both branches with each other.
- Op (+, =, <, etc.): builtin signatures (int*int->int monomorphic,
  =/<> polymorphic 'a->'a->bool).

Tests pass for: literals, fun x -> x : 'a -> 'a, let id ... id 5/id true,
fun f x -> f (f x) : ('a -> 'a) -> 'a -> 'a (twice).

Pending: tuples, lists, pattern matching, let-rec, modules in HM.
This commit is contained in:
2026-05-08 09:02:25 +00:00
parent 4c6790046c
commit 26863242a0
3 changed files with 276 additions and 4 deletions

View File

@@ -30,10 +30,13 @@ cat > "$TMPFILE" << 'EPOCHS'
(load "lib/guest/lex.sx")
(load "lib/guest/prefix.sx")
(load "lib/guest/pratt.sx")
(load "lib/guest/match.sx")
(load "lib/guest/hm.sx")
(load "lib/ocaml/tokenizer.sx")
(load "lib/ocaml/parser.sx")
(load "lib/ocaml/eval.sx")
(load "lib/ocaml/runtime.sx")
(load "lib/ocaml/infer.sx")
(load "lib/ocaml/tests/tokenize.sx")
(eval "(ocaml-load-stdlib!)")
@@ -639,6 +642,36 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 852)
(eval "(ocaml-run-program \"let x = 1 and y = 2;; x + y\")")
;; ── Phase 5: Hindley-Milner type inference ────────────────────
(epoch 900)
(eval "(ocaml-type-of \"42\")")
(epoch 901)
(eval "(ocaml-type-of \"true\")")
(epoch 902)
(eval "(ocaml-type-of \"\\\"hi\\\"\")")
(epoch 903)
(eval "(ocaml-type-of \"1 + 2\")")
(epoch 904)
(eval "(ocaml-type-of \"fun x -> x + 1\")")
(epoch 905)
(eval "(ocaml-type-of \"fun x -> x\")")
(epoch 906)
(eval "(ocaml-type-of \"fun x y -> x + y\")")
(epoch 907)
(eval "(ocaml-type-of \"let f x = x + 1 in f 10\")")
(epoch 908)
(eval "(ocaml-type-of \"let id = fun x -> x in id 5\")")
(epoch 909)
(eval "(ocaml-type-of \"let id = fun x -> x in id true\")")
(epoch 910)
(eval "(ocaml-type-of \"if true then 1 else 2\")")
(epoch 911)
(eval "(ocaml-type-of \"fun f -> fun x -> f (f x)\")")
(epoch 912)
(eval "(ocaml-type-of \"fun b -> if b then 1 else 0\")")
(epoch 913)
(eval "(ocaml-type-of \"not true\")")
EPOCHS
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1016,6 +1049,22 @@ check 850 "even 10 (mutual rec)" 'true'
check 851 "odd 7 (mutual rec)" 'true'
check 852 "let x = 1 and y = 2" '3'
# ── Phase 5: Hindley-Milner type inference ────────────────────
check 900 "type 42 = Int" '"Int"'
check 901 "type true = Bool" '"Bool"'
check 902 'type string lit' '"String"'
check 903 "type 1+2 = Int" '"Int"'
check 904 "type fun x->x+1 = Int->Int" '"Int -> Int"'
check 905 "type fun x->x = poly" ' -> '
check 906 "type fun x y->x+y" '"Int -> Int -> Int"'
check 907 "type let f x=x+1 in f 10" '"Int"'
check 908 "type let id; id 5" '"Int"'
check 909 "type let id; id true" '"Bool"'
check 910 "type if/then/else" '"Int"'
check 911 "type twice" ' -> '
check 912 "type bool branch" '"Bool -> Int"'
check 913 "type not true" '"Bool"'
TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"