ocaml: phase 6 String/Char/Int/Float/Printf modules (+13 tests, 278 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s

Host primitives _string_length / _string_sub / _char_code / etc. exposed
in the base env (underscore-prefixed to avoid user clash). lib/ocaml/
runtime.sx wraps them into OCaml-syntax modules: String (length, get,
sub, concat, uppercase/lowercase_ascii, starts_with), Char (code, chr,
lowercase/uppercase_ascii), Int (to_string, of_string, abs, max, min),
Float.to_string, Printf stubs.

Also added print_string / print_endline / print_int IO builtins.
This commit is contained in:
2026-05-08 09:10:06 +00:00
parent 26863242a0
commit c8bfd22786
4 changed files with 119 additions and 1 deletions

View File

@@ -47,7 +47,26 @@
;; can pattern-match them.
(list "raise" (fn (e) (raise e)))
(list "failwith" (fn (msg) (raise (list "Failure" msg))))
(list "invalid_arg" (fn (msg) (raise (list "Invalid_argument" msg)))))))
(list "invalid_arg" (fn (msg) (raise (list "Invalid_argument" msg)))
)
;; Host primitives exposed for the OCaml stdlib (lib/ocaml/runtime.sx).
;; Underscore-prefixed to avoid clashing with user names.
(list "_string_length" (fn (s) (len s)))
(list "_string_get" (fn (s) (fn (i) (nth s i))))
(list "_string_sub" (fn (s) (fn (i) (fn (n) (slice s i (+ i n))))))
(list "_string_concat" (fn (sep) (fn (xs) (join sep xs))))
(list "_string_upper" (fn (s) (upper s)))
(list "_string_lower" (fn (s) (lower s)))
(list "_string_starts_with" (fn (p) (fn (s) (starts-with? s p))))
(list "_int_of_string" (fn (s) (parse-number s)))
(list "_string_of_int" (fn (i) (str i)))
(list "_string_of_float" (fn (f) (str f)))
(list "_char_code" (fn (c) (char-code c)))
(list "_char_chr" (fn (n) (char-from-code n)))
;; Print: prints to host stdout via println.
(list "print_string" (fn (s) (begin (print s) nil)))
(list "print_endline" (fn (s) (begin (println s) nil)))
(list "print_int" (fn (i) (begin (print (str i)) nil))))))
(define ocaml-env-lookup
(fn (env name)

View File

@@ -136,6 +136,40 @@
match r with
| Ok _ -> false
| Error _ -> true
end ;;
module String = struct
let length s = _string_length s
let get s i = _string_get s i
let sub s i n = _string_sub s i n
let concat sep xs = _string_concat sep xs
let uppercase_ascii s = _string_upper s
let lowercase_ascii s = _string_lower s
let starts_with prefix s = _string_starts_with prefix s
end ;;
module Char = struct
let code c = _char_code c
let chr n = _char_chr n
let lowercase_ascii c = _string_lower c
let uppercase_ascii c = _string_upper c
end ;;
module Int = struct
let to_string i = _string_of_int i
let of_string s = _int_of_string s
let abs n = if n < 0 then 0 - n else n
let max a b = if a > b then a else b
let min a b = if a < b then a else b
end ;;
module Float = struct
let to_string f = _string_of_float f
end ;;
module Printf = struct
let sprintf fmt = fmt
let printf fmt = print_string fmt
end")
(define ocaml-stdlib-loaded false)

View File

@@ -672,6 +672,36 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 913)
(eval "(ocaml-type-of \"not true\")")
;; ── Phase 6 expanded: String / Char / Int / Float modules ─────
(epoch 950)
(eval "(ocaml-run \"String.length \\\"hello\\\"\")")
(epoch 951)
(eval "(ocaml-run \"String.uppercase_ascii \\\"hi\\\"\")")
(epoch 952)
(eval "(ocaml-run \"String.lowercase_ascii \\\"HI\\\"\")")
(epoch 953)
(eval "(ocaml-run \"String.sub \\\"hello\\\" 1 3\")")
(epoch 954)
(eval "(ocaml-run \"String.starts_with \\\"he\\\" \\\"hello\\\"\")")
(epoch 955)
(eval "(ocaml-run \"String.concat \\\",\\\" [\\\"a\\\"; \\\"b\\\"; \\\"c\\\"]\")")
(epoch 960)
(eval "(ocaml-run \"Char.code \\\"A\\\"\")")
(epoch 961)
(eval "(ocaml-run \"Char.chr 65\")")
(epoch 970)
(eval "(ocaml-run \"Int.to_string 42\")")
(epoch 971)
(eval "(ocaml-run \"Int.of_string \\\"123\\\"\")")
(epoch 972)
(eval "(ocaml-run \"Int.abs (-5)\")")
(epoch 973)
(eval "(ocaml-run \"Int.max 7 3\")")
(epoch 974)
(eval "(ocaml-run \"Int.min 7 3\")")
EPOCHS
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1065,6 +1095,23 @@ check 911 "type twice" ' -> '
check 912 "type bool branch" '"Bool -> Int"'
check 913 "type not true" '"Bool"'
# ── Phase 6 String / Char / Int ─────────────────────────────────
check 950 "String.length" '5'
check 951 "String.uppercase_ascii" '"HI"'
check 952 "String.lowercase_ascii" '"hi"'
check 953 "String.sub" '"ell"'
check 954 "String.starts_with" 'true'
check 955 "String.concat" '"a,b,c"'
check 960 "Char.code A" '65'
check 961 "Char.chr 65" '"A"'
check 970 "Int.to_string" '"42"'
check 971 "Int.of_string" '123'
check 972 "Int.abs -5" '5'
check 973 "Int.max" '7'
check 974 "Int.min" '3'
TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"

View File

@@ -229,6 +229,16 @@ SX CEK evaluator (both JS and OCaml hosts)
_(Pending: fold/join/iter/to_list/to_result.)_
- [~] `Result`: `map`, `bind`, `is_ok`, `is_error`. _(Pending:
fold/get_ok/get_error/map_error/to_option.)_
- [~] `String`: `length`, `get`, `sub`, `concat`, `uppercase_ascii`,
`lowercase_ascii`, `starts_with`. _(Pending: split_on_char, trim,
contains, ends_with, index_opt, replace_all.)_
- [~] `Char`: `code`, `chr`, `lowercase_ascii`, `uppercase_ascii`.
_(Pending: escaped.)_
- [~] `Int`: `to_string`, `of_string`, `abs`, `max`, `min`.
_(Pending: arithmetic helpers, min_int/max_int.)_
- [~] `Float`: `to_string`. _(Pending: of_string, arithmetic helpers.)_
- [~] `Printf`: stub `sprintf`/`printf`. _(Real format-string
interpretation pending.)_
- [ ] `String`: `length`, `get`, `sub`, `concat`, `split_on_char`, `trim`,
`uppercase_ascii`, `lowercase_ascii`, `contains`, `starts_with`, `ends_with`,
`index_opt`, `replace_all` (non-stdlib but needed).
@@ -333,6 +343,14 @@ the "mother tongue" closure: OCaml → SX → OCaml. This means:
_Newest first._
- 2026-05-08 Phase 6 — extended stdlib slice (+13 tests, 278 total).
Host primitives exposed via `_string_*`, `_char_*`, `_int_*`,
`_string_of_*` underscore-prefixed builtins so the OCaml-side
`lib/ocaml/runtime.sx` modules can wrap them: String (length, get,
sub, concat, uppercase_ascii, lowercase_ascii, starts_with), Char
(code, chr, lowercase_ascii, uppercase_ascii), Int (to_string,
of_string, abs, max, min), Float.to_string, Printf stubs. Also added
`print_string`/`print_endline`/`print_int` builtins.
- 2026-05-08 Phase 5 — Hindley-Milner type inference, paired-sequencing
consumer of `lib/guest/hm.sx` (algebra) and `lib/guest/match.sx`
(unify). `lib/ocaml/infer.sx` ships Algorithm W rules for OCaml AST: