Skip to content

Commit b5c4a18

Browse files
authored
Simple step towards importing structs, add initializeWithCopy funcs (#206)
1 parent 84587b4 commit b5c4a18

File tree

13 files changed

+286
-74
lines changed

13 files changed

+286
-74
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
public class MySwiftClass {
16+
17+
public var len: Int
18+
public var cap: Int
19+
20+
public init(len: Int, cap: Int) {
21+
self.len = len
22+
self.cap = cap
23+
24+
p("\(MySwiftClass.self).len = \(self.len)")
25+
p("\(MySwiftClass.self).cap = \(self.cap)")
26+
let addr = unsafeBitCast(self, to: UInt64.self)
27+
p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))")
28+
}
29+
30+
deinit {
31+
let addr = unsafeBitCast(self, to: UInt64.self)
32+
p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
33+
}
34+
35+
public var counter: Int32 = 0
36+
37+
public func voidMethod() {
38+
p("")
39+
}
40+
41+
public func takeIntMethod(i: Int) {
42+
p("i:\(i)")
43+
}
44+
45+
public func echoIntMethod(i: Int) -> Int {
46+
p("i:\(i)")
47+
return i
48+
}
49+
50+
public func makeIntMethod() -> Int {
51+
p("make int -> 12")
52+
return 12
53+
}
54+
55+
public func makeRandomIntMethod() -> Int {
56+
return Int.random(in: 1..<256)
57+
}
58+
}

Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -47,68 +47,18 @@ public func globalCallMeRunnable(run: () -> ()) {
4747
run()
4848
}
4949

50-
public class MySwiftClass {
51-
52-
public var len: Int
53-
public var cap: Int
54-
55-
public init(len: Int, cap: Int) {
56-
self.len = len
57-
self.cap = cap
58-
59-
p("\(MySwiftClass.self).len = \(self.len)")
60-
p("\(MySwiftClass.self).cap = \(self.cap)")
61-
let addr = unsafeBitCast(self, to: UInt64.self)
62-
p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))")
63-
}
64-
65-
deinit {
66-
let addr = unsafeBitCast(self, to: UInt64.self)
67-
p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
68-
}
69-
70-
public var counter: Int32 = 0
71-
72-
public func voidMethod() {
73-
p("")
74-
}
75-
76-
public func takeIntMethod(i: Int) {
77-
p("i:\(i)")
78-
}
79-
80-
public func echoIntMethod(i: Int) -> Int {
81-
p("i:\(i)")
82-
return i
83-
}
84-
85-
public func makeIntMethod() -> Int {
86-
p("make int -> 12")
87-
return 12
88-
}
89-
90-
public func writeString(string: String) -> Int {
91-
p("echo -> \(string)")
92-
return string.count
93-
}
94-
95-
public func makeRandomIntMethod() -> Int {
96-
return Int.random(in: 1..<256)
97-
}
98-
}
99-
10050
// ==== Internal helpers
10151

102-
private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
103-
// print("[swift][\(file):\(line)](\(function)) \(msg)")
104-
// fflush(stdout)
52+
func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
53+
print("[swift][\(file):\(line)](\(function)) \(msg)")
54+
fflush(stdout)
10555
}
10656

107-
#if os(Linux)
108-
// FIXME: why do we need this workaround?
109-
@_silgen_name("_objc_autoreleaseReturnValue")
110-
public func _objc_autoreleaseReturnValue(a: Any) {}
57+
#if os(Linux)
58+
// FIXME: why do we need this workaround?
59+
@_silgen_name("_objc_autoreleaseReturnValue")
60+
public func _objc_autoreleaseReturnValue(a: Any) {}
11161

112-
@_silgen_name("objc_autoreleaseReturnValue")
113-
public func objc_autoreleaseReturnValue(a: Any) {}
114-
#endif
62+
@_silgen_name("objc_autoreleaseReturnValue")
63+
public func objc_autoreleaseReturnValue(a: Any) {}
64+
#endif
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
public struct MySwiftStruct {
16+
17+
public var number: Int
18+
19+
public init(number: Int) {
20+
self.number = number
21+
}
22+
23+
public func voidMethod() {
24+
p("")
25+
}
26+
27+
public func takeIntMethod(i: Int) {
28+
p("i:\(i)")
29+
}
30+
31+
public func echoIntMethod(i: Int) -> Int {
32+
p("i:\(i)")
33+
return i
34+
}
35+
36+
public func makeIntMethod() -> Int {
37+
p("make int -> 12")
38+
return 12
39+
}
40+
41+
public func makeRandomIntMethod() -> Int {
42+
return Int.random(in: 1..<256)
43+
}
44+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#if os(Linux)
16+
// FIXME: why do we need this workaround?
17+
@_silgen_name("_objc_autoreleaseReturnValue")
18+
public func _objc_autoreleaseReturnValue(a: Any) {}
19+
20+
@_silgen_name("objc_autoreleaseReturnValue")
21+
public func objc_autoreleaseReturnValue(a: Any) {}
22+
#endif

Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ static void examples() {
5252

5353
obj.voidMethod();
5454
obj.takeIntMethod(42);
55+
56+
MySwiftStruct swiftValue = new MySwiftStruct(12);
57+
5558
}
5659

5760
System.out.println("DONE.");
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
package com.example.swift;
16+
17+
import org.junit.jupiter.api.Disabled;
18+
import org.junit.jupiter.api.Test;
19+
import org.swift.swiftkit.SwiftArena;
20+
import org.swift.swiftkit.SwiftKit;
21+
22+
import java.io.File;
23+
import java.util.stream.Stream;
24+
25+
import static org.junit.jupiter.api.Assertions.assertEquals;
26+
27+
public class MySwiftStructTest {
28+
29+
@Test
30+
void test_MySwiftClass_voidMethod() {
31+
try (var arena = SwiftArena.ofConfined()) {
32+
MySwiftStruct o = new MySwiftStruct(12);
33+
// o.voidMethod();
34+
}
35+
}
36+
37+
}

Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ public void arena_releaseClassOnClose_class_leaked() {
7070
// The message should point out which objects "leaked":
7171
assertTrue(ex.getMessage().contains(memorySegmentDescription));
7272
}
73+
}
74+
75+
@Test
76+
public void arena_initializeWithCopy_struct() {
7377

7478
}
7579
}

