ocaml: phase 4 'assert EXPR' (+3 tests, 487 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s

Tokenizer already classified 'assert' as a keyword; this commit wires
it through:
  parser  : parse-prefix dispatches like 'not' — advance, recur, wrap
            as (:assert EXPR).
  eval    : evaluate operand; nil on truthy, host-error 'Assert_failure'
            on false. Caught cleanly by existing try/with.

  assert true; 42                          = 42
  let x = 5 in assert (x = 5); x + 1       = 6
  try (assert false; 0) with _ -> 99       = 99
This commit is contained in:
2026-05-09 00:32:35 +00:00
parent bd2cd8aad1
commit 14b52cfaa7
4 changed files with 26 additions and 0 deletions

View File

@@ -430,6 +430,11 @@
(else (error (str "ocaml-eval: unbound variable " name))))))
((= tag "neg") (- 0 (ocaml-eval (nth ast 1) env)))
((= tag "not") (not (ocaml-eval (nth ast 1) env)))
((= tag "assert")
(let ((v (ocaml-eval (nth ast 1) env)))
(cond
((= v false) (error "Assert_failure"))
(else nil))))
((= tag "deref")
(let ((cell (ocaml-eval (nth ast 1) env)))
(nth cell 0)))

View File

@@ -622,6 +622,8 @@
(begin (advance-tok!) (list :deref (parse-prefix))))
((at-kw? "not")
(begin (advance-tok!) (list :not (parse-prefix))))
((at-kw? "assert")
(begin (advance-tok!) (list :assert (parse-prefix))))
(else (parse-app)))))
(set!
parse-binop-rhs

View File

@@ -1202,6 +1202,14 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 4922)
(eval "(ocaml-run \"let s = \\\"hi\\\" in let n = ref 0 in for i = 0 to String.length s - 1 do n := !n + Char.code s.[i] done; !n\")")
;; ── assert ────────────────────────────────────────────────────
(epoch 4930)
(eval "(ocaml-run \"assert true; 42\")")
(epoch 4931)
(eval "(ocaml-run \"let x = 5 in assert (x = 5); x + 1\")")
(epoch 4932)
(eval "(ocaml-run \"try (assert false; 0) with _ -> 99\")")
EPOCHS
OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1906,6 +1914,11 @@ check 4920 "s.[0] hello" '"h"'
check 4921 "Char.code s.[2] abc" '99'
check 4922 "for i s.[i] sum hi" '209'
# ── assert ───────────────────────────────────────────────────────
check 4930 "assert true; 42" '42'
check 4931 "assert (x = 5); x + 1" '6'
check 4932 "try (assert false; ...) with" '99'
TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"

View File

@@ -407,6 +407,12 @@ _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 4 — `assert EXPR` (+3 tests, 487 total). Tokenizer
already classified `assert` as a keyword; parse-prefix now handles
it like `not` (advance, recur, wrap). Eval evaluates the operand and
returns nil on truthy, raises `Assert_failure` on false (host-side
error so existing try/with handles it). `try (assert false; 0) with
_ -> 99` → 99.
- 2026-05-09 Phase 5.1 — levenshtein.ml baseline (recursive edit
distance, no memo). Sums distances for five short pairs:
("abc","abx")=1 + ("ab","ba")=2 + ("abc","axyc")=2 +