Skip to content

Commit 7d4b57b

Browse files
committed
Followups for handling value inits, various helper funcs
1 parent 62b898e commit 7d4b57b

9 files changed

+175
-75
lines changed

Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,22 @@ extension ImplicitlyUnwrappedOptionalTypeSyntax {
5252
}
5353
}
5454

55-
extension TypeSyntax {
56-
fileprivate var isActorSystem: Bool {
57-
self.trimmedDescription == "ActorSystem"
55+
extension SyntaxProtocol {
56+
57+
var asNominalTypeKind: NominalTypeKind {
58+
if isClass {
59+
.class
60+
} else if isActor {
61+
.actor
62+
} else if isStruct {
63+
.struct
64+
} else if isEnum {
65+
.enum
66+
} else {
67+
fatalError("Unknown nominal kind: \(self)")
68+
}
5869
}
59-
}
6070

61-
extension DeclSyntaxProtocol {
6271
var isClass: Bool {
6372
return self.is(ClassDeclSyntax.self)
6473
}
@@ -79,11 +88,8 @@ extension DeclSyntaxProtocol {
7988
extension DeclModifierSyntax {
8089
var isAccessControl: Bool {
8190
switch self.name.tokenKind {
82-
case .keyword(.private): fallthrough
83-
case .keyword(.fileprivate): fallthrough
84-
case .keyword(.internal): fallthrough
85-
case .keyword(.package): fallthrough
86-
case .keyword(.public):
91+
case .keyword(.private), .keyword(.fileprivate), .keyword(.internal), .keyword(.package),
92+
.keyword(.public):
8793
return true
8894
default:
8995
return false

Sources/JExtractSwift/ImportedDecls.swift

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,19 @@ public struct ImportedNominalType: ImportedDecl {
4444
TranslatedType(
4545
cCompatibleConvention: .direct,
4646
originalSwiftType: "\(raw: swiftTypeName)",
47+
originalSwiftTypeKind: self.kind,
4748
cCompatibleSwiftType: "UnsafeRawPointer",
4849
cCompatibleJavaMemoryLayout: .heapObject,
4950
javaType: javaType
5051
)
5152
}
52-
53+
5354
public var isReferenceType: Bool {
5455
switch self.kind {
5556
case .class, .actor:
56-
return true
57-
case .enum, .struct:
58-
return false
57+
true
58+
default:
59+
false
5960
}
6061
}
6162

@@ -73,6 +74,34 @@ public enum NominalTypeKind {
7374
case `class`
7475
case `enum`
7576
case `struct`
77+
case `void` // TODO: NOT NOMINAL, BUT...
78+
case function // TODO: NOT NOMINAL, BUT...
79+
case primitive // TODO: NOT NOMINAL, BUT...
80+
81+
var isReferenceType: Bool {
82+
switch self {
83+
case .actor, .class: true
84+
case .enum, .struct: false
85+
case .void, .function, .primitive: false
86+
}
87+
}
88+
89+
var isValueType: Bool {
90+
switch self {
91+
case .actor, .class: false
92+
case .enum, .struct: true
93+
case .void, .function, .primitive: false
94+
}
95+
}
96+
97+
var isVoid: Bool {
98+
switch self {
99+
case .actor, .class: false
100+
case .enum, .struct: false
101+
case .void: true
102+
case .function, .primitive: false
103+
}
104+
}
76105
}
77106

78107
public struct ImportedParam {
@@ -99,7 +128,7 @@ public struct ImportedParam {
99128
var effectiveName: String? {
100129
firstName ?? secondName
101130
}
102-
131+
103132
var effectiveValueName: String {
104133
secondName ?? firstName ?? "_"
105134
}
@@ -269,9 +298,9 @@ extension ImportedFunc: Hashable {
269298
self.swiftDecl.id.hash(into: &hasher)
270299
}
271300

272-
public static func ==(lhs: ImportedFunc, rhs: ImportedFunc) -> Swift.Bool {
273-
lhs.parent?.originalSwiftType.id == rhs.parent?.originalSwiftType.id &&
274-
lhs.swiftDecl.id == rhs.swiftDecl.id
301+
public static func == (lhs: ImportedFunc, rhs: ImportedFunc) -> Swift.Bool {
302+
lhs.parent?.originalSwiftType.id == rhs.parent?.originalSwiftType.id
303+
&& lhs.swiftDecl.id == rhs.swiftDecl.id
275304
}
276305
}
277306

@@ -394,8 +423,8 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible {
394423
)
395424

396425
case nil,
397-
.wrapper,
398-
.swiftThunkSelf:
426+
.wrapper,
427+
.swiftThunkSelf:
399428
break
400429
}
401430
}

Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ extension Swift2JavaTranslator {
3434
continue
3535
}
3636

37-
layouts.append(param.type.foreignValueLayout)
37+
var layout = param.type.foreignValueLayout
38+
layout.inlineComment = "\(param.effectiveValueName)"
39+
layouts.append(layout)
3840
}
3941

4042
return layouts

Sources/JExtractSwift/Swift2JavaTranslator.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ extension Swift2JavaTranslator {
120120
"java.util.Arrays",
121121
"java.util.stream.Collectors",
122122
"java.nio.charset.StandardCharsets",
123+
124+
"java.util.concurrent.atomic.*",
123125
]
124126

125127
}

Sources/JExtractSwift/Swift2JavaVisitor.swift

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ final class Swift2JavaVisitor: SyntaxVisitor {
2626
/// store this along with type names as we import them.
2727
let targetJavaPackage: String
2828

29+
var currentType: ImportedNominalType? = nil
30+
2931
/// The current type name as a nested name like A.B.C.
30-
var currentTypeName: String? = nil
32+
var currentTypeName: String? { self.currentType?.swiftTypeName }
3133

3234
var log: Logger { translator.log }
3335

@@ -45,34 +47,34 @@ final class Swift2JavaVisitor: SyntaxVisitor {
4547
return .skipChildren
4648
}
4749

48-
currentTypeName = importedNominalType.swiftTypeName
50+
self.currentType = importedNominalType
4951
return .visitChildren
5052
}
5153

5254
override func visitPost(_ node: ClassDeclSyntax) {
53-
if currentTypeName != nil {
55+
if currentType != nil {
5456
log.debug("Completed import: \(node.kind) \(node.name)")
55-
currentTypeName = nil
57+
self.currentType = nil
5658
}
5759
}
58-
60+
5961
override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
6062
log.debug("Visit \(node.kind): \(node)")
6163
guard let importedNominalType = translator.importedNominalType(node) else {
6264
return .skipChildren
6365
}
6466

65-
currentTypeName = importedNominalType.swiftTypeName
67+
self.currentType = importedNominalType
6668
return .visitChildren
6769
}
6870

6971
override func visitPost(_ node: StructDeclSyntax) {
70-
if currentTypeName != nil {
72+
if currentType != nil {
7173
log.debug("Completed import: \(node.kind) \(node.name)")
72-
currentTypeName = nil
74+
self.currentType = nil
7375
}
7476
}
75-
77+
7678
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
7779
// Resolve the extended type of the extension as an imported nominal, and
7880
// recurse if we found it.
@@ -82,13 +84,13 @@ final class Swift2JavaVisitor: SyntaxVisitor {
8284
return .skipChildren
8385
}
8486

85-
currentTypeName = importedNominalType.swiftTypeName
87+
self.currentType = importedNominalType
8688
return .visitChildren
8789
}
8890

8991
override func visitPost(_ node: ExtensionDeclSyntax) {
90-
if currentTypeName != nil {
91-
currentTypeName = nil
92+
if currentType != nil {
93+
self.currentType = nil
9294
}
9395
}
9496

@@ -266,6 +268,7 @@ extension InitializerDeclSyntax {
266268
}
267269

268270
// Ok, import it
271+
log.warning("Import initializer: \(self)")
269272
return true
270273
}
271274
}

Sources/JExtractSwift/SwiftThunkTranslator.swift

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,45 @@ struct SwiftThunkTranslator {
8080

8181
func renderSwiftInitAccessor(_ function: ImportedFunc) -> [DeclSyntax] {
8282
guard let parent = function.parent else {
83-
fatalError("Cannot render initializer accessor if init function has no parent! Was: \(function)")
83+
fatalError(
84+
"Cannot render initializer accessor if init function has no parent! Was: \(function)")
8485
}
8586

8687
let thunkName = self.st.thunkNameRegistry.functionThunkName(
8788
module: st.swiftModuleName, decl: function)
8889

89-
return
90-
[
90+
let cDecl =
91+
"""
92+
@_cdecl("\(thunkName)")
93+
"""
94+
let typeName = "\(parent.swiftTypeName)"
95+
96+
if parent.isReferenceType {
97+
return [
9198
"""
92-
@_cdecl("\(raw: thunkName)")
93-
public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil))) -> UnsafeMutableRawPointer /* \(raw: parent.swiftTypeName) */ {
94-
let _self = \(raw: parent.swiftTypeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil)))
99+
\(raw: cDecl)
100+
public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil))) -> UnsafeMutableRawPointer /* \(raw: typeName) */ {
101+
var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil)))
95102
let self$ = unsafeBitCast(_self, to: UnsafeMutableRawPointer.self)
96-
return _swiftjava_swift_retain(object: self$)
103+
_swiftjava_swift_retain(object: self$)
104+
return self$
105+
}
106+
"""
107+
]
108+
} else {
109+
return [
110+
"""
111+
\(raw: cDecl)
112+
public func \(raw: thunkName)(
113+
\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil)),
114+
resultBuffer: /* \(raw: typeName) */ UnsafeMutableRawPointer
115+
) {
116+
var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil)))
117+
resultBuffer.assumingMemoryBound(to: \(raw: typeName).self).initialize(to: _self)
97118
}
98119
"""
99120
]
121+
}
100122
}
101123

102124
func render(forFunc decl: ImportedFunc) -> [DeclSyntax] {
@@ -109,20 +131,25 @@ struct SwiftThunkTranslator {
109131
} else {
110132
"-> \(decl.returnType.cCompatibleSwiftType) /* \(decl.returnType.swiftTypeName) */"
111133
}
112-
134+
113135
// Do we need to pass a self parameter?
114136
let paramPassingStyle: SelfParameterVariant?
115137
let callBase: String
116138
let callBaseDot: String
117-
if let parent = decl.parent {
118-
paramPassingStyle = .swiftThunkSelf
119-
callBase = "let self$ = unsafeBitCast(_self, to: \(parent.originalSwiftType).self)"
120-
callBaseDot = "self$."
121-
} else {
122-
paramPassingStyle = nil
123-
callBase = ""
124-
callBaseDot = ""
125-
}
139+
if let parent = decl.parent, parent.isReferenceType {
140+
paramPassingStyle = .swiftThunkSelf
141+
callBase = "let self$ = unsafeBitCast(_self, to: \(parent.originalSwiftType).self)"
142+
callBaseDot = "self$."
143+
} else if let parent = decl.parent, !parent.isReferenceType {
144+
paramPassingStyle = .swiftThunkSelf
145+
callBase =
146+
"var self$ = _self.assumingMemoryBound(to: \(parent.originalSwiftType).self).pointee"
147+
callBaseDot = "self$."
148+
} else {
149+
paramPassingStyle = nil
150+
callBase = ""
151+
callBaseDot = ""
152+
}
126153

127154
// FIXME: handle in thunk: errors
128155

@@ -155,7 +182,7 @@ struct SwiftThunkTranslator {
155182
"""
156183
]
157184
}
158-
185+
159186
func adaptArgumentsInThunk(_ decl: ImportedFunc) -> String {
160187
var lines: [String] = []
161188
for p in decl.parameters {
@@ -165,11 +192,11 @@ struct SwiftThunkTranslator {
165192
"""
166193
let \(p.effectiveValueName) = String(cString: \(p.effectiveValueName))
167194
"""
168-
195+
169196
lines += [adaptedType]
170197
}
171198
}
172-
199+
173200
return lines.joined(separator: "\n")
174201
}
175202
}

0 commit comments

Comments
 (0)