parser(step 60): user types #11

Merged
crowmaki merged 1 commit from parser/user-types into main 2026-08-23 22:37:20 +00:00
Owner

Add the declaration forms that name a new shape: struct (owned fields,
defaults, a head), enum (base type, variant values, trailing comma),
interface (operator[] naming, optional closing ;), impl (both <...> lists,
the for target, a body), type aliases, and the #[...] attribute.

parse_item reads { attribute } declaration | statement. That is what an
impl body is made of (impl-member = top-level-item), so it lands here and
step 70's program loop reuses it rather than the other way round. A
decl_parser table maps keyword to parser once, so parse_decl's dispatch and
parse_item's "does a declaration start here?" cannot drift apart.

Decl::dump now renders an impl's interface as (I T), the shape
TypeRef::Named already dumps. The arguments used to print flat beside the
name, so impl<T> I<T> for X and impl<T> I for X dumped alike and the
test contract could not tell them apart. 60-user-types.md's draft assertion
had the same hole; it and three claims the reviewed grammar overtook
(struct heads take type parameters, alias heads do not, enum bodies take a
trailing comma) are corrected there.

Verified by driving every fixture file through parse_item, not only the
transcribed snippets: all 35 parse/ fixtures build a tree. Three semantics/
fixtures still do not, each blocked by a gap older than this step, filed as
backlog items 45-47 (type modifiers have no TypeRef node; new [N]T takes
only a literal size; the static-member declaration form has no leading
keyword to dispatch on). Those are what step 70 needs before the fixture
driver can drop its #[ignore].

Add the declaration forms that name a new shape: struct (owned fields, defaults, a <T> head), enum (base type, variant values, trailing comma), interface (operator[] naming, optional closing ;), impl (both <...> lists, the for target, a body), type aliases, and the #[...] attribute. parse_item reads `{ attribute } declaration | statement`. That is what an impl body is made of (impl-member = top-level-item), so it lands here and step 70's program loop reuses it rather than the other way round. A decl_parser table maps keyword to parser once, so parse_decl's dispatch and parse_item's "does a declaration start here?" cannot drift apart. Decl::dump now renders an impl's interface as `(I T)`, the shape TypeRef::Named already dumps. The arguments used to print flat beside the name, so `impl<T> I<T> for X` and `impl<T> I for X` dumped alike and the test contract could not tell them apart. 60-user-types.md's draft assertion had the same hole; it and three claims the reviewed grammar overtook (struct heads take type parameters, alias heads do not, enum bodies take a trailing comma) are corrected there. Verified by driving every fixture file through parse_item, not only the transcribed snippets: all 35 parse/ fixtures build a tree. Three semantics/ fixtures still do not, each blocked by a gap older than this step, filed as backlog items 45-47 (type modifiers have no TypeRef node; new [N]T takes only a literal size; the static-member declaration form has no leading keyword to dispatch on). Those are what step 70 needs before the fixture driver can drop its #[ignore].
Add the declaration forms that name a new shape: struct (owned fields,
defaults, a <T> head), enum (base type, variant values, trailing comma),
interface (operator[] naming, optional closing ;), impl (both <...> lists,
the for target, a body), type aliases, and the #[...] attribute.

parse_item reads `{ attribute } declaration | statement`. That is what an
impl body is made of (impl-member = top-level-item), so it lands here and
step 70's program loop reuses it rather than the other way round. A
decl_parser table maps keyword to parser once, so parse_decl's dispatch and
parse_item's "does a declaration start here?" cannot drift apart.

Decl::dump now renders an impl's interface as `(I T)`, the shape
TypeRef::Named already dumps. The arguments used to print flat beside the
name, so `impl<T> I<T> for X` and `impl<T> I for X` dumped alike and the
test contract could not tell them apart. 60-user-types.md's draft assertion
had the same hole; it and three claims the reviewed grammar overtook
(struct heads take type parameters, alias heads do not, enum bodies take a
trailing comma) are corrected there.

Verified by driving every fixture file through parse_item, not only the
transcribed snippets: all 35 parse/ fixtures build a tree. Three semantics/
fixtures still do not, each blocked by a gap older than this step, filed as
backlog items 45-47 (type modifiers have no TypeRef node; new [N]T takes
only a literal size; the static-member declaration form has no leading
keyword to dispatch on). Those are what step 70 needs before the fixture
driver can drop its #[ignore].
crowmaki deleted branch parser/user-types 2026-08-23 22:37:20 +00:00
crowmaki referenced this pull request from a commit 2026-08-23 22:37:20 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
crowmaki/catlang!11
No description provided.