@@ -58,73 +58,112 @@ struct ASTGenVisitor {
58
58
}
59
59
60
60
func generate( sourceFile node: SourceFileSyntax ) -> [ BridgedASTNode ] {
61
- var out = [ BridgedASTNode] ( )
62
- let isTopLevel = self . declContext. isModuleScopeContext
61
+ // If not top-level, no need for 'TopLevelCodeDecl' treatment.
62
+ if !self . declContext. isModuleScopeContext {
63
+ return self . generate ( codeBlockItemList: node. statements)
64
+ } else {
65
+ return self . generateTopLevel ( codeBlockItemList: node. statements)
66
+ }
67
+ }
63
68
64
- visitIfConfigElements (
65
- node. statements,
66
- of: CodeBlockItemSyntax . self,
67
- split: Self . splitCodeBlockItemIfConfig
68
- ) { element in
69
+ func generateTopLevel( codeBlockItem node: CodeBlockItemSyntax ) -> BridgedASTNode ? {
70
+ let parentDC = self . declContext
69
71
70
- func generateStmtOrExpr( _ body: ( ) -> BridgedASTNode ) -> BridgedASTNode {
71
- if !isTopLevel {
72
- return body ( )
73
- }
72
+ func maybeTopLevelCodeDecl( body: ( ) -> BridgedASTNode ? ) -> BridgedASTNode ? {
73
+ let topLevelDecl : BridgedTopLevelCodeDecl = BridgedTopLevelCodeDecl . create ( self . ctx, declContext: self . declContext)
74
+ guard let astNode = withDeclContext ( topLevelDecl. asDeclContext, body) else {
75
+ return nil
76
+ }
77
+
78
+ if astNode. kind == . decl {
79
+ // If a decl is generated, discard the TopLevelCodeDecl.
80
+ return astNode
81
+ }
74
82
75
- let topLevelDecl = BridgedTopLevelCodeDecl . create ( self . ctx, declContext: self . declContext)
76
- let astNode = withDeclContext ( topLevelDecl. asDeclContext) {
77
- body ( )
83
+ // Diagnose top-level code in non-script files.
84
+ if !declContext. parentSourceFile. isScriptMode {
85
+ switch astNode. kind {
86
+ case . stmt:
87
+ self . diagnose ( . illegalTopLevelStmt( node) )
88
+ case . expr:
89
+ self . diagnose ( . illegalTopLevelExpr( node) )
90
+ case . decl:
91
+ fatalError ( " unreachable " )
78
92
}
93
+ }
94
+
95
+ let bodyRange = self . generateImplicitBraceRange ( node)
96
+ let body = BridgedBraceStmt . createImplicit (
97
+ self . ctx,
98
+ lBraceLoc: bodyRange. start,
99
+ element: astNode,
100
+ rBraceLoc: bodyRange. end
101
+ )
102
+ topLevelDecl. setBody ( body: body)
103
+ return . decl( topLevelDecl. asDecl)
104
+ }
79
105
80
- // Diagnose top level code in non-script file.
81
- if ( !declContext. parentSourceFile. isScriptMode) {
82
- switch element. item {
83
- case . stmt:
84
- self . diagnose ( . illegalTopLevelStmt( element) )
85
- case . expr:
86
- self . diagnose ( . illegalTopLevelExpr( element) )
87
- case . decl:
88
- fatalError ( " unreachable " )
106
+ switch node. item {
107
+ case . decl( let node) :
108
+ if let node = node. as ( MacroExpansionDeclSyntax . self) {
109
+ return maybeTopLevelCodeDecl {
110
+ switch self . maybeGenerateBuiltinPound ( freestandingMacroExpansion: node) {
111
+ case . generated( let generated) :
112
+ return generated
113
+ case . ignored:
114
+ /// If it is actually a macro expansion decl, it should use the parent DC.
115
+ return self . withDeclContext ( parentDC) {
116
+ return . decl( self . generate ( macroExpansionDecl: node) . asDecl)
117
+ }
89
118
}
90
119
}
120
+ }
121
+ // Regular 'decl' nodes never be a stmt or expr. No top-level code treatment.
122
+ return self . generate ( decl: node) . map { . decl( $0) }
123
+
124
+ case . expr( let node) :
125
+ return maybeTopLevelCodeDecl {
126
+ if let node = node. as ( MacroExpansionExprSyntax . self) {
127
+ switch self . maybeGenerateBuiltinPound ( freestandingMacroExpansion: node) {
128
+ case . generated( let generated) :
129
+ return generated
130
+ case . ignored:
131
+ // Let regular 'self.generate(expr:)' generate the macro expansions.
132
+ break
133
+ }
134
+ }
135
+ return . expr( self . generate ( expr: node) )
136
+ }
91
137
92
- let bodyRange = self . generateImplicitBraceRange ( element)
93
- let body = BridgedBraceStmt . createImplicit (
94
- self . ctx,
95
- lBraceLoc: bodyRange. start,
96
- element: astNode,
97
- rBraceLoc: bodyRange. end
98
- )
99
- topLevelDecl. setBody ( body: body)
100
- return . decl( topLevelDecl. asDecl)
138
+ case . stmt( let node) :
139
+ return maybeTopLevelCodeDecl {
140
+ return . stmt( self . generate ( stmt: node) )
101
141
}
142
+ }
143
+ }
102
144
103
- // TODO: Set semicolon loc.
104
- switch element. item {
105
- case . decl( let node) :
106
- if let d = self . generate ( decl: node) {
107
- out. append ( . decl( d) )
145
+ func generateTopLevel( codeBlockItemList node: CodeBlockItemListSyntax ) -> [ BridgedASTNode ] {
146
+ var out = [ BridgedASTNode] ( )
147
+ visitIfConfigElements (
148
+ node,
149
+ of: CodeBlockItemSyntax . self,
150
+ split: Self . splitCodeBlockItemIfConfig
151
+ ) { element in
152
+ guard let item = self . generateTopLevel ( codeBlockItem: element) else {
153
+ return
154
+ }
155
+ out. append ( item)
108
156
109
- // Hoist 'VarDecl' to the top-level .
110
- withBridgedSwiftClosure { ptr in
111
- let hoisted = ptr! . load ( as : BridgedDecl . self )
112
- out . append ( . decl ( hoisted ) )
113
- } call : { handle in
114
- d . forEachDeclToHoist ( handle)
115
- }
157
+ // Hoist 'VarDecl' to the block .
158
+ if item . kind == . decl {
159
+ withBridgedSwiftClosure { ptr in
160
+ let d = ptr! . load ( as : BridgedDecl . self )
161
+ out . append ( . decl ( d ) )
162
+ } call : { handle in
163
+ item . castToDecl ( ) . forEachDeclToHoist ( handle )
116
164
}
117
- case . stmt( let node) :
118
- out. append ( generateStmtOrExpr {
119
- . stmt( self . generate ( stmt: node) )
120
- } )
121
- case . expr( let node) :
122
- out. append ( generateStmtOrExpr {
123
- . expr( self . generate ( expr: node) )
124
- } )
125
165
}
126
166
}
127
-
128
167
return out
129
168
}
130
169
}
0 commit comments