From ca9e12fc5752153a02c8cdf3aa74aa2fe695fda5 Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 7 May 2026 15:07:38 +0000 Subject: [PATCH] =?UTF-8?q?haskell:=20Phase=2014=20=E2=80=94=20record=20sy?= =?UTF-8?q?ntax=20in=20parser=20(con-rec=20AST=20node)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- lib/haskell/parser.sx | 51 ++++++++++++++++++++++++++++------- plans/haskell-completeness.md | 9 ++++++- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/lib/haskell/parser.sx b/lib/haskell/parser.sx index fcaefbd8..75ace6f9 100644 --- a/lib/haskell/parser.sx +++ b/lib/haskell/parser.sx @@ -1212,16 +1212,47 @@ (not (hk-match? "conid" nil)) (hk-err "expected constructor name")) (let - ((name (get (hk-advance!) "value")) (fields (list))) - (define - hk-cd-loop - (fn - () - (when - (hk-atype-start? (hk-peek)) - (do (append! fields (hk-parse-atype)) (hk-cd-loop))))) - (hk-cd-loop) - (list :con-def name fields)))) + ((name (get (hk-advance!) "value"))) + (cond + ((hk-match? "lbrace" nil) + (begin + (hk-advance!) + (let + ((rec-fields (list))) + (define + hk-rec-loop + (fn + () + (when + (hk-match? "varid" nil) + (let + ((fname (get (hk-advance!) "value"))) + (begin + (hk-expect! "reservedop" "::") + (let + ((ftype (hk-parse-type))) + (begin + (append! rec-fields (list fname ftype)) + (when + (hk-match? "comma" nil) + (begin (hk-advance!) (hk-rec-loop)))))))))) + (hk-rec-loop) + (hk-expect! "rbrace" nil) + (list :con-rec name rec-fields)))) + (:else + (let + ((fields (list))) + (define + hk-cd-loop + (fn + () + (when + (hk-atype-start? (hk-peek)) + (begin + (append! fields (hk-parse-atype)) + (hk-cd-loop))))) + (hk-cd-loop) + (list :con-def name fields))))))) (define hk-parse-tvars (fn diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index ac47b20c..c18897af 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -247,7 +247,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. ### Phase 14 — Record syntax -- [ ] Parser: extend `hk-parse-data` to recognise `{ field :: Type, … }` +- [x] Parser: extend `hk-parse-data` to recognise `{ field :: Type, … }` constructor bodies. AST node: `(:con-rec CNAME [(FNAME TYPE) …])`. - [ ] Desugar: `:con-rec` → positional `:con-def` plus generated accessor functions `(\rec -> case rec of …)` for each field name. @@ -313,6 +313,13 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 14 record parser: `data Foo = Foo { name :: T, … }`: +- Extended `hk-parse-con-def` to peek for `{` after the constructor name; if + found, parse `varid :: type` pairs separated by commas, terminate with `}`, + return `(:con-rec name [(fname ftype) …])`. Positional constructors fall + through to the existing `:con-def` path. Verified record parses; no + regressions in parse.sx (43/43), parser-decls (24/24), deriving (15/15). + **2026-05-07** — Phase 13 conformance: shapes.hs (5/5) → Phase 13 complete: - `class Shape` with a default `perimeter` (using a where-clause inside the default body), two instances `Square` / `Rect` — Square overrides