ocaml: phase 4 'let f (a, b) = body' tuple-param on inner-let (+3 tests, 556 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s

Mirrors iteration 101's parse-fun change inside parse-let's
parse-one!:

  - same '(IDENT, ...)' detection on collect-params
  - same __pat_N synth name for the function param
  - same innermost-first match-wrapping

Difference: for inner-let the wrapping is applied to the rhs of the
let-binding (which is the function value), not directly to a fun
body.

  let f (a, b) = a + b in f (3, 7)            = 10
  let g x (a, b) = x + a + b in g 1 (2, 3)    = 6
  let h (a, b) (c, d) = a * b + c * d
    in h (1, 2) (3, 4)                        = 14
This commit is contained in:
2026-05-09 04:36:33 +00:00
parent 64f4f10c32
commit b526d81a4c
3 changed files with 62 additions and 5 deletions

View File

@@ -826,13 +826,33 @@
(define parse-one!
(fn ()
(let ((nm (ocaml-tok-value (consume! "ident" nil)))
(ps (list)))
(ps (list))
(tuple-binds (list)))
(begin
(define collect-params
(fn ()
(let ((p (try-consume-param!)))
(when (not (= p nil))
(begin (append! ps p) (collect-params))))))
(cond
;; `(IDENT, ...)` — tuple param.
((and (at-op? "(")
(= (ocaml-tok-type (peek-tok-at 1)) "ident")
(or (= (ocaml-tok-value (peek-tok-at 2)) ",")
(= (ocaml-tok-value (peek-tok-at 2)) ")")))
(cond
((= (ocaml-tok-value (peek-tok-at 2)) ":")
(let ((p (try-consume-param!)))
(when (not (= p nil))
(begin (append! ps p) (collect-params)))))
(else
(let ((pat (parse-pattern)))
(let ((sn (str "__pat_" (len tuple-binds))))
(begin
(append! tuple-binds (list sn pat))
(append! ps sn)
(collect-params)))))))
(else
(let ((p (try-consume-param!)))
(when (not (= p nil))
(begin (append! ps p) (collect-params))))))))
(collect-params)
;; Optional type annotation: skip `: TYPE` before `=`.
(when (at-op? ":")
@@ -848,7 +868,23 @@
(skip-tann)))
(consume! "op" "=")
(let ((rhs (parse-expr)))
(append! bindings (list nm ps rhs)))))))
(begin
;; Wrap rhs with `match __pat_N with PAT -> ...`
;; for each tuple-param, innermost first.
(let ((wrapped rhs))
(begin
(define wrap-binds
(fn (xs)
(when (not (= xs (list)))
(begin
(let ((sn (nth (first xs) 0))
(pat (nth (first xs) 1)))
(set! wrapped
(list :match (list :var sn)
(list (list :case pat wrapped)))))
(wrap-binds (rest xs))))))
(wrap-binds (reverse tuple-binds))
(append! bindings (list nm ps wrapped))))))))))
(parse-one!)
(define more
(fn ()

View File

@@ -1380,6 +1380,14 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 5123)
(eval "(ocaml-run \"(fun a (b, c) d -> a + b + c + d) 1 (2, 3) 4\")")
;; ── let f (a, b) = body — tuple param on inner-let ────────────
(epoch 5130)
(eval "(ocaml-run \"let f (a, b) = a + b in f (3, 7)\")")
(epoch 5131)
(eval "(ocaml-run \"let g x (a, b) = x + a + b in g 1 (2, 3)\")")
(epoch 5132)
(eval "(ocaml-run \"let h (a, b) (c, d) = a * b + c * d in h (1, 2) (3, 4)\")")
EPOCHS
OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -2193,6 +2201,11 @@ check 5121 "List.map fun (a, b)" '(2 12 30)'
check 5122 "List.map fun (k, _)" '("a" "b")'
check 5123 "fun a (b, c) d mixed" '10'
# ── let f (a, b) = body — let with tuple param ──────────────────
check 5130 "let f (a, b) = a + b" '10'
check 5131 "let g x (a, b) mixed" '6'
check 5132 "let h (a, b) (c, d) curried" '14'
TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"

View File

@@ -407,6 +407,14 @@ _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 4 — `let f (a, b) = body in body2` tuple-param on
inner-let bindings (+3 tests, 556 total). Mirrors iteration 101's
parse-fun change inside parse-let's parse-one!: same `(IDENT, ...)`
detection, same `__pat_N` synth name, same innermost-first match
wrapping — but applied to the rhs of the let-binding (which is the
function value). Lets us write `let f (a, b) = a + b in f (3, 7)`,
`let g x (a, b) = x + a + b in g 1 (2, 3)`, and `let h (a, b)
(c, d) = a * b + c * d in h (1, 2) (3, 4)`.
- 2026-05-09 Phase 4 — `fun (a, b) -> body` tuple-param destructuring
(+4 tests, 553 total). parse-fun's collect-params now detects
`(IDENT, ...)` (lookahead at peek-tok-at 1/2 to distinguish from