feat: parser slice 14 — match expression (MatchExpr, MatchArm, when guard) #3

Manually merged
hkowalski merged 6 commits from feat/003-feat-parser-slice-14-match-expression-matchexp into master 2026-01-07 08:00:00 +01:00
Owner

feat: parser slice 14 — match expression (MatchExpr, MatchArm, when guard)

Along the way:

  • feat: parser slice 15 — catch / defer / return / assert statements
  • docs: add stdlib/ — per-effect and per-type status board
  • feat: parser slice 16 — for loop (closes the parser cascade)
  • prepared a new set of sliced
  • feat: parser slice 17 — lambda expressions (opens expr sub-cascade)

Touches 60 files: docs/README.md, docs/assert.md, docs/errors.md, docs/impl/02-lexer.md, docs/impl/03-parser.md, docs/impl/04-name-resolution.md and 54 more.

feat: parser slice 14 — match expression (MatchExpr, MatchArm, when guard) Along the way: - feat: parser slice 15 — catch / defer / return / assert statements - docs: add stdlib/ — per-effect and per-type status board - feat: parser slice 16 — for loop (closes the parser cascade) - prepared a new set of sliced - feat: parser slice 17 — lambda expressions (opens expr sub-cascade) Touches 60 files: `docs/README.md`, `docs/assert.md`, `docs/errors.md`, `docs/impl/02-lexer.md`, `docs/impl/03-parser.md`, `docs/impl/04-name-resolution.md` and 54 more.
hkowalski approved these changes 2026-01-07 07:55:00 +01:00
hkowalski left a comment

Happy with this. I ran the suite against the branch and it is green, src/rust/crates/ck_parser/src/tests/lambda.rs included.

Happy with this. I ran the suite against the branch and it is green, `src/rust/crates/ck_parser/src/tests/lambda.rs` included.
@ -0,0 +148,4 @@
}
}
SyntaxKind::Eof => return false,
_ => {}
Owner

The catch-all arm means a variant added later compiles and lands here without a word. Can the match on _ name every variant so the compiler tells us?