Sources/ExampleSwiftLibrary/MySwiftLibrary.swift

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,7 @@ public func _getTypeByMangledNameInEnvironment(
9797

9898
// ==== Internal helpers
9999

100-
private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
100+
func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
101101
print("[swift][\(file):\(line)](\(function)) \(msg)")
102102
fflush(stdout)
103103
}
104-
105-
#if os(Linux)
106-
// FIXME: why do we need this workaround?
107-
@_silgen_name("_objc_autoreleaseReturnValue")
108-
public func _objc_autoreleaseReturnValue(a: Any) {}
109-
110-
@_silgen_name("objc_autoreleaseReturnValue")
111-
public func objc_autoreleaseReturnValue(a: Any) {}
112-
#endif

Sources/JExtractSwift/ImportedDecls.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ public struct ImportedNominalType: ImportedDecl {
4949
javaType: javaType
5050
)
5151
}
52+
53+
public var isReferenceType: Bool {
54+
switch self.kind {
55+
case .class, .actor:
56+
return true
57+
case .enum, .struct:
58+
return false
59+
}
60+
}
5261

5362
/// The Java class name without the package.
5463
public var javaClassName: String {

Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ extension Swift2JavaTranslator {
194194
printPackage(&printer)
195195
printImports(&printer)
196196

197-
printClass(&printer, decl) { printer in
197+
printNominal(&printer, decl) { printer in
198198
// Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static.
199199
// We call into source swift-java source generated accessors which give us the type of the Swift object:
200200
// TODO: seems we no longer need the mangled name per se, so avoiding such constant and downcall
@@ -277,10 +277,17 @@ extension Swift2JavaTranslator {
277277
printer.print("")
278278
}
279279

280-
public func printClass(
280+
public func printNominal(
281281
_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void
282282
) {
283-
printer.printTypeDecl("public final class \(decl.javaClassName) implements SwiftHeapObject") {
283+
let parentProtocol: String
284+
if decl.isReferenceType {
285+
parentProtocol = "SwiftHeapObject"
286+
} else {
287+
parentProtocol = "SwiftValue"
288+
}
289+
290+
printer.printTypeDecl("public final class \(decl.javaClassName) implements \(parentProtocol)") {
284291
printer in
285292
// ==== Storage of the class
286293
printClassSelfProperty(&printer, decl)

Sources/JExtractSwift/Swift2JavaVisitor.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ final class Swift2JavaVisitor: SyntaxVisitor {
4040
}
4141

4242
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
43+
log.debug("Visit \(node.kind): \(node)")
4344
guard let importedNominalType = translator.importedNominalType(node) else {
4445
return .skipChildren
4546
}
@@ -54,7 +55,24 @@ final class Swift2JavaVisitor: SyntaxVisitor {
5455
currentTypeName = nil
5556
}
5657
}
58+
59+
override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
60+
log.debug("Visit \(node.kind): \(node)")
61+
guard let importedNominalType = translator.importedNominalType(node) else {
62+
return .skipChildren
63+
}
64+
65+
currentTypeName = importedNominalType.swiftTypeName
66+
return .visitChildren
67+
}
5768

69+
override func visitPost(_ node: StructDeclSyntax) {
70+
if currentTypeName != nil {
71+
log.debug("Completed import: \(node.kind) \(node.name)")
72+
currentTypeName = nil
73+
}
74+
}
75+
5876
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
5977
// Resolve the extended type of the extension as an imported nominal, and
6078
// recurse if we found it.

SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public ConfinedSwiftMemorySession(Thread owner) {
3636

3737
public void checkValid() throws RuntimeException {
3838
if (this.owner != null && this.owner != Thread.currentThread()) {
39-
throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!".formatted(this.owner, Thread.currentThread()));
39+
throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!"
40+
.formatted(this.owner, Thread.currentThread()));
4041
} else if (this.state.get() < ACTIVE) {
4142
throw new RuntimeException("SwiftArena is already closed!");
4243
}

0 commit comments

Comments
 (0)