Skip to content

Commit a966dff

Browse files
committed
Unified: Add more patterns and some fixes to the AST
1 parent 6b58482 commit a966dff

5 files changed

Lines changed: 266 additions & 43 deletions

File tree

unified/extractor/ast_types.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ supertypes:
99
- unsupported_node
1010
stmt:
1111
- empty_stmt
12+
- block_stmt
13+
- expr_stmt
1214
- if_stmt
1315
- variable_declaration_stmt
1416
- guard_if_stmt
@@ -105,7 +107,7 @@ named:
105107
# A pattern such as `Some(x)` where `Some` is the constructor and `x` is an argument
106108
apply_pattern:
107109
constructor: expr
108-
argument*: expr
110+
argument*: pattern
109111

110112
# An simple unqualified identifier token
111113
identifier:

unified/extractor/src/languages/swift/swift.rs

Lines changed: 124 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,99 @@ fn translation_rules() -> Vec<yeast::Rule> {
133133
(line_string_literal) @lit
134134
=>
135135
(string_literal #{lit})
136+
), // ---- Lambdas / closures ----
137+
// Map a `lambda_literal` whose body is a single statement to
138+
// `lambda_expr`. Multi-statement bodies fall through to
139+
// `unsupported_node` because `lambda_expr.body` is single-valued
140+
// in the current `ast_types.yml`. Parameters from explicit-typed
141+
// closures (`{ (x: Int) -> Int in ... }`) are not yet captured.
142+
rule!(
143+
(lambda_literal
144+
(statements (_) @body))
145+
=>
146+
(lambda_expr
147+
body: {body})
148+
),
149+
// ---- Block / statement wrapping ----
150+
// A `(statements ...)` node corresponds to a brace-delimited block.
151+
// Each child is mapped through translation; bare expression results
152+
// get wrapped in `expr_stmt`.
153+
rule!(
154+
(statements (_)* @stmts)
155+
=>
156+
(block_stmt body: {..stmts})
157+
),
158+
// ---- Guard statement ----
159+
// `guard let x = e else { ... }` — currently only handles the
160+
// let-binding form, since plain `guard cond else { ... }` is not
161+
// exercised by any existing corpus test.
162+
rule!(
163+
(guard_statement
164+
bound_identifier: (simple_identifier) @id
165+
condition: (_)* @cond_children
166+
(else)
167+
(statements) @else_branch)
168+
=>
169+
(guard_if_stmt
170+
condition: (let_pattern_condition
171+
pattern: (var_pattern identifier: (identifier #{id}))
172+
value: {*cond_children.last().unwrap()})
173+
else: {else_branch})
174+
),
175+
// ---- If statement ----
176+
// if-let binding (with optional else branch). The Swift parser puts
177+
// the bound name in `bound_identifier` and the source expression as
178+
// the last child of the multi-child `condition` field.
179+
rule!(
180+
(if_statement
181+
bound_identifier: (simple_identifier) @id
182+
condition: (_)* @cond_children
183+
(statements) @then
184+
(else)
185+
(_) @else_branch)
186+
=>
187+
(if_stmt
188+
condition: (let_pattern_condition
189+
pattern: (var_pattern identifier: (identifier #{id}))
190+
value: {*cond_children.last().unwrap()})
191+
then: {then}
192+
else: {else_branch})
193+
),
194+
rule!(
195+
(if_statement
196+
bound_identifier: (simple_identifier) @id
197+
condition: (_)* @cond_children
198+
(statements) @then)
199+
=>
200+
(if_stmt
201+
condition: (let_pattern_condition
202+
pattern: (var_pattern identifier: (identifier #{id}))
203+
value: {*cond_children.last().unwrap()})
204+
then: {then})
136205
),
137-
// ---- Patterns ----
206+
// With explicit else branch (block or chained if).
207+
rule!(
208+
(if_statement
209+
condition: (_) @cond
210+
(statements) @then
211+
(else)
212+
(_) @else_branch)
213+
=>
214+
(if_stmt
215+
condition: (expr_condition expr: {cond})
216+
then: {then}
217+
else: {else_branch})
218+
),
219+
// Without else branch.
220+
rule!(
221+
(if_statement
222+
condition: (_) @cond
223+
(statements) @then)
224+
=>
225+
(if_stmt
226+
condition: (expr_condition expr: {cond})
227+
then: {then})
228+
), // ---- Patterns ----
138229
// The Swift parser uses a `pattern` node with a `bound_identifier`
139230
// field for simple bindings such as `let x = ...`.
140231
rule!(
@@ -143,26 +234,45 @@ fn translation_rules() -> Vec<yeast::Rule> {
143234
(var_pattern
144235
identifier: (identifier #{id}))
145236
),
146-
// ---- Variable declarations ----
147-
// `let x = e` / `var x = e` (with initializer).
237+
// Inside tuple patterns, the inner `pattern` node holds a bare
238+
// `simple_identifier` (with no `bound_identifier` field).
148239
rule!(
149-
(property_declaration
150-
name: (_) @pat
151-
value: (_) @value)
240+
(pattern (simple_identifier) @id)
152241
=>
153-
(variable_declaration_stmt
154-
variable_declarator: (variable_declarator
155-
pattern: {pat}
156-
value: {value}))
242+
(var_pattern
243+
identifier: (identifier #{id}))
157244
),
158-
// `var x: T` (no initializer).
245+
// Tuple destructuring pattern, e.g. `let (a, b) = pair`. The parser
246+
// emits a `pattern` node whose unnamed children are themselves
247+
// `pattern` nodes. We synthesize a `tuple` constructor since the
248+
// syntax has no name.
249+
rule!(
250+
(pattern (pattern)+ @parts)
251+
=>
252+
(apply_pattern
253+
constructor: (name_expr identifier: (identifier "tuple"))
254+
argument: {..parts})
255+
),
256+
// ---- Variable declarations ----
257+
// Handles single (`let x = e`), multiple (`let x = 1, y = 2`),
258+
// and uninitialized (`var x: T`) bindings.
159259
rule!(
160260
(property_declaration
161-
name: (_) @pat)
261+
name: (_)* @pats
262+
value: (_)* @vals)
162263
=>
163264
(variable_declaration_stmt
164-
variable_declarator: (variable_declarator
165-
pattern: {pat}))
265+
variable_declarator: {..pats.iter().enumerate().map(|(i, &pat)| {
266+
match vals.get(i).copied() {
267+
Some(val) => yeast::tree!(
268+
(variable_declarator
269+
pattern: {pat}
270+
value: {val})),
271+
None => yeast::tree!(
272+
(variable_declarator
273+
pattern: {pat})),
274+
}
275+
})})
166276
),
167277
// ---- Fallbacks ----
168278
rule!(

unified/extractor/tests/corpus/swift/closures.txt

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
Closure with explicit parameters
33
===
44

5-
// TODO: map lambda_literal -> lambda_expr
65
let f = { (x: Int) -> Int in x * 2 }
76

87
---
98

109
source_file
11-
comment "// TODO: map lambda_literal -> lambda_expr"
1210
property_declaration
1311
name:
1412
pattern
@@ -38,11 +36,18 @@ source_file
3836

3937
top_level
4038
body:
41-
unsupported_node "// TODO: map lambda_literal -> lambda_expr"
4239
variable_declaration_stmt
4340
variable_declarator:
4441
variable_declarator
45-
value: unsupported_node "{ (x: Int) -> Int in x * 2 }"
42+
value:
43+
lambda_expr
44+
body:
45+
binary_expr
46+
operator: operator "*"
47+
left:
48+
name_expr
49+
identifier: identifier "x"
50+
right: int_literal "2"
4651
pattern:
4752
var_pattern
4853
identifier: identifier "f"
@@ -77,7 +82,17 @@ top_level
7782
variable_declaration_stmt
7883
variable_declarator:
7984
variable_declarator
80-
value: unsupported_node "{ $0 + $1 }"
85+
value:
86+
lambda_expr
87+
body:
88+
binary_expr
89+
operator: operator "+"
90+
left:
91+
name_expr
92+
identifier: identifier "$0"
93+
right:
94+
name_expr
95+
identifier: identifier "$1"
8196
pattern:
8297
var_pattern
8398
identifier: identifier "f"
@@ -151,7 +166,9 @@ top_level
151166
variable_declaration_stmt
152167
variable_declarator:
153168
variable_declarator
154-
value: unsupported_node "{ [weak self] in self?.doThing() }"
169+
value:
170+
lambda_expr
171+
body: unsupported_node "self?.doThing()"
155172
pattern:
156173
var_pattern
157174
identifier: identifier "f"
@@ -213,7 +230,22 @@ top_level
213230
variable_declaration_stmt
214231
variable_declarator:
215232
variable_declarator
216-
value: unsupported_node "{ (x: Int) -> Int in\n let y = x + 1\n return y * 2\n}"
233+
value:
234+
lambda_expr
235+
body:
236+
variable_declaration_stmt
237+
variable_declarator:
238+
variable_declarator
239+
value:
240+
binary_expr
241+
operator: operator "+"
242+
left:
243+
name_expr
244+
identifier: identifier "x"
245+
right: int_literal "1"
246+
pattern:
247+
var_pattern
248+
identifier: identifier "y"
217249
pattern:
218250
var_pattern
219251
identifier: identifier "f"

0 commit comments

Comments
 (0)