Skip to content

Conversation

@rossirpaulo
Copy link
Collaborator

@rossirpaulo rossirpaulo commented Dec 17, 2025

Important

Supersedes #2825
I renamed the paulo/map branch to paulo/match and had to recreate this PR. The original is referenced above to preserve the original comments.

This is the first pass on matchs implementation. I've tried to make sure there are plenty of comments referencing the BEP shared yesterday on critical moments; expect a cleanup later on.

There are somethings to keep in mind:

Completed Work

Core Infrastructure

Component Status Location
Lexer tokens Done TokenKind::Match, FatArrow, Pipe
Syntax kinds Done syntax_kind.rs
Parser Done parser.rs - parse_match_expr, parse_match_arm, etc.
HIR Done body.rs - Expr::Match, MatchArm, Pattern variants
AST helpers Done ast.rs

Type Checking

Feature Status Location
Pattern variable binding Done lib.rs:781-785 - ctx.define(name, narrowed_ty)
Type narrowing Done lib.rs:834-855 - extract_pattern_binding returns narrowed type
Exhaustiveness checking Done lib.rs:1011-1121 - check_match_exhaustiveness
Unreachable arm detection Done Same function, detects arms after catch-all

Phase 3: Code Generation

Feature Status Location
instanceof codegen Done compiler.rs:913-943 - compile_match_pattern emits CmpOp::InstanceOf
Pattern binding Done compiler.rs:1047-1061 - bind_pattern_variable
Guard handling Done compiler.rs:518-535
If-else desugaring Done Full match-to-if-else chain implemented

Tests (PARTIAL)

Test Type Status Location
VM integration tests Done match_expr.rs - 20+ tests covering bindings, literals, typed patterns, guards
Exhaustiveness tests Done match_exhaustiveness/

What's Next

Type System Improvements

1. Type Alias Expansion
Current: Type aliases like type Result = Success | Failure are treated as opaque Ty::Named("Result").
Required: Expand type aliases to their definitions for proper union exhaustiveness checking.

Without this, exhaustiveness checking doesn't work for type alias unions.

2. Enum Variant Exhaustiveness
Current: Enum variant patterns (Status.Active) are treated as literals, not contributing to exhaustiveness.

Required: Track which enum variants are covered and error if variants are missing.

enum Status { Active, Inactive, Pending }
match (s) {
  Status.Active => "active"
  // ERROR: Inactive and Pending not handled
}

3. Literal Type Exhaustiveness
Current: Literal patterns don't contribute to type-level exhaustiveness.

Required: For literal union types (200 | 201 | 204), track which values are covered.

Refinements

1. Overlapping Pattern Verification
The BEP says this should work (second arm only matches B, not unreachable):

match (x) {
  _: A => "a"
  _: A | B => "ab"  // Should NOT be flagged as unreachable
}

Status: Likely works, but needs explicit test coverage.

2. Better Error Spans
Current: Error spans point to the match expression, not the specific arm.

Required: Point to the specific arm that's unreachable or the missing cases.

…f checks in the compiler. Add support for pattern matching, including typed bindings, literals, and unions. Enhance the handling of pattern variables and guards within match arms.
…ing typed bindings, literals, and unions. Add methods for binding pattern variables and extracting type names for instanceof checks.
…luding match arms, typed bindings, literals, and unions. Implement methods for lowering match expressions and patterns from CST to HIR, enhancing the compiler's pattern matching capabilities.
…ms and guards. Implement methods for parsing match patterns and elements, enhancing the parser's capabilities for the new Match token.
…associated methods for handling match expressions and patterns. Enhance the syntax tree with functionality for scrutinee extraction, arm iteration, and pattern analysis, including union and typed bindings.
…, arms, patterns, and guards in the syntax kind enum.
…nd pattern coverage analysis. enhanced the `infer_expr` function to handle match arms and more
…sions. furthered exhaustiveness checking and unreachable arm detection in match statements.
…pattern handling with typed bindings, literals, and unions. Update error formatting for non-exhaustive matches and unreachable arms.
@vercel
Copy link

vercel bot commented Dec 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
promptfiddle Ready Ready Preview, Comment Dec 17, 2025 9:47pm

@github-actions
Copy link

github-actions bot commented Dec 17, 2025

Latest build completeView logs

@github-actions
Copy link

🐑 BEPs Preview Ready

Preview URL: https://dj7ggjkp4tlhz.cloudfront.net/paulo-match/

Commit: f2f902ffdbed401156175e021d12c5893400036cWorkflow run

@rossirpaulo rossirpaulo marked this pull request as draft December 17, 2025 19:25
@codspeed-hq
Copy link

codspeed-hq bot commented Dec 17, 2025

CodSpeed Performance Report

Merging #2828 will not alter performance

Comparing paulo/match (f2f902f) with canary (54559e1)

Summary

✅ 15 untouched
⏩ 14 skipped1

Footnotes

  1. 14 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some of these tests to baml_codegen/tests/ as well?

Comment on lines +820 to +824
/// Lower a match expression from CST to HIR.
///
/// MATCH_EXPR structure (from parser):
/// - Scrutinee expression (could be a PAREN_EXPR wrapping the actual expr, or a literal token)
/// - One or more MATCH_ARM nodes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I would add AST accessors to make lowering higher level (pun intended), not direct syntax nodes access. See this comment in PR #2838

Comment on lines +897 to +904
/// Lower a single match arm from CST to HIR.
///
/// MATCH_ARM structure (from parser):
/// - MATCH_PATTERN node
/// - Optional MATCH_GUARD node (contains 'if' keyword + expression)
/// - FAT_ARROW token ('=>')
/// - Body expression (BLOCK_EXPR or other expression, or literal token)
fn lower_match_arm(&mut self, node: &baml_syntax::SyntaxNode) -> MatchArm {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, I'd add AST accessors.

Comment on lines +992 to +1004
/// Lower a match pattern from CST to HIR.
///
/// MATCH_PATTERN structure (from parser):
/// - Pattern elements (identifiers, literals, type expressions)
/// - Optional PIPE tokens for union patterns
///
/// Pattern forms:
/// - Binding: `x`, `_`
/// - Typed binding: `s: Success`
/// - Literal: `null`, `true`, `42`, `"hello"`
/// - Enum variant: `Status.Active`
/// - Union: `200 | 201` or `Status.Active | Status.Pending`
fn lower_match_pattern(&mut self, node: &baml_syntax::SyntaxNode) -> PatId {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CST -> AST -> HIR

@antoniosarosi
Copy link
Contributor

I think this is no longer necessary, we merged match-3 branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants