Skip to content

Commit 91c6311

Browse files
committed
Add Swift-side infrastructure for ASTGen.
1 parent cc0da04 commit 91c6311

File tree

8 files changed

+290
-4
lines changed

8 files changed

+290
-4
lines changed

Sources/ASTGen/ASTGen.swift

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import SwiftParser
2+
import SwiftSyntax
3+
4+
import CASTBridging
5+
6+
extension Array {
7+
public func withBridgedArrayRef<T>(_ c: (BridgedArrayRef) -> T) -> T {
8+
withUnsafeBytes { buf in
9+
c(BridgedArrayRef(data: buf.baseAddress!, numElements: count))
10+
}
11+
}
12+
}
13+
14+
extension UnsafePointer {
15+
public var raw: UnsafeMutableRawPointer {
16+
UnsafeMutableRawPointer(mutating: self)
17+
}
18+
}
19+
20+
struct ASTGenVisitor: SyntaxTransformVisitor {
21+
let ctx: UnsafeMutableRawPointer
22+
let base: UnsafePointer<CChar>
23+
24+
// TOOD: we need to be up updating this.
25+
var declContext: UnsafeMutableRawPointer
26+
27+
// TODO: this some how messes up the witness table when I uncomment it locally :/
28+
// public func visit<T>(_ node: T?) -> [UnsafeMutableRawPointer]? {
29+
// if let node = node { return visit(node) }
30+
// return nil
31+
// }
32+
33+
@_disfavoredOverload
34+
public func visit(_ node: SourceFileSyntax) -> UnsafeMutableRawPointer {
35+
fatalError("Use other overload.")
36+
}
37+
38+
public func visit(_ node: SourceFileSyntax) -> [UnsafeMutableRawPointer] {
39+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
40+
var out = [UnsafeMutableRawPointer]()
41+
42+
for element in node.statements {
43+
let swiftASTNodes = visit(element)
44+
if element.item.is(StmtSyntax.self) {
45+
out.append(SwiftTopLevelCodeDecl_createStmt(ctx, declContext, loc, swiftASTNodes, loc))
46+
} else if element.item.is(ExprSyntax.self) {
47+
out.append(SwiftTopLevelCodeDecl_createExpr(ctx, declContext, loc, swiftASTNodes, loc))
48+
} else {
49+
assert(element.item.is(DeclSyntax.self))
50+
out.append(swiftASTNodes)
51+
}
52+
}
53+
54+
return out
55+
}
56+
57+
public func visit(_ node: FunctionCallExprSyntax) -> UnsafeMutableRawPointer {
58+
let args = visit(node.argumentList)
59+
// TODO: hack
60+
let callee = visit(node.calledExpression)
61+
return SwiftFunctionCallExpr_create(self.ctx, callee, args)
62+
}
63+
64+
public func visit(_ node: IdentifierExprSyntax) -> UnsafeMutableRawPointer {
65+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
66+
67+
var text = node.identifier.text
68+
let id = text.withUTF8 { buf in
69+
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
70+
}
71+
72+
return SwiftIdentifierExpr_create(ctx, id, loc)
73+
}
74+
75+
public func visit(_ node: SimpleTypeIdentifierSyntax) -> UnsafeMutableRawPointer {
76+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
77+
78+
var text = node.name.text
79+
let id = text.withUTF8 { buf in
80+
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
81+
}
82+
83+
return SimpleIdentTypeRepr_create(ctx, loc, id)
84+
}
85+
86+
public func visit(_ node: IdentifierPatternSyntax) -> UnsafeMutableRawPointer {
87+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
88+
89+
var text = node.identifier.text
90+
let id = text.withUTF8 { buf in
91+
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
92+
}
93+
94+
return SwiftIdentifierExpr_create(ctx, id, loc)
95+
}
96+
97+
public func visit(_ node: MemberAccessExprSyntax) -> UnsafeMutableRawPointer {
98+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
99+
let base = visit(node.base!)
100+
var nameText = node.name.text
101+
let name = nameText.withUTF8 { buf in
102+
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
103+
}
104+
105+
return UnresolvedDotExpr_create(ctx, base, loc, name, loc)
106+
}
107+
108+
public func visit(_ node: TupleExprElementSyntax) -> UnsafeMutableRawPointer {
109+
visit(node.expression)
110+
}
111+
112+
public func visit(_ node: TupleExprElementListSyntax) -> UnsafeMutableRawPointer {
113+
let elements = node.map(self.visit)
114+
115+
// TODO: find correct paren locs.
116+
let lParenLoc = self.base.advanced(by: node.position.utf8Offset).raw
117+
let rParenLoc = self.base.advanced(by: node.position.utf8Offset).raw
118+
119+
return elements.withBridgedArrayRef { elementsRef in
120+
SwiftTupleExpr_create(self.ctx, lParenLoc, elementsRef, rParenLoc)
121+
}
122+
}
123+
124+
public func visit(_ node: VariableDeclSyntax) -> UnsafeMutableRawPointer {
125+
let pattern = visit(node.bindings.first!.pattern)
126+
let initializer = visit(node.bindings.first!.initializer!)
127+
128+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
129+
let isStateic = false // TODO: compute this
130+
let isLet = node.letOrVarKeyword.tokenKind == .letKeyword
131+
132+
// TODO: don't drop "initializer" on the floor.
133+
return SwiftVarDecl_create(ctx, pattern, loc, isStateic, isLet, declContext)
134+
}
135+
136+
public func visit(_ node: ConditionElementSyntax) -> UnsafeMutableRawPointer {
137+
visit(node.condition)
138+
}
139+
140+
public func visit(_ node: CodeBlockItemSyntax) -> UnsafeMutableRawPointer {
141+
visit(node.item)
142+
}
143+
144+
public func visit(_ node: CodeBlockSyntax) -> UnsafeMutableRawPointer {
145+
let statements = node.statements.map(self.visit)
146+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
147+
148+
return statements.withBridgedArrayRef { ref in
149+
BraceStmt_create(ctx, loc, ref, loc)
150+
}
151+
}
152+
153+
public func visit(_ node: FunctionParameterSyntax) -> UnsafeMutableRawPointer {
154+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
155+
156+
let firstName: UnsafeMutableRawPointer?
157+
let secondName: UnsafeMutableRawPointer?
158+
159+
if let nodeFirstName = node.firstName {
160+
var text = nodeFirstName.text
161+
firstName = text.withUTF8 { buf in
162+
SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count).raw
163+
}
164+
} else {
165+
firstName = nil
166+
}
167+
168+
if let nodeSecondName = node.secondName {
169+
var text = nodeSecondName.text
170+
secondName = text.withUTF8 { buf in
171+
SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count).raw
172+
}
173+
} else {
174+
secondName = nil
175+
}
176+
177+
return ParamDecl_create(ctx, loc, loc, firstName, loc, secondName, declContext)
178+
}
179+
180+
public func visit(_ node: FunctionDeclSyntax) -> UnsafeMutableRawPointer {
181+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
182+
183+
var nameText = node.identifier.text
184+
let name = nameText.withUTF8 { buf in
185+
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
186+
}
187+
188+
let body: UnsafeMutableRawPointer?
189+
if let nodeBody = node.body {
190+
body = visit(nodeBody)
191+
} else {
192+
body = nil
193+
}
194+
195+
let returnType: UnsafeMutableRawPointer?
196+
if let output = node.signature.output {
197+
returnType = visit(output.returnType)
198+
} else {
199+
returnType = nil
200+
}
201+
202+
let params = node.signature.input.parameterList.map { visit($0) }
203+
return params.withBridgedArrayRef { ref in
204+
FuncDecl_create(ctx, loc, false, loc, name, loc, false, nil, false, nil, loc, ref, loc, body, returnType, declContext)
205+
}
206+
}
207+
208+
public func visit(_ node: IfStmtSyntax) -> UnsafeMutableRawPointer {
209+
let conditions = node.conditions.map(self.visit)
210+
assert(conditions.count == 1) // TODO: handle multiple conditions.
211+
212+
let body = visit(node.body)
213+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
214+
215+
if let elseBody = node.elseBody, node.elseKeyword != nil {
216+
return IfStmt_create(ctx, loc, conditions.first!, body, loc, visit(elseBody))
217+
}
218+
219+
return IfStmt_create(ctx, loc, conditions.first!, body, nil, nil)
220+
}
221+
222+
public func visit(_ node: StringLiteralExprSyntax) -> UnsafeMutableRawPointer {
223+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
224+
var segment = node.segments.first!.as(StringSegmentSyntax.self)!.content.text
225+
return segment.withUTF8 { buf in
226+
let id = SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
227+
return SwiftStringLiteralExpr_create(ctx, id, buf.count, loc)
228+
}
229+
}
230+
231+
public func visit(_ node: IntegerLiteralExprSyntax) -> UnsafeMutableRawPointer {
232+
let loc = self.base.advanced(by: node.position.utf8Offset).raw
233+
var segment = node.digits.text
234+
return segment.withUTF8 { buf in
235+
let id = SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
236+
return SwiftIntegerLiteralExpr_create(ctx, id, buf.count, loc)
237+
}
238+
}
239+
}
240+
241+
@_cdecl("parseTopLevelSwift")
242+
public func parseTopLevelSwift(
243+
buffer: UnsafePointer<CChar>, declContext: UnsafeMutableRawPointer,
244+
ctx: UnsafeMutableRawPointer,
245+
outputContext: UnsafeMutableRawPointer,
246+
callback: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void
247+
) {
248+
let syntax = try! Parser.parse(source: String(cString: buffer))
249+
dump(syntax)
250+
ASTGenVisitor(ctx: ctx, base: buffer, declContext: declContext)
251+
.visit(syntax)
252+
.forEach { callback($0, outputContext) }
253+
}

