@@ -38,6 +38,9 @@ struct SwiftContext {
3838 /// True while translating a pattern. Optional chaining in this context is
3939 /// represented as an `Optional.some` call rather than being unwrapped.
4040 in_pattern : bool ,
41+ /// True when a conditional compilation block should be translated into an
42+ /// if expression.
43+ conditional_compilation_as_expr : bool ,
4144 /// When iterating over the clauses of a conditional compilation block, this
4245 /// holds the tail of the clauses that have already been translated.
4346 conditional_compilation_tail : Option < yeast:: OutputId > ,
@@ -67,29 +70,11 @@ fn implicit_parameterless_initializer(
6770 ctx : & mut yeast:: build:: BuildCtx < ' _ , SwiftContext > ,
6871 members : & [ yeast:: OutputId ] ,
6972) -> Option < yeast:: OutputId > {
70- // Search for an initializer while recursing into nodes for conditional
71- // compilation blocks.
72- fn find_initializer ( ast : & yeast:: OutputAst , id : yeast:: OutputId ) -> Option < yeast:: OutputId > {
73- let node = ast. get_node ( id) ?;
74- match node. kind_name ( ) {
75- "constructor_declaration" => Some ( id) ,
76- name => {
77- let fields: & [ & str ] = match name {
78- "if_expr" => & [ "then" , "else" ] , // look into conditional compilation
79- "block" => & [ "stmt" ] , // look into blocks in branches
80- _ => & [ ] ,
81- } ;
82- fields. iter ( ) . find_map ( |field| {
83- node. field_children ( ast. field_id_for_name ( field) ?)
84- . iter ( )
85- . find_map ( |child| find_initializer ( ast, * child) )
86- } )
87- }
88- }
89- }
90- let has_explicit_initializer = members
91- . iter ( )
92- . any ( |member| find_initializer ( ctx. output , * member) . is_some ( ) ) ;
73+ let has_explicit_initializer = members. iter ( ) . any ( |member| {
74+ ctx. output
75+ . get_node ( * member)
76+ . is_some_and ( |node| node. kind_name ( ) == "constructor_declaration" )
77+ } ) ;
9378 ( !has_explicit_initializer) . then ( || {
9479 tree ! ( ( constructor_declaration
9580 modifier: ( modifier "generated" )
@@ -174,6 +159,14 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
174159 // but a single wrapped `variableDecl` can translate to *several*
175160 // declarations (`let x = 1, y = 2`), so the wrapped node is captured with
176161 // `_*` and the result annotated `stmt*` to splice all of them.
162+ rule!(
163+ ( codeBlockItem item: ( ifConfigDecl) @@item)
164+ =>
165+ stmt* {
166+ ctx. conditional_compilation_as_expr = true ;
167+ ctx. translate( item) ?
168+ }
169+ ) ,
177170 rule!( ( codeBlockItem item: _* @item) => stmt* { item } ) ,
178171 // ---- Literals ----
179172 // swift-syntax does not distinguish the lexical integer/string forms
@@ -897,25 +890,33 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
897890 =>
898891 ( parameter pattern: ( identifier #{ name} ) )
899892 ) ,
900- // ---- Conditioal compilation blocks ----
893+ // ---- Conditional compilation blocks ----
901894 // Conditional compilation blocks (`#if … #elseif … #else … #endif`) are
902895 // represented with a `ifConfigDecl` node for the entire block and an
903- // `ifConfigClause` for each branch. We translate them into nested
904- // `if_expr` nodes.
896+ // `ifConfigClause` for each branch.
905897
906- // When a conditional compilation block contains a switch case it
907- // appears within a `switch` -- we do not support this yet.
898+ // When a conditional compilation block is not in a context where it
899+ // should be translated into an if expression we simply extract the
900+ // first branch (for now).
908901 rule!(
909- ( ifConfigDecl clauses: ( ifConfigClause elements: ( switchCase) ) )
902+ ( ifConfigDecl
903+ clauses: ( ifConfigClause elements: _* @items)
904+ clauses: _* @@rest)
905+ where !ctx. conditional_compilation_as_expr
910906 =>
911- ( unsupported_node )
907+ _ * { items }
912908 ) ,
913909 // A conditional compilation block is translated into `if_expr` nodes
914910 // with branches occurring nested within the else branch.
915911 rule!(
916912 ( ifConfigDecl clauses: _* @@clauses) @@declaration
917913 =>
918914 expr {
915+ // Revert `conditional_compilation_as_expr` before processing
916+ // clauses. Note that if a clause contains a nested conditional
917+ // compilation block, then that block will be wrapped in another
918+ // `codeBlockItem` which will flip this back to `true`.
919+ ctx. conditional_compilation_as_expr = false ;
919920 ctx. conditional_compilation_tail = None ;
920921 for clause in clauses. into_iter( ) . rev( ) {
921922 ctx. conditional_compilation_tail = ctx. translate( clause) ?. into_iter( ) . next( ) ;
0 commit comments