ocaml: phase 2 let..and.. mutual recursion (+3 tests, 251 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s

Parser collects multiple bindings via 'and', emitting (:def-rec-mut
BINDINGS) for let-rec chains and (:def-mut BINDINGS) for non-rec.
Single bindings keep the existing (:def …) / (:def-rec …) shapes.

Eval (def-rec-mut): allocate placeholder cell per binding, build joint
env where each name forwards through its cell, then evaluate each rhs
against the joint env and fill the cells. Even/odd mutual-rec works.
This commit is contained in:
2026-05-08 08:53:53 +00:00
parent 19f1cad11d
commit 4c6790046c
4 changed files with 116 additions and 36 deletions

View File

@@ -790,46 +790,51 @@
((at-kw? "module") nil)
((at-kw? "open") nil)
((at-kw? "include") nil)
((at-kw? "and") nil)
(else (begin (advance-tok!) (skip-to-boundary!))))))
(define
parse-decl-let
(fn
()
(fn ()
(advance-tok!)
(let
((reccy false))
(let ((reccy false) (bindings (list)))
(begin
(when
(at-kw? "rec")
(begin (advance-tok!) (set! reccy true)))
(let
((name (ocaml-tok-value (consume! "ident" nil)))
(params (list)))
(begin
(define
collect-params
(fn
()
(when
(check-tok? "ident" nil)
(begin
(append! params (ocaml-tok-value (peek-tok)))
(advance-tok!)
(collect-params)))))
(collect-params)
(consume! "op" "=")
(let
((expr-start (cur-pos)))
(when (at-kw? "rec") (begin (advance-tok!) (set! reccy true)))
(define parse-one!
(fn ()
(let ((nm (ocaml-tok-value (consume! "ident" nil)))
(ps (list)))
(begin
(skip-to-boundary!)
(let
((expr-src (slice src expr-start (cur-pos))))
(let
((expr (ocaml-parse expr-src)))
(if
reccy
(list :def-rec name params expr)
(list :def name params expr))))))))))))
(define collect-params
(fn ()
(when (check-tok? "ident" nil)
(begin
(append! ps (ocaml-tok-value (peek-tok)))
(advance-tok!)
(collect-params)))))
(collect-params)
(consume! "op" "=")
(let ((expr-start (cur-pos)))
(begin
(skip-to-boundary!)
(let ((expr-src (slice src expr-start (cur-pos))))
(let ((expr (ocaml-parse expr-src)))
(append! bindings (list nm ps expr))))))))))
(parse-one!)
(define more
(fn ()
(when (at-kw? "and")
(begin (advance-tok!) (parse-one!) (more)))))
(more)
(cond
((= (len bindings) 1)
(let ((b (first bindings)))
(if reccy
(list :def-rec (nth b 0) (nth b 1) (nth b 2))
(list :def (nth b 0) (nth b 1) (nth b 2)))))
(else
(if reccy
(list :def-rec-mut bindings)
(list :def-mut bindings))))))))
(define
parse-decl-expr
(fn