Sources/ASTGen/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
add_library(ASTGen
2+
ASTGen.swift)
3+
4+
target_compile_options(ASTGen PUBLIC
5+
"-emit-module-interface")
6+
7+
target_link_libraries(ASTGen PUBLIC
8+
SwiftSyntax
9+
SwiftParser
10+
SwiftDiagnostics)
11+
12+
target_include_directories(SwiftParser PUBLIC
13+
"${CMAKE_CURRENT_BINARY_DIR}/../SwiftSyntax"
14+
"${CMAKE_CURRENT_BINARY_DIR}/../SwiftDiagnostics"
15+
"${CMAKE_CURRENT_BINARY_DIR}/../SwiftParser")
16+
17+
set_property(GLOBAL APPEND PROPERTY SWIFTSYNTAX_EXPORTS ASTGen)
18+
19+
# NOTE: workaround for CMake not setting up include flags yet
20+
set_target_properties(ASTGen PROPERTIES
21+
INTERFACE_INCLUDE_DIRECTORIES
22+
"${CMAKE_Swift_MODULE_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR}")
23+
24+
install(TARGETS ASTGen
25+
EXPORT SwiftSyntaxTargets
26+
ARCHIVE DESTINATION lib
27+
LIBRARY DESTINATION lib
28+
RUNTIME DESTINATION bin)

Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
add_subdirectory(SwiftSyntax)
1010
add_subdirectory(SwiftDiagnostics)
1111
add_subdirectory(SwiftParser)
12+
add_subdirectory(ASTGen)

