From 986b15c0e52947e335243655c3f224d7dae83d6f Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 8 May 2026 13:58:52 +0000 Subject: [PATCH] ocaml: phase 6 Float module: sqrt/sin/cos/pow/floor/ceil/round/pi (+6 tests, 378 total) Wraps host SX math primitives via _float_* builtins. Float.pi is a Float literal in the OCaml-side module. --- lib/ocaml/eval.sx | 8 ++++++++ lib/ocaml/runtime.sx | 8 ++++++++ lib/ocaml/test.sh | 22 ++++++++++++++++++++++ plans/ocaml-on-sx.md | 6 +++++- 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/ocaml/eval.sx b/lib/ocaml/eval.sx index d7843211..b92da38f 100644 --- a/lib/ocaml/eval.sx +++ b/lib/ocaml/eval.sx @@ -67,6 +67,14 @@ (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))) + ;; Float math primitives. + (list "_float_sqrt" (fn (x) (sqrt x))) + (list "_float_sin" (fn (x) (sin x))) + (list "_float_cos" (fn (x) (cos x))) + (list "_float_pow" (fn (a) (fn (b) (pow a b)))) + (list "_float_floor" (fn (x) (floor x))) + (list "_float_ceil" (fn (x) (ceil x))) + (list "_float_round" (fn (x) (round x))) ;; Polymorphic compare — returns negative / 0 / positive like ;; OCaml's Stdlib.compare. Defers to host SX `<` and `>`. (list "compare" diff --git a/lib/ocaml/runtime.sx b/lib/ocaml/runtime.sx index 3d754646..0c9b3e0e 100644 --- a/lib/ocaml/runtime.sx +++ b/lib/ocaml/runtime.sx @@ -316,6 +316,14 @@ module Float = struct let to_string f = _string_of_float f + let sqrt f = _float_sqrt f + let sin f = _float_sin f + let cos f = _float_cos f + let pow a b = _float_pow a b + let floor f = _float_floor f + let ceil f = _float_ceil f + let round f = _float_round f + let pi = 3.141592653589793 end ;; module Printf = struct diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index e01147c5..0351d0f3 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -922,6 +922,20 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 2304) (eval "(ocaml-type-of \"fun x y -> x +. y\")") +;; ── Float module ─────────────────────────────────────────────── +(epoch 2400) +(eval "(ocaml-run \"Float.sqrt 16.0\")") +(epoch 2401) +(eval "(ocaml-run \"Float.sin 0.0\")") +(epoch 2402) +(eval "(ocaml-run \"Float.cos 0.0\")") +(epoch 2403) +(eval "(ocaml-run \"Float.pow 2.0 10.0\")") +(epoch 2404) +(eval "(ocaml-run \"Float.floor 3.7\")") +(epoch 2405) +(eval "(ocaml-run \"Float.ceil 3.2\")") + EPOCHS OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) @@ -1458,6 +1472,14 @@ check 2302 "10.0 /. 4.0" '2.5' check 2303 "type 1.5 +. 2.5" '"Float"' check 2304 "type fun x y -> x +. y" '"Float -> Float -> Float"' +# ── Float module ──────────────────────────────────────────────── +check 2400 "Float.sqrt 16" '4' +check 2401 "Float.sin 0" '0' +check 2402 "Float.cos 0" '1' +check 2403 "Float.pow 2 10" '1024' +check 2404 "Float.floor 3.7" '3' +check 2405 "Float.ceil 3.2" '4' + 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 7df43b9a..2d34bf31 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -266,7 +266,8 @@ SX CEK evaluator (both JS and OCaml hosts) _(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.)_ +- [~] `Float`: `to_string`, `sqrt`, `sin`, `cos`, `pow`, `floor`, + `ceil`, `round`, `pi`. _(Pending: of_string.)_ - [~] `Printf`: stub `sprintf`/`printf`. _(Real format-string interpretation pending.)_ - [ ] `String`: `length`, `get`, `sub`, `concat`, `split_on_char`, `trim`, @@ -373,6 +374,9 @@ the "mother tongue" closure: OCaml → SX → OCaml. This means: _Newest first._ +- 2026-05-08 Phase 6 — Float module: sqrt/sin/cos/pow/floor/ceil/round + + pi constant (+6 tests, 378 total). Wraps host SX math primitives + via `_float_*` builtins. - 2026-05-08 Phase 1+5+6 — Float arithmetic (`+.` `-.` `*.` `/.`) (+5 tests, 372 total). Tokenizer recognises the dotted operators. Parser table places them at int's level (7 / 8). Eval routes them