diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index 7ddf40cd..86ceac8d 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -17,6 +17,7 @@ "poly_stack.ml": 5, "queens.ml": 2, "quicksort.ml": 44, + "roman.ml": 44, "sum_squares.ml": 385, "word_count.ml": 3 } diff --git a/lib/ocaml/baseline/roman.ml b/lib/ocaml/baseline/roman.ml new file mode 100644 index 00000000..5dec490d --- /dev/null +++ b/lib/ocaml/baseline/roman.ml @@ -0,0 +1,20 @@ +let to_roman n = + let pairs = [ + (1000, "M"); (900, "CM"); (500, "D"); (400, "CD"); + (100, "C"); (90, "XC"); (50, "L"); (40, "XL"); + (10, "X"); (9, "IX"); (5, "V"); (4, "IV"); (1, "I") + ] in + let rec aux n pairs acc = + match pairs with + | [] -> acc + | (v, s) :: rest -> + if n >= v then aux (n - v) pairs (acc ^ s) + else aux n rest acc + in + aux n pairs "" +;; + +List.fold_left + (fun acc n -> acc + String.length (to_roman n)) + 0 + [1; 4; 9; 14; 49; 99; 444; 1994; 3888] diff --git a/lib/ocaml/parser.sx b/lib/ocaml/parser.sx index 642bc607..c686a257 100644 --- a/lib/ocaml/parser.sx +++ b/lib/ocaml/parser.sx @@ -1147,7 +1147,16 @@ (when (at-kw? "rec") (begin (advance-tok!) (set! reccy true))) (define parse-one! (fn () - (let ((nm (ocaml-tok-value (consume! "ident" nil))) + (let ((nm (cond + ((and (at-op? "(") + (< (+ idx 1) tok-len) + (let ((t1 (nth tokens (+ idx 1)))) + (and (= (ocaml-tok-type t1) "op") + (= (ocaml-tok-value t1) ")")))) + (begin (advance-tok!) (advance-tok!) + (str "__unit_" idx))) + (else + (ocaml-tok-value (consume! "ident" nil))))) (ps (list))) (begin (define collect-params diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index 59e816f5..cdaf806b 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -1196,7 +1196,7 @@ cat > "$TMPFILE" << 'EPOCHS' EPOCHS -OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) +OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) check() { local epoch="$1" desc="$2" expected="$3" diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 1b8ec2b9..1dec9472 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,15 @@ _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 5.1 — roman.ml baseline (Roman numeral greedy + encoding). Side-quest: top-level `let () = expr` was unsupported by + ocaml-parse-program — now parse-decl-let recognises `()` as a unit + binding (`__unit_NN` synthetic name), matching the inner-let handling + in parse-let. roman.ml uses recursive pattern match on + `(int * string) list` greedy table + `List.fold_left + String.length` + to compute the cumulative length of 9 encoded numbers (44). + Bumped test.sh server timeout 180→360s for headroom on contended + systems. - 2026-05-08 Phase 4 — `M.(expr)` local-open expression form (+3 tests, 481 total). Implemented in parse-atom-postfix: after consuming `.`, if next token is `(`, parse the inner expression and