Sources/SwiftDiagnostics/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ add_library(SwiftDiagnostics STATIC
1414

1515
target_link_libraries(SwiftDiagnostics PUBLIC
1616
SwiftSyntax)
17+
18+
target_include_directories(SwiftDiagnostics PUBLIC
19+
"${CMAKE_CURRENT_BINARY_DIR}/../SwiftSyntax")
1720

1821
set_property(GLOBAL APPEND PROPERTY SWIFTSYNTAX_EXPORTS SwiftDiagnostics)
1922

Sources/SwiftParser/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ add_library(SwiftParser STATIC
3535
target_link_libraries(SwiftParser PUBLIC
3636
SwiftSyntax
3737
SwiftDiagnostics)
38+
39+
target_include_directories(SwiftParser PUBLIC
40+
"${CMAKE_CURRENT_BINARY_DIR}/../SwiftSyntax"
41+
"${CMAKE_CURRENT_BINARY_DIR}/../SwiftDiagnostics")
3842

3943
set_property(GLOBAL APPEND PROPERTY SWIFTSYNTAX_EXPORTS SwiftParser)
4044

Sources/SwiftParser/CharacterInfo.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ extension Unicode.Scalar {
9393
}
9494
}
9595

96-
#if swift(<5.7)
9796
extension UnsafeRawBufferPointer {
9897
/// Returns a typed buffer to the memory referenced by this buffer,
9998
/// assuming that the memory is already bound to the specified type.
@@ -122,7 +121,6 @@ extension UnsafeRawBufferPointer {
122121
return .init(start: s.assumingMemoryBound(to: T.self), count: n)
123122
}
124123
}
125-
#endif
126124

127125
private var InfoTable: CharacterInfoTable = (
128126
// 0 NUL 1 SOH 2 STX 3 ETX

Sources/SwiftSyntax/BumpPtrAllocator.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ public class BumpPtrAllocator {
163163

164164
// MARK: Compatibilty Shims
165165

166-
#if swift(<5.7)
167166
extension UnsafeMutableRawPointer {
168167
/// Obtain the next pointer whose bit pattern is a multiple of alignment.
169168
///
@@ -181,4 +180,3 @@ extension UnsafeMutableRawPointer {
181180
return .init(bitPattern: bits)!
182181
}
183182
}
184-
#endif

Sources/SwiftSyntax/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_library(SwiftSyntax STATIC
4242
gyb_generated/SyntaxKind.swift
4343
gyb_generated/SyntaxRewriter.swift
4444
gyb_generated/SyntaxTraits.swift
45+
gyb_generated/SyntaxTransform.swift
4546
gyb_generated/SyntaxVisitor.swift
4647
gyb_generated/TokenKind.swift
4748
gyb_generated/Tokens.swift

0 commit comments

Comments
 (0)