ocaml: parser accepts top-level tuple patterns in match cases
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s

Real OCaml accepts `match e1, e2 with | p1, p2 -> …` without
surrounding parens. parse-pattern previously stopped at the cons
layer (`p :: rest`) and treated a trailing `,` as a separator
the outer caller couldn't handle, surfacing as
"expected op -> got op ,".

Fix: `parse-pattern` now collects comma-separated patterns into a
:ptuple after parse-pattern-cons, before the optional `as` alias.
The scrutinee side already built tuples via parse-tuple, so both
sides are now symmetric.

lru_cache.ml (iter 258) reverts its workaround back to the natural
form:

  let rec take n lst = match n, lst with
    | 0, _ -> []
    | _, [] -> []
    | _, h :: r -> h :: take (n - 1) r

607/607 regressions clean.
This commit is contained in:
2026-05-11 00:31:08 +00:00
parent fd1f94f292
commit 800dca67ca
3 changed files with 41 additions and 12 deletions

View File

@@ -27,11 +27,10 @@ let put k v =
let cleaned = remove !cache in
let trimmed =
if List.length cleaned >= cap then
let rec take n lst =
if n = 0 then []
else match lst with
| [] -> []
| h :: r -> h :: take (n - 1) r
let rec take n lst = match n, lst with
| 0, _ -> []
| _, [] -> []
| _, h :: r -> h :: take (n - 1) r
in
take (cap - 1) cleaned
else cleaned

View File

@@ -328,14 +328,38 @@
;; use `(A | B)` if needed in the future via a parens-only or.
(set! parse-pattern
(fn ()
(let ((p (parse-pattern-cons)))
;; Top-level pattern: cons-pat, optionally followed by
;; comma-separated patterns for ad-hoc tuple matching
;; (`match e1, e2 with | p1, p2 -> …`), optionally aliased
;; with `as name`.
(let ((first (parse-pattern-cons)))
(cond
((at-op? ",")
(let ((items (list first)))
(begin
(define loop-comma
(fn ()
(when (at-op? ",")
(begin
(advance-tok!)
(append! items (parse-pattern-cons))
(loop-comma)))))
(loop-comma)
(let ((p (cons :ptuple items)))
(cond
((at-kw? "as")
(begin
(advance-tok!)
(let ((n (ocaml-tok-value
(consume! "ident" nil))))
(list :pas p n))))
(else p))))))
((at-kw? "as")
(begin
(advance-tok!)
(let ((n (ocaml-tok-value (consume! "ident" nil))))
(list :pas p n))))
(else p)))))
(list :pas first n))))
(else first)))))
(define peek-tok-at
(fn (n)