From 4fdf6980dae9b304bebacc4afce5a93b09a19ca4 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 10 May 2026 06:11:57 +0000 Subject: [PATCH] ocaml: parser accepts if/match/let/fun as rhs of <- and := Previously `a.(i) <- if c then x else y` failed with "unexpected token keyword if" because parse-binop-rhs called parse-prefix for the rhs, which doesn't accept if/match/let/fun. Real OCaml allows full expressions on the rhs of <-/:=. Fix: special-case prec-1 ops in parse-binop-rhs to call parse-expr-no-seq instead of parse-prefix. The recursive parse-binop-rhs with min-prec restored after picks up any further chained <- (since both ops are right-associative with no higher-prec binops above them). Manacher baseline updated to use bare `if` on rhs of <-, removing the parens workaround from iter 235. 607/607 regressions remain clean. --- lib/ocaml/baseline/manacher.ml | 2 +- lib/ocaml/parser.sx | 32 ++++++++++++++++++++++---------- plans/ocaml-on-sx.md | 14 ++++++++++---- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/ocaml/baseline/manacher.ml b/lib/ocaml/baseline/manacher.ml index c80a250a..02bb99b3 100644 --- a/lib/ocaml/baseline/manacher.ml +++ b/lib/ocaml/baseline/manacher.ml @@ -13,7 +13,7 @@ let manacher s = if i < !right then begin let v = !right - i in let pm = p.(mirror) in - p.(i) <- (if pm < v then pm else v) + p.(i) <- if pm < v then pm else v end; while i + p.(i) + 1 < m && i - p.(i) - 1 >= 0 && t.(i + p.(i) + 1) = t.(i - p.(i) - 1) do diff --git a/lib/ocaml/parser.sx b/lib/ocaml/parser.sx index 92773071..941507ea 100644 --- a/lib/ocaml/parser.sx +++ b/lib/ocaml/parser.sx @@ -741,16 +741,28 @@ (else (begin (advance-tok!) - (let - ((rhs (parse-prefix)) - (next-min - (if - (ocaml-binop-right? op) - prec - (+ prec 1)))) - (begin - (set! rhs (parse-binop-rhs rhs next-min)) - (parse-binop-rhs (list :op op lhs rhs) min-prec)))))))))))) + ;; For `<-` and `:=`, the rhs is at expression + ;; level — accept `if/match/let/fun/...` keywords + ;; on the right (real OCaml does). Otherwise, + ;; fall back to the standard prefix-then-binop + ;; chain. + (cond + ((or (= op "<-") (= op ":=")) + (let ((rhs (parse-expr-no-seq))) + (parse-binop-rhs + (list :op op lhs rhs) min-prec))) + (else + (let + ((rhs (parse-prefix)) + (next-min + (if + (ocaml-binop-right? op) + prec + (+ prec 1)))) + (begin + (set! rhs (parse-binop-rhs rhs next-min)) + (parse-binop-rhs + (list :op op lhs rhs) min-prec)))))))))))))) (define parse-binary (fn diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index e24a59e0..19410721 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,16 +407,22 @@ _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-10 Phase 5.1 — parser: accept `if/match/let/fun/...` as + the rhs of `<-` and `:=`. parse-binop-rhs now special-cases prec-1 + ops (`<-`, `:=`) to call parse-expr-no-seq for their right operand + instead of parse-prefix. Real OCaml accepts `a.(i) <- if c then x + else y`, `r := match e with | A -> 1 | B -> 2`, etc. Manacher + baseline (iter 235) updated to use bare `if` on rhs of `<-`, + matching the workaround note left in its previous Progress entry. + 607/607 regressions clean. Useful improvement for hot inner-loop + code that needs conditional rhs. - 2026-05-10 Phase 5.1 — manacher.ml baseline (Manacher's longest palindromic substring on "babadaba" = 7). Inserts `#` separators to unify odd/even cases (string of length 2n+1), then maintains palindrome radii in `p[]` plus a current rightmost-reach pair (center, right). Linear time. The full input "babadaba" itself is not a palindrome, but "abadaba" (positions 1..7) is — length 7. - Note: `p.(i) <- if pm < v then pm else v` requires explicit - parens — our parser doesn't accept `if` as the rhs of `<-` at - binop level (real OCaml does); workaround until we relax binop - RHS parsing. 149 baseline programs total. + 149 baseline programs total. - 2026-05-10 Phase 5.1 — floyd_warshall.ml baseline (all-pairs shortest path on 4-node weighted graph, dist 0→3 = 9). Standard O(n³) DP: for each intermediate vertex k, relax all (i,j) pairs.