@@ -25,23 +25,34 @@ struct SwiftContext {
2525 /// by the outer `function_parameter` rule; read by the `parameter`
2626 /// rules.
2727 default_value : Option < yeast:: Id > ,
28- /// Translated outer modifiers (e.g. visibility, attributes) to
29- /// attach to each child of a flattening outer rule. Set by
30- /// `property_declaration`, `enum_entry`, and
31- /// `protocol_property_declaration`.
28+ /// Translated outer modifiers to attach to each child of a flattening
29+ /// outer rule. Set by `property_declaration`, `binding_pattern`,
30+ /// `enum_entry`, and `protocol_property_declaration`. For `let`/`var`
31+ /// declarations and `binding_pattern`s the list is led by the binding
32+ /// modifier, which also serves as the "this is a binding" signal for
33+ /// pattern translation (see `in_binding_pattern`).
3234 outer_modifiers : Vec < yeast:: Id > ,
33- /// The `let`/`var` binding modifier for a `property_declaration`.
34- /// Set by `property_declaration`; read by the inner declaration
35- /// rules (`property_binding` variants, accessor rules) so they
36- /// emit it as part of the output node's `modifier:` field.
37- binding_modifier : Option < yeast:: Id > ,
3835 /// True when the current child of a flattening outer rule is not
3936 /// the first one — its inner rule should emit a
4037 /// `chained_declaration` modifier so the original grouping can be
4138 /// recovered downstream.
4239 is_chained : bool ,
4340}
4441
42+ impl SwiftContext {
43+ /// Whether the pattern currently being translated is a binding
44+ /// (the LHS of a `let`/`var` declaration or a `binding_pattern`).
45+ ///
46+ /// True exactly when an enclosing binding has published its modifier into
47+ /// `outer_modifiers`. This is reliable because non-binding subtrees
48+ /// (bodies, initializer values, ...) are translated with a reset context
49+ /// (see `BuildCtx::translate_reset`), so a bare identifier only sees a
50+ /// non-empty `outer_modifiers` when it really is a binding.
51+ fn in_binding_pattern ( & self ) -> bool {
52+ !self . outer_modifiers . is_empty ( )
53+ }
54+ }
55+
4556/// Build a freshly-created `chained_declaration` modifier node if
4657/// `ctx.is_chained`, else `None`. Used by inner declaration rules to
4758/// emit the chained tag for non-first children of a flattening outer
@@ -220,16 +231,15 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
220231 ( property_binding
221232 name: ( pattern bound_identifier: @name)
222233 type : _? @ty
223- computed_value: ( computed_property statement: _* @body) )
234+ computed_value: ( computed_property statement: _* @@ body) )
224235 =>
225236 ( accessor_declaration
226- modifier: { ctx. binding_modifier}
227237 modifier: { ctx. outer_modifiers. clone( ) }
228238 modifier: { chained_modifier( & mut ctx) }
229239 name: ( identifier #{ name} )
230240 type : { ty}
231241 accessor_kind: ( accessor_kind "get" )
232- body: ( block stmt: { body} ) )
242+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
233243 ) ,
234244 // Stored property with willSet/didSet observers (initializer
235245 // optional) → a `variable_declaration` followed by one
@@ -246,13 +256,19 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
246256 ( property_binding
247257 name: ( pattern bound_identifier: @name)
248258 type : _? @ty
249- value: _? @val
259+ value: _? @@ val
250260 observers: ( willset_didset_block willset: _? @@ws didset: _? @@ds) )
251261 =>
252262 { {
263+ // The initializer value must not inherit the binding context
264+ // (it may contain patterns, e.g. a switch expression), so
265+ // translate it with a reset context. The observers keep the
266+ // context: each willSet/didSet accessor emits the binding
267+ // modifier and resets its own body.
268+ let val = ctx. translate_reset( val) ?;
269+
253270 let var_decl = tree!(
254271 ( variable_declaration
255- modifier: { ctx. binding_modifier}
256272 modifier: { ctx. outer_modifiers. clone( ) }
257273 modifier: { chained_modifier( & mut ctx) }
258274 pattern: ( name_pattern identifier: ( identifier #{ name} ) )
@@ -275,19 +291,23 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
275291 ) ,
276292 // property_binding with any pattern name (identifier or
277293 // destructuring). Reads outer modifiers / chained tag from `ctx`.
294+ //
295+ // The enclosing `property_declaration` leads `ctx.outer_modifiers`
296+ // with the `let`/`var` binding modifier, so the auto-translated name
297+ // pattern (the LHS) becomes a binding, while the initializer value is
298+ // translated with a reset context (see `translate_reset`).
278299 rule!(
279300 ( property_binding
280301 name: @pattern
281302 type : _? @ty
282- value: _? @val)
303+ value: _? @@ val)
283304 =>
284305 ( variable_declaration
285- modifier: { ctx. binding_modifier}
286306 modifier: { ctx. outer_modifiers. clone( ) }
287307 modifier: { chained_modifier( & mut ctx) }
288308 pattern: { pattern}
289309 type : { ty}
290- value: { val} )
310+ value: { ctx . translate_reset ( val) ? } ) // reset context: the initializer must not see the binding
291311 ) ,
292312 // property_declaration: flatten declarators (each may translate
293313 // to multiple nodes — variable_declaration and/or
@@ -307,8 +327,11 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
307327 =>
308328 { {
309329 let binding_text = ctx. ast. source_text( binding_kind) ;
310- ctx. binding_modifier = Some ( ctx. literal( "modifier" , & binding_text) ) ;
311- ctx. outer_modifiers = mods;
330+ let binding = ctx. literal( "modifier" , & binding_text) ;
331+ // The `let`/`var` binding modifier leads the declaration's
332+ // modifier list and doubles as the "this is a binding" signal
333+ // for pattern translation (see `in_binding_pattern`).
334+ ctx. outer_modifiers = std:: iter:: once( binding) . chain( mods) . collect( ) ;
312335
313336 let mut result = Vec :: new( ) ;
314337 for ( i, decl) in decls. into_iter( ) . enumerate( ) {
@@ -403,14 +426,23 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
403426 rule!( ( type name: @inner) => { inner} ) ,
404427 // `directly_assignable_expression` is just a wrapper; unwrap it
405428 rule!( ( directly_assignable_expression expr: @inner) => { inner} ) ,
406- // Pattern with bound_identifier → name_pattern
407- rule!( ( pattern bound_identifier: @name) => ( name_pattern identifier: ( identifier #{ name} ) ) ) ,
408- // Pattern with 'let' or 'var' binding: extract the inner pattern
409- // TODO: Names in a pattern need to be translated to expr_equality_pattern if not under a 'var/let' but we lack a way to pass down context to do this.
429+ // Pattern with bound_identifier → name_pattern.
430+ rule!(
431+ ( pattern bound_identifier: @name)
432+ =>
433+ ( name_pattern identifier: ( identifier #{ name} ) )
434+ ) ,
435+ // Pattern with 'let' or 'var' binding: publish the binding modifier
436+ // into `ctx` and translate the inner pattern under it.
410437 rule!(
411- ( pattern kind: ( binding_pattern binding: _? pattern: @pattern) )
438+ ( pattern kind: ( binding_pattern binding: ( value_binding_pattern mutability : @@binding_kind ) pattern: @ @pattern) )
412439 =>
413- { pattern}
440+ { {
441+ let binding_text = ctx. ast. source_text( binding_kind) ;
442+ let binding = ctx. literal( "modifier" , & binding_text) ;
443+ ctx. outer_modifiers = vec![ binding] ;
444+ ctx. translate( pattern) ?
445+ } }
414446 ) ,
415447 // case T.foo(x,y) pattern
416448 rule!(
@@ -436,6 +468,22 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
436468 rule!( ( pattern kind: ( type_casting_pattern) ) => ( unsupported_node) ) ,
437469 // Wildcard pattern
438470 rule!( ( pattern kind: ( wildcard_pattern) ) => ( ignore_pattern) ) ,
471+ // A bare identifier used as an expression-pattern. Under a `var`/`let`
472+ // binding it introduces a new variable and becomes a `name_pattern`;
473+ // otherwise it matches by equality and is left as an `expr_equality_pattern`
474+ // over the name expression.
475+ rule!(
476+ ( pattern kind: ( simple_identifier) @name)
477+ =>
478+ {
479+ if ctx. in_binding_pattern( ) {
480+ tree!( ( name_pattern identifier: ( identifier #{ name} ) ) )
481+ } else {
482+ let expr = tree!( ( name_expr identifier: ( identifier #{ name} ) ) ) ;
483+ tree!( ( expr_equality_pattern expr: { expr} ) )
484+ }
485+ }
486+ ) ,
439487 // Expression pattern
440488 // We lack a way to check if 'expr' is actually an expression, but due to rule ordering
441489 // the 'expression' case is the only remaining possibility when this rule tries to match.
@@ -1062,56 +1110,52 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10621110 // and binding/outer modifiers + chained tag from the outer
10631111 // property_declaration rule.
10641112 rule!(
1065- ( computed_getter body: ( block statement: _* @body) ?)
1113+ ( computed_getter body: ( block statement: _* @@ body) ?)
10661114 =>
10671115 ( accessor_declaration
1068- modifier: { ctx. binding_modifier}
10691116 modifier: { ctx. outer_modifiers. clone( ) }
10701117 modifier: { chained_modifier( & mut ctx) }
10711118 name: { ctx. property_name. ok_or( "computed_getter outside property_binding context" ) ?}
10721119 type : { ctx. property_type}
10731120 accessor_kind: ( accessor_kind "get" )
1074- body: ( block stmt: { body} ) )
1121+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
10751122 ) ,
10761123 // Computed setter with explicit parameter name.
10771124 rule!(
1078- ( computed_setter parameter: @param body: ( block statement: _* @body) )
1125+ ( computed_setter parameter: @param body: ( block statement: _* @@ body) )
10791126 =>
10801127 ( accessor_declaration
1081- modifier: { ctx. binding_modifier}
10821128 modifier: { ctx. outer_modifiers. clone( ) }
10831129 modifier: { chained_modifier( & mut ctx) }
10841130 name: { ctx. property_name. ok_or( "computed_setter outside property_binding context" ) ?}
10851131 type : { ctx. property_type}
10861132 accessor_kind: ( accessor_kind "set" )
10871133 parameter: ( parameter pattern: ( name_pattern identifier: ( identifier #{ param} ) ) )
1088- body: ( block stmt: { body} ) )
1134+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
10891135 ) ,
10901136 // Computed setter without explicit parameter name; body optional.
10911137 rule!(
1092- ( computed_setter body: ( block statement: _* @body) ?)
1138+ ( computed_setter body: ( block statement: _* @@ body) ?)
10931139 =>
10941140 ( accessor_declaration
1095- modifier: { ctx. binding_modifier}
10961141 modifier: { ctx. outer_modifiers. clone( ) }
10971142 modifier: { chained_modifier( & mut ctx) }
10981143 name: { ctx. property_name. ok_or( "computed_setter outside property_binding context" ) ?}
10991144 type : { ctx. property_type}
11001145 accessor_kind: ( accessor_kind "set" )
1101- body: ( block stmt: { body} ) )
1146+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
11021147 ) ,
11031148 // Computed modify → accessor_declaration
11041149 rule!(
1105- ( computed_modify body: ( block statement: _* @body) )
1150+ ( computed_modify body: ( block statement: _* @@ body) )
11061151 =>
11071152 ( accessor_declaration
1108- modifier: { ctx. binding_modifier}
11091153 modifier: { ctx. outer_modifiers. clone( ) }
11101154 modifier: { chained_modifier( & mut ctx) }
11111155 name: { ctx. property_name. ok_or( "computed_modify outside property_binding context" ) ?}
11121156 type : { ctx. property_type}
11131157 accessor_kind: ( accessor_kind "modify" )
1114- body: ( block stmt: { body} ) )
1158+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
11151159 ) ,
11161160 // willset/didset block — spread to children (only reachable as a
11171161 // fallback; the outer property_binding manual rule normally
@@ -1122,27 +1166,25 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
11221166 // binding/outer modifiers + chained tag from the outer
11231167 // property_declaration rule.
11241168 rule!(
1125- ( willset_clause body: ( block statement: _* @body) ?)
1169+ ( willset_clause body: ( block statement: _* @@ body) ?)
11261170 =>
11271171 ( accessor_declaration
1128- modifier: { ctx. binding_modifier}
11291172 modifier: { ctx. outer_modifiers. clone( ) }
11301173 modifier: { chained_modifier( & mut ctx) }
11311174 name: { ctx. property_name. ok_or( "willset_clause outside property_binding context" ) ?}
11321175 accessor_kind: ( accessor_kind "willSet" )
1133- body: ( block stmt: { body} ) )
1176+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
11341177 ) ,
11351178 // didset clause → accessor_declaration (body optional).
11361179 rule!(
1137- ( didset_clause body: ( block statement: _* @body) ?)
1180+ ( didset_clause body: ( block statement: _* @@ body) ?)
11381181 =>
11391182 ( accessor_declaration
1140- modifier: { ctx. binding_modifier}
11411183 modifier: { ctx. outer_modifiers. clone( ) }
11421184 modifier: { chained_modifier( & mut ctx) }
11431185 name: { ctx. property_name. ok_or( "didset_clause outside property_binding context" ) ?}
11441186 accessor_kind: ( accessor_kind "didSet" )
1145- body: ( block stmt: { body} ) )
1187+ body: ( block stmt: { ctx . translate_reset ( body) ? } ) )
11461188 ) ,
11471189 // Preprocessor conditionals — unsupported
11481190 rule!( ( diagnostic) => ( unsupported_node) ) ,
0 commit comments