Add value-returning match expressions

This commit is contained in:
pavel 2026-08-27 17:56:13 +02:00
commit ab783c33ed
12 changed files with 384 additions and 14 deletions

View file

@ -793,6 +793,68 @@ func (p *parser) parseMatch() (Stmt, error) {
return MatchStmt{Value: value, Cases: cases}, nil
}
func (p *parser) parseMatchExpr() (Expr, error) {
if _, err := p.expect(tokenLParen, "expected '(' after match"); err != nil {
return nil, err
}
value, err := p.parseExpr(0)
if err != nil {
return nil, err
}
if _, err := p.expect(tokenRParen, "expected ')' after match value"); err != nil {
return nil, err
}
if _, err := p.expect(tokenLBrace, "expected '{' after match value"); err != nil {
return nil, err
}
var cases []MatchExprCase
for !p.check(tokenRBrace) && !p.check(tokenEOF) {
enumName, err := p.expect(tokenIdent, "expected enum name in match case")
if err != nil {
return nil, err
}
if _, err := p.expect(tokenDoubleColon, "expected '::' in match case"); err != nil {
return nil, err
}
variant, err := p.expect(tokenIdent, "expected variant name")
if err != nil {
return nil, err
}
var bindings []string
if p.match(tokenLParen) {
if !p.check(tokenRParen) {
for {
binding, err := p.expect(tokenIdent, "expected variant binding")
if err != nil {
return nil, err
}
bindings = append(bindings, binding.lexeme)
if !p.match(tokenComma) {
break
}
}
}
if _, err := p.expect(tokenRParen, "expected ')' after variant bindings"); err != nil {
return nil, err
}
}
if _, err := p.expect(tokenArrow, "expected '->' after match pattern"); err != nil {
return nil, err
}
result, err := p.parseExpr(0)
if err != nil {
return nil, err
}
cases = append(cases, MatchExprCase{EnumName: enumName.lexeme, VariantName: variant.lexeme, Bindings: bindings, Value: result})
p.match(tokenComma)
p.match(tokenSemicolon)
}
if _, err := p.expect(tokenRBrace, "expected '}' after match"); err != nil {
return nil, err
}
return MatchExpr{Value: value, Cases: cases}, nil
}
func (p *parser) parseSelect() (Stmt, error) {
if _, err := p.expect(tokenLBrace, "expected '{' after select"); err != nil {
return nil, err
@ -1016,6 +1078,8 @@ func (p *parser) parsePrefix() (Expr, error) {
return p.parsePostfix(expr)
case tokenLBrace:
return p.parseLambdaExpr()
case tokenMatch:
return p.parseMatchExpr()
case tokenBang, tokenMinus, tokenAmp, tokenStar:
value, err := p.parseExpr(7)
if err != nil {