From cbe4c81ca665617342fd209bdecdea41e7008bb5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 11 May 2026 14:39:29 +0200 Subject: [PATCH] Unified: add tuple_pattern and sequence_condition; refine if-let/guard mapping ast_types.yml additions: - tuple_pattern { element*: pattern } in the pattern supertype. - sequence_condition { stmt*: stmt, condition: condition } in the condition supertype. swift.rs: - Map Swift tuple destructuring (e.g. `let (a, b) = pair`) to the new tuple_pattern instead of synthesizing an apply_pattern. - if-let / guard-let: explicitly match the value_binding_pattern (the `let` keyword) and bind the source expression as the next condition child, so `let` no longer leaks into the output. --- unified/extractor/ast_types.yml | 8 ++++++ .../extractor/src/languages/swift/swift.rs | 25 +++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/unified/extractor/ast_types.yml b/unified/extractor/ast_types.yml index a04e1d38e95..7ed6f9cf854 100644 --- a/unified/extractor/ast_types.yml +++ b/unified/extractor/ast_types.yml @@ -18,6 +18,7 @@ supertypes: condition: - expr_condition - let_pattern_condition + - sequence_condition - unsupported_node pattern: - var_pattern @@ -92,6 +93,13 @@ named: expr_condition: expr: expr + # A series of statements that are executed before evaluating the trailing condition. + # Useful for languages where a conditional clause may be preceded by side-effecting + # syntactic elements (e.g. binding clauses) that don't themselves form a condition. + sequence_condition: + stmt*: stmt + condition: condition + # Evaluate 'expr' and match its result against 'pattern', and return true if it matches. # Variables bound by the pattern will be in scope within the 'true' branch controlled by this condition. let_pattern_condition: diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 9a7d18c8321..47bfe437ef2 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -157,29 +157,33 @@ fn translation_rules() -> Vec { ), // ---- Guard statement ---- // `guard let x = e else { ... }` — currently only handles the - // let-binding form, since plain `guard cond else { ... }` is not - // exercised by any existing corpus test. + // let-binding form. The Swift parser models the `let` keyword as a + // `value_binding_pattern` child of `condition`, followed by an + // unnamed `=` and the source expression. rule!( (guard_statement bound_identifier: (simple_identifier) @id - condition: (_)* @cond_children + condition: (value_binding_pattern) + condition: (_) @value (else) (statements) @else_branch) => (guard_if_stmt condition: (let_pattern_condition pattern: (var_pattern identifier: (identifier #{id})) - value: {*cond_children.last().unwrap()}) + value: {value}) else: {else_branch}) ), // ---- If statement ---- // if-let binding (with optional else branch). The Swift parser puts - // the bound name in `bound_identifier` and the source expression as - // the last child of the multi-child `condition` field. + // the bound name in `bound_identifier`, the `let` keyword as a + // `value_binding_pattern` child of `condition`, and the source + // expression as a separate child of `condition`. rule!( (if_statement bound_identifier: (simple_identifier) @id - condition: (_)* @cond_children + condition: (value_binding_pattern) + condition: (_) @value (statements) @then (else) (_) @else_branch) @@ -187,20 +191,21 @@ fn translation_rules() -> Vec { (if_stmt condition: (let_pattern_condition pattern: (var_pattern identifier: (identifier #{id})) - value: {*cond_children.last().unwrap()}) + value: {value}) then: {then} else: {else_branch}) ), rule!( (if_statement bound_identifier: (simple_identifier) @id - condition: (_)* @cond_children + condition: (value_binding_pattern) + condition: (_) @value (statements) @then) => (if_stmt condition: (let_pattern_condition pattern: (var_pattern identifier: (identifier #{id})) - value: {*cond_children.last().unwrap()}) + value: {value}) then: {then}) ), // With explicit else branch (block or chained if).