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

@@ -163,7 +163,7 @@
((= tt "ctor") true)
((and (= tt "keyword") (or (= tv "true") (= tv "false")))
true)
((and (= tt "op") (or (= tv "(") (= tv "["))) true)
((and (= tt "op") (or (= tv "(") (= tv "[") (= tv "{"))) true)
(else false)))))
(set!
parse-pattern-atom
@@ -401,6 +401,60 @@
(let
((e (parse-expr)))
(begin (consume! "keyword" "end") e))))
;; Record literal { f1 = e1; f2 = e2 } or update
;; { r with f1 = e1; f2 = e2 }.
((and (= tt "op") (= tv "{"))
(begin
(advance-tok!)
(cond
;; { r with field = expr; ... } — base ident + with.
((and (= (ocaml-tok-type (peek-tok)) "ident")
(= (ocaml-tok-value (peek-tok-at 1)) "with"))
(let ((base-name (ocaml-tok-value (peek-tok))))
(begin
(advance-tok!) ;; ident
(advance-tok!) ;; with
(let ((fields (list)))
(begin
(define one
(fn ()
(let ((fname (ocaml-tok-value (consume! "ident" nil))))
(begin
(consume! "op" "=")
(let ((fexpr (parse-expr-no-seq)))
(append! fields (list fname fexpr)))))))
(one)
(define more
(fn ()
(when (at-op? ";")
(begin (advance-tok!)
(when (not (at-op? "}"))
(begin (one) (more)))))))
(more)
(consume! "op" "}")
(cons :record-update
(cons (list :var base-name) fields)))))))
(else
;; Plain record literal { f = e; f = e; ... }.
(let ((fields (list)))
(begin
(define one
(fn ()
(let ((fname (ocaml-tok-value (consume! "ident" nil))))
(begin
(consume! "op" "=")
(let ((fexpr (parse-expr-no-seq)))
(append! fields (list fname fexpr)))))))
(one)
(define more
(fn ()
(when (at-op? ";")
(begin (advance-tok!)
(when (not (at-op? "}"))
(begin (one) (more)))))))
(more)
(consume! "op" "}")
(cons :record fields)))))))
(else
(error
(str
@@ -425,7 +479,7 @@
((= tt "ctor") true)
((and (= tt "keyword") (or (= tv "true") (= tv "false") (= tv "begin")))
true)
((and (= tt "op") (or (= tv "(") (= tv "["))) true)
((and (= tt "op") (or (= tv "(") (= tv "[") (= tv "{"))) true)
(else false)))))
(define parse-atom-postfix
(fn ()