From 2d519461c435cb016fc31a70850d14ace64c2a13 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 9 May 2026 05:56:10 +0000 Subject: [PATCH] ocaml: phase 6 Seq module (eager, list-backed) (+4 tests, 576 total) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Real OCaml's Seq.t is 'unit -> Cons of elt * Seq.t | Nil' — a lazy thunk that lets you build infinite sequences. Ours is just a list, which gives the right shape for everything in baseline programs that don't rely on laziness (taking from infinite sequences would force memory). API: empty, cons, return, is_empty, iter, iteri, map, filter, filter_map, fold_left, length, take, drop, append, to_list, of_list, init, unfold. unfold takes a step fn 'acc -> Option (elt * acc)' and threads through until it returns None: Seq.fold_left (+) 0 (Seq.unfold (fun n -> if n > 4 then None else Some (n, n + 1)) 1) = 1 + 2 + 3 + 4 = 10 --- lib/ocaml/runtime.sx | 70 ++++++++++++++++++++++++++++++++++++++++++++ lib/ocaml/test.sh | 16 ++++++++++ plans/ocaml-on-sx.md | 10 +++++++ 3 files changed, 96 insertions(+) diff --git a/lib/ocaml/runtime.sx b/lib/ocaml/runtime.sx index 62eee777..c5eb84d0 100644 --- a/lib/ocaml/runtime.sx +++ b/lib/ocaml/runtime.sx @@ -696,6 +696,76 @@ let bits () = int 1073741824 end ;; + module Seq = struct + (* Eager list-backed Seq — no laziness. Real OCaml's Seq is a + thunk producing Cons / Nil; ours is just a list. Adequate for + most baseline programs that don't rely on infinite sequences. *) + let empty = [] + let cons x s = x :: s + let return x = [x] + let is_empty s = match s with [] -> true | _ -> false + + let rec iter f s = + match s with + | [] -> () + | h :: t -> f h; iter f t + + let rec iteri f s = + let rec go i xs = + match xs with + | [] -> () + | h :: t -> f i h; go (i + 1) t + in + go 0 s + + let rec map f s = match s with [] -> [] | h :: t -> f h :: map f t + + let rec filter p s = + match s with + | [] -> [] + | h :: t -> if p h then h :: filter p t else filter p t + + let rec filter_map f s = + match s with + | [] -> [] + | h :: t -> + match f h with + | Some v -> v :: filter_map f t + | None -> filter_map f t + + let rec fold_left f init s = + match s with + | [] -> init + | h :: t -> fold_left f (f init h) t + + let rec length s = + match s with [] -> 0 | _ :: t -> 1 + length t + + let rec take n s = + if n <= 0 then [] + else match s with [] -> [] | h :: t -> h :: take (n - 1) t + + let rec drop n s = + if n <= 0 then s + else match s with [] -> [] | _ :: t -> drop (n - 1) t + + let rec append a b = + match a with [] -> b | h :: t -> h :: append t b + + let to_list s = s + let of_list xs = xs + + let rec init n f = + if n = 0 then [] else + let rec build i = if i = n then [] else f i :: build (i + 1) in + build 0 + + let rec unfold f acc = + match f acc with + | None -> [] + | Some (x, acc') -> x :: unfold f acc' + end ;; + module Lazy = struct let force lz = _lazy_force lz end ;; diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index 9135631b..58868059 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -1430,6 +1430,16 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 5182) (eval "(ocaml-run-program \"module IntOrd = struct let compare a b = a - b end ;; module M = Map.Make (IntOrd) ;; let m = M.add 1 \\\"a\\\" (M.add 2 \\\"b\\\" M.empty) ;; M.cardinal m\")") +;; ── Seq module (eager list-backed) ──────────────────────────── +(epoch 5190) +(eval "(ocaml-run \"Seq.fold_left (+) 0 (Seq.map (fun x -> x * x) (Seq.of_list [1;2;3;4]))\")") +(epoch 5191) +(eval "(ocaml-run \"Seq.length (Seq.filter (fun x -> x mod 2 = 0) (Seq.of_list [1;2;3;4;5;6;7;8;9;10]))\")") +(epoch 5192) +(eval "(ocaml-run \"Seq.fold_left (+) 0 (Seq.init 5 (fun i -> i * 2))\")") +(epoch 5193) +(eval "(ocaml-run \"Seq.fold_left (+) 0 (Seq.unfold (fun n -> if n > 4 then None else Some (n, n + 1)) 1)\")") + EPOCHS OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) @@ -2274,6 +2284,12 @@ check 5180 "Set.Make dedupe sum" '9' check 5181 "Set.Make mem" 'true' check 5182 "Map.Make cardinal" '2' +# ── Seq module (eager list-backed) ────────────────────────────── +check 5190 "Seq fold map squares" '30' +check 5191 "Seq filter evens" '5' +check 5192 "Seq init 5 i*2" '20' +check 5193 "Seq unfold 1..4 sum" '10' + 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 0c9fe76f..212bfbb7 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,16 @@ _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 6 — Seq module (eager, list-backed) (+4 tests, + 576 total). Real OCaml's Seq is lazy (a thunk producing + Cons / Nil); ours is just a list, which is adequate for most + baseline programs that don't rely on infinite sequences. API: + empty, cons, return, is_empty, iter, iteri, map, filter, + filter_map, fold_left, length, take, drop, append, to_list, + of_list, init, unfold. unfold takes a step fn `acc -> Option (elt + * acc)` and threads through until it returns None. Lets us write + `Seq.fold_left (+) 0 (Seq.unfold (fun n -> if n > 4 then None else + Some (n, n + 1)) 1)` → 10. - 2026-05-09 Phase 5.1 — unique_set.ml baseline (Set.Make + IntOrd functor app, count uniques in [3;1;4;1;5;9;2;6;5;3;5;8;9;7;9] → 9). First baseline that exercises the functor pipeline end to