feat: struct and tuple patterns in match (bootstrap + selfhost)

Support destructuring in match arms:
- Tuple: (a, b) binds subject._0 / _1
- Struct: Point { x: px, y: py } and shorthand Point { x, y }

Bootstrap: matchPatternBindings for pkTuple/pkStruct; register local
tuple typedefs from function bodies. Selfhost: parse, Sema_BindPattern,
Lcx_PatternBindings with scope defines. Fix operator-overload path that
crashed when typeName was null after pattern binds.

Example: examples/struct_tuple_pat.bux. Selfhost-loop IDENTICAL.
This commit is contained in:
2026-07-18 01:15:44 +03:00
parent eac78f28c1
commit e3ca724bfa
12 changed files with 494 additions and 16 deletions
+7 -3
View File
@@ -324,7 +324,7 @@ proc parsePrimaryPattern(p: var Parser): Pattern =
return Pattern(kind: pkEnum, loc: loc, patEnumPath: path, patEnumArgs: args, patEnumNamed: named)
return Pattern(kind: pkEnum, loc: loc, patEnumPath: path, patEnumArgs: @[], patEnumNamed: @[])
elif p.check(tkLBrace):
# Struct pattern: Point { x: 0, y: 0 }
# Struct pattern: Point { x: px, y: py } or shorthand Point { x, y }
discard p.advance()
var fields: seq[tuple[name: string, pattern: Pattern]] = @[]
while not p.check(tkRBrace) and not p.isAtEnd:
@@ -333,8 +333,12 @@ proc parsePrimaryPattern(p: var Parser): Pattern =
if p.check(tkRBrace) or p.isAtEnd:
break
let fieldName = p.expect(tkIdent, "expected field name in struct pattern").text
discard p.expect(tkColon, "expected ':' after field name in pattern")
fields.add((fieldName, p.parsePattern()))
if p.check(tkColon):
discard p.advance()
fields.add((fieldName, p.parsePattern()))
else:
# Shorthand: { x } means { x: x }
fields.add((fieldName, Pattern(kind: pkIdent, loc: loc, patIdent: fieldName)))
if p.check(tkComma):
discard p.advance()
discard p.expect(tkRBrace, "expected '}' to close struct pattern")