diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index b38d6a77..7a081af7 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -26,6 +26,7 @@ "queens.ml": 2, "quicksort.ml": 44, "roman.ml": 44, + "safe_div.ml": 20, "sieve.ml": 15, "sum_squares.ml": 385, "unique_set.ml": 9, diff --git a/lib/ocaml/baseline/safe_div.ml b/lib/ocaml/baseline/safe_div.ml new file mode 100644 index 00000000..93e16e29 --- /dev/null +++ b/lib/ocaml/baseline/safe_div.ml @@ -0,0 +1,14 @@ +let safe_div a b = + if b = 0 then Error "division by zero" + else Ok (a / b) + +let sum_safe pairs = + List.fold_left (fun acc (a, b) -> + match safe_div a b with + | Ok q -> acc + q + | Error _ -> acc + ) 0 pairs + +;; + +sum_safe [(10, 2); (20, 4); (30, 0); (50, 5)] diff --git a/lib/ocaml/runtime.sx b/lib/ocaml/runtime.sx index b9ac30d9..132d7586 100644 --- a/lib/ocaml/runtime.sx +++ b/lib/ocaml/runtime.sx @@ -410,6 +410,25 @@ match r with | Ok x -> ok_f x | Error e -> err_f e + + let equal eq_ok eq_err a b = + match a with + | Ok x -> + (match b with Ok y -> eq_ok x y | Error _ -> false) + | Error e -> + (match b with Ok _ -> false | Error e2 -> eq_err e e2) + + let compare cmp_ok cmp_err a b = + match a with + | Ok x -> + (match b with Ok y -> cmp_ok x y | Error _ -> -1) + | Error e -> + (match b with Ok _ -> 1 | Error e2 -> cmp_err e e2) + + let iter_error f r = + match r with + | Ok _ -> () + | Error e -> f e end ;; module String = struct diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index 76587eac..1a2b5041 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -1472,6 +1472,14 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 5224) (eval "(ocaml-run \"List.compare compare [] []\")") +;; ── Result.equal / Result.compare ──────────────────────────── +(epoch 5230) +(eval "(ocaml-run \"Result.equal (=) (=) (Ok 1) (Ok 1)\")") +(epoch 5231) +(eval "(ocaml-run \"Result.compare compare compare (Ok 5) (Ok 3)\")") +(epoch 5232) +(eval "(ocaml-run \"Result.compare compare compare (Ok 1) (Error \\\"fail\\\")\")") + EPOCHS OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) @@ -2341,6 +2349,11 @@ check 5222 "List.compare [1;2;3] [1;2;4]" '-1' check 5223 "List.compare [1;2] [1;2;3]" '-1' check 5224 "List.compare [] []" '0' +# ── Result.equal / Result.compare ─────────────────────────────── +check 5230 "Result.equal Ok 1 Ok 1" 'true' +check 5231 "Result.compare Ok 5 Ok 3" '1' +check 5232 "Result.compare Ok < Error" '-1' + TOTAL=$((PASS + FAIL)) if [ $FAIL -eq 0 ]; then echo "ok $PASS/$TOTAL OCaml-on-SX tests passed" diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 0bd9a913..3b0ad6db 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,13 @@ _Newest first._ binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree * 'a tree`) with insert + in-order traversal. Tests parametric ADT, recursive match, List.append, List.fold_left. +- 2026-05-09 Phase 5.1 — safe_div.ml baseline + Result.equal / + compare / iter_error (+3 tests, 592 total). safe_div divides only + if divisor non-zero, returns `Error "..."` otherwise. sum_safe folds + pairs with `Ok q -> acc+q | Error _ -> acc`. + `[(10,2);(20,4);(30,0);(50,5)]` → 5+5+0+10 = 20. Result additions: + equal/compare take separate eq/cmp for Ok and Error sides; Ok < Error + (-1) and Error > Ok (1). 30 baseline programs total. - 2026-05-09 Phase 6 — List.equal / List.compare (+5 tests, 589 total). Both take an inner predicate / comparator and walk both lists in lockstep. equal short-circuits on first mismatch.