ocaml: phase 6 expanded stdlib (+15 tests, 319 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 54s

List: concat/flatten, init, find/find_opt, partition, mapi/iteri,
assoc/assoc_opt. Option: iter/fold/to_list. Result: get_ok/get_error/
map_error/to_option.

Fixed skip-to-boundary! in parser to track let..in / begin..end /
struct..end / for/while..done nesting via a depth counter — without
this, nested-let inside a top-level decl body trips over the
decl-boundary detector. Stdlib functions like List.init / mapi / iteri
use begin..end to make their nested-let intent explicit.
This commit is contained in:
2026-05-08 12:49:23 +00:00
parent bc557a5ad2
commit 88c02c7c73
4 changed files with 202 additions and 20 deletions

View File

@@ -895,22 +895,45 @@
(fn
()
(let ((t (peek-tok))) (if (= t nil) (len src) (get t :pos)))))
;; skip-to-boundary! advances `idx` to the next top-level decl
;; boundary, tracking `let`/`begin`/`struct` etc. nesting so that
;; an inner `let ... in ...` doesn't terminate a top-level decl
;; body. Boundary tokens (when at depth 0):
;; ;; let module open include and type exception
;; Boundary at any depth: eof.
(define
skip-to-boundary!
(fn
()
(cond
((>= idx tok-len) nil)
((= (ocaml-tok-type (peek-tok)) "eof") nil)
((at-op? ";;") nil)
((at-kw? "let") nil)
((at-kw? "module") nil)
((at-kw? "open") nil)
((at-kw? "include") nil)
((at-kw? "and") nil)
((at-kw? "type") nil)
((at-kw? "exception") nil)
(else (begin (advance-tok!) (skip-to-boundary!))))))
(fn ()
(let ((depth 0))
(begin
(define step
(fn ()
(cond
((>= idx tok-len) nil)
((= (ocaml-tok-type (peek-tok)) "eof") nil)
((and (= depth 0) (at-op? ";;")) nil)
((and (= depth 0) (at-kw? "let")) nil)
((and (= depth 0) (at-kw? "module")) nil)
((and (= depth 0) (at-kw? "open")) nil)
((and (= depth 0) (at-kw? "include")) nil)
((and (= depth 0) (at-kw? "and")) nil)
((and (= depth 0) (at-kw? "type")) nil)
((and (= depth 0) (at-kw? "exception")) nil)
;; Track nested blocks that have explicit closing
;; tokens. let..in / begin..end / struct..end /
;; sig..end / for..done / while..done. `if`/`match`/
;; `try` don't have hard close tokens so we don't
;; track them — their bodies are bounded by the
;; surrounding expression structure.
((or (at-kw? "let") (at-kw? "begin") (at-kw? "struct")
(at-kw? "sig") (at-kw? "for") (at-kw? "while"))
(begin (set! depth (+ depth 1)) (advance-tok!) (step)))
((or (at-kw? "in") (at-kw? "end") (at-kw? "done"))
(begin
(when (> depth 0) (set! depth (- depth 1)))
(advance-tok!) (step)))
(else (begin (advance-tok!) (step))))))
(step)))))
(define
parse-decl-let
(fn ()