The catch-all arm means a variant added later compiles and lands here without a word. Can the match on `_` name every variant so the compiler tells us?
@ -100,0 +264,4 @@
self.expect(SyntaxKind::LParen, "E0064", "expected `(` after `assert`");
self.parse_expr(0);
self.expect(SyntaxKind::RParen, "E0065", "expected `)` to close assert");
self.expect(
Owner

The expect message on expect is the only thing a user sees if this fires. Does it say what they should do, or only what we assumed?, at src/rust/crates/ck_parser/src/stmt.rs:267.

The expect message on `expect` is the only thing a user sees if this fires. Does it say what they should do, or only what we assumed?, at src/rust/crates/ck_parser/src/stmt.rs:267.
@ -0,0 +103,4 @@
}
#[test]
fn lambda_body_is_full_expression() {
Owner

lambda_body_is_full_expression reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?

`lambda_body_is_full_expression` reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?
Author
Owner

Split. The decision in lambda_body_is_full_expression is a pure function now, with its own tests in src/rust/crates/ck_parser/src/tests/lambda.rs.

Split. The decision in `lambda_body_is_full_expression` is a pure function now, with its own tests in `src/rust/crates/ck_parser/src/tests/lambda.rs`.
Author
Owner

It said what I assumed. Reworded in src/rust/crates/ck_parser/src/stmt.rs so it names the input that broke it, which is what the bug report will need, at src/rust/crates/ck_parser/src/stmt.rs:267.

It said what I assumed. Reworded in `src/rust/crates/ck_parser/src/stmt.rs` so it names the input that broke it, which is what the bug report will need, at src/rust/crates/ck_parser/src/stmt.rs:267.
Author
Owner

Named them all. A new variant is a compile error in src/rust/crates/ck_parser/src/lambda.rs now, which is where we want to find out.

Named them all. A new variant is a compile error in `src/rust/crates/ck_parser/src/lambda.rs` now, which is where we want to find out.
`match` is wired in as a Pratt primary so it composes with the slice-10
binary / postfix operators for free. Scrutinee and arm body use
parse_expr(0); arm patterns reuse slice 13; the `when` guard finally
gets a caller. Three diagnostics (E0061..E0063) for missing `{`, `}`,
and `->`. Slice-13 type-assert greedy `:` folds into the pattern
before the arm's `->`, so `s: String -> ...` works without extra logic.
Closes the parser dependency cascade locked 2026-05-21. Adds the four
keyword-introduced statement forms to `parse_block_body` ahead of the
speculative expression parse via a `try_parse_stmt_keyword` dispatch:

- `CatchStmt   ::= catch ( Pattern ) Block`  (binder reuses slice-13
  patterns; `e: Err<T>` parses as `TypeAssertPattern` for free)
- `DeferStmt   ::= defer Expr ;`             (multi-stmt body via the
  slice-11 block-as-primary form: `defer { ... };`)
- `ReturnStmt  ::= return Expr? ;`           (bare `return;` is the
  optional-expression form)
- `AssertStmt  ::= assert ( Expr ) ;`        (mandatory parens; hint
  slot / narrowing / soft-vs-hard deferred to later stages)

Five new diagnostics (E0064..E0068) for the slot-specific cases;
`;`-terminator codes (E0055) and pattern/expr codes (E0048, E0056) are
reused unchanged. `program_basic.cktest` and `program_record.cktest`
fixtures flip from `Error+E0048` on `return ...` to a real `ReturnStmt`
node.

Doc lock-ins that gated this slice (design questions resolved
2026-05-22):

- `assert.md` — recognized predicate set, release-mode strip, two-form
  syntax, placement rules.
- `errors.md` — catch binder shape; defer-on-every-exit semantics.
- `syntax.md` — statement grammar with all five forms.
- `principles.md` — Go-speed reframed as the north star (aspiration,
  not gate) + single-pass parser as the front-end's compile-speed
  commitment.
- `impl/README.md` — single-pass-parser architectural lock.
- `meta-substrate.md` — `AssertEvaluated` correctly `—` in release
  (asserts are stripped, emission site does not exist).
- `principles.md` + `04-name-resolution.md` + `open-questions.md` —
  `comptime` formally dropped; `const` evaluation rules carry the
  surviving piece.
Adds `docs/stdlib/` as a status-board directory for the standard
library: one file per effect (`effect_*.md` — alloc, async, file, log,
meta, net, panic, proc, rand, time) and one file per type (`type_*.md`
— collections, duration, err, future, instant, path, primitives,
strings, tagged_value, traceid), plus a README that groups them by
locked / sketched / pending design. This is the surface form of open
question #9 ("what is the stdlib"): treat each file as the current
design state of one item, not a finished reference. Linked from the
top-level `docs/README.md` index.
ForStmt ::= for Pattern in Expr Block. Body's closing `}` is the
terminator (like CatchStmt); no trailing `;`. Reuses slice-13 patterns,
slice-10 expression, slice-11 block — no new shapes. Adds For / In as
reserved keywords and three diagnostics (E0069..E0071). Closes the
parser cascade locked 2026-05-21 (expressions → blocks → statements →
patterns → match → catch/defer/return/assert → for).
LambdaExpr / LambdaParamList / LambdaParam wired as a parse_primary
branch on `(` with a non-consuming paren-balanced disambiguator against
ParenExpr. Body reuses the slice-10 Pratt parser; the slice-11
block-as-primary form covers multi-statement bodies for free. Adds
E0072..E0074. R3 tightened 850 → 840 after compressing the lib.rs slice
index to single-line pointers.
hkowalski manually merged commit 9c99abba51 into master 2026-01-07 08:00:00 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
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
northgale/cklang-bootstrap!3
No description provided.