ocaml: phase 1+2 records {x=1;y=2} + with-update (+6 tests, 289 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s

Parser: { f = e; f = e; ... } -> (:record (F E)...). { base with f = e;
... } -> (:record-update BASE (F E)...). Eval builds a dict from field
bindings; record-update merges the new fields over the base dict — the
same dict representation already used for modules.

{ also added to at-app-start? so records are valid arg atoms. Field
access via the existing :field postfix unifies record/module access.

Record patterns deferred to a later iteration.
This commit is contained in:
2026-05-08 09:26:24 +00:00
parent 9473911cf3
commit 7fb65cd26a
4 changed files with 115 additions and 2 deletions

View File

@@ -381,6 +381,37 @@
;; matches its argument against the clauses.
(let ((clauses (nth ast 1)) (captured env))
(fn (arg) (ocaml-match-clauses arg clauses captured))))
((= tag "record")
(let ((fields (rest ast)) (result {}))
(begin
(define loop
(fn (xs)
(when (not (= xs (list)))
(let ((kv (first xs)))
(let ((k (first kv)) (v (ocaml-eval (nth kv 1) env)))
(begin
(set! result (merge result (dict k v)))
(loop (rest xs))))))))
(loop fields)
result)))
((= tag "record-update")
(let ((base-ast (nth ast 1)) (fields (rest (rest ast))))
(let ((base (ocaml-eval base-ast env)))
(cond
((dict? base)
(let ((result base))
(begin
(define loop
(fn (xs)
(when (not (= xs (list)))
(let ((kv (first xs)))
(let ((k (first kv)) (v (ocaml-eval (nth kv 1) env)))
(begin
(set! result (merge result (dict k v)))
(loop (rest xs))))))))
(loop fields)
result)))
(else (error (str "ocaml-eval: with-update on non-record: " base)))))))
((= tag "field")
;; `e.name` — evaluate e, expect a dict (record/module), get name.
;; Special case: `(:field (:con "M") "x")` looks up M as a module