diff --git a/lib/ocaml/runtime.sx b/lib/ocaml/runtime.sx index 52a27d08..d1ceec8f 100644 --- a/lib/ocaml/runtime.sx +++ b/lib/ocaml/runtime.sx @@ -377,6 +377,16 @@ let chr n = _char_chr n let lowercase_ascii c = _string_lower c let uppercase_ascii c = _string_upper c + let is_digit c = + let n = _char_code c in n >= 48 && n <= 57 + let is_lower c = + let n = _char_code c in n >= 97 && n <= 122 + let is_upper c = + let n = _char_code c in n >= 65 && n <= 90 + let is_alpha c = is_lower c || is_upper c + let is_alnum c = is_alpha c || is_digit c + let is_whitespace c = + c = \" \" || c = \"\\t\" || c = \"\\n\" || c = \"\\r\" end ;; module Int = struct diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index 1bde32a3..b86b1c14 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -1124,6 +1124,22 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 4202) (eval "(ocaml-type-of-program \"let rec map f xs = match xs with | [] -> [] | h :: t -> f h :: map f t and length lst = match lst with | [] -> 0 | _ :: t -> 1 + length t;; map\")") +;; ── Char predicate helpers ──────────────────────────────────── +(epoch 4300) +(eval "(ocaml-run \"Char.is_digit \\\"5\\\"\")") +(epoch 4301) +(eval "(ocaml-run \"Char.is_digit \\\"x\\\"\")") +(epoch 4302) +(eval "(ocaml-run \"Char.is_alpha \\\"x\\\"\")") +(epoch 4303) +(eval "(ocaml-run \"Char.is_alnum \\\"5\\\"\")") +(epoch 4304) +(eval "(ocaml-run \"Char.is_whitespace \\\" \\\"\")") +(epoch 4305) +(eval "(ocaml-run \"Char.is_upper \\\"A\\\"\")") +(epoch 4306) +(eval "(ocaml-run \"Char.is_lower \\\"a\\\"\")") + EPOCHS OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) @@ -1780,6 +1796,15 @@ check 4200 "let-mut x+y" '"Int"' check 4201 "let-rec-mut even 10" '"Bool"' check 4202 "let-rec-mut map+length" 'list -> ' +# ── Char predicates ──────────────────────────────────────────── +check 4300 "Char.is_digit 5" 'true' +check 4301 "Char.is_digit x" 'false' +check 4302 "Char.is_alpha x" 'true' +check 4303 "Char.is_alnum 5" 'true' +check 4304 "Char.is_whitespace ' '" 'true' +check 4305 "Char.is_upper A" 'true' +check 4306 "Char.is_lower a" 'true' + 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 d7ccc61d..b404aad6 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,9 @@ _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-08 Phase 6 — Char predicates: is_digit/is_alpha/is_alnum/ + is_whitespace/is_upper/is_lower (+7 tests, 461 total). All written + in OCaml in runtime.sx using Char.code + ASCII range checks. - 2026-05-08 Phase 5 — HM for top-level `let..and..` decls (+3 tests, 454 total). `ocaml-type-of-program` now handles `:def-mut` (sequential generalization) and `:def-rec-mut` (mutual recursion