Skip to content

Commit 258ccff

Browse files
committed
Prepare accessor function descriptors for properties: get set
1 parent 94dbaff commit 258ccff

File tree

6 files changed

+397
-47
lines changed

6 files changed

+397
-47
lines changed

Sources/ExampleSwiftLibrary/MySwiftLibrary.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public class MySwiftClass {
5555
p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
5656
}
5757

58+
public var counter: Int32 = 0
59+
5860
public func voidMethod() {
5961
p("")
6062
}

Sources/JExtractSwift/ImportedDecls.swift

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Foundation
1616
import JavaTypes
1717
import SwiftSyntax
1818

19+
/// Any imported (Swift) declaration
1920
protocol ImportedDecl {
2021

2122
}
@@ -32,6 +33,7 @@ public struct ImportedNominalType: ImportedDecl {
3233

3334
public var initializers: [ImportedFunc] = []
3435
public var methods: [ImportedFunc] = []
36+
public var variables: [ImportedVariable] = []
3537

3638
public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil, kind: NominalTypeKind) {
3739
self.swiftTypeName = swiftTypeName
@@ -195,7 +197,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible {
195197

196198
public var swiftMangledName: String = ""
197199

198-
public var swiftDeclRaw: String? = nil
200+
public var syntax: String? = nil
199201

200202
public var isInit: Bool = false
201203

@@ -221,7 +223,160 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible {
221223
222224
Swift mangled name:
223225
Imported from:
224-
\(swiftDeclRaw ?? "<no swift source>")
226+
\(syntax?.description ?? "<no swift source>")
227+
}
228+
"""
229+
}
230+
}
231+
232+
public enum VariableAccessorKind {
233+
case get
234+
case set
235+
236+
public var renderDescFieldName: String {
237+
switch self {
238+
case .get: "DESC_GET"
239+
case .set: "DESC_SET"
240+
}
241+
}
242+
}
243+
244+
public struct ImportedVariable: ImportedDecl, CustomStringConvertible {
245+
/// If this function/method is member of a class/struct/protocol,
246+
/// this will contain that declaration's imported name.
247+
///
248+
/// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have.
249+
public var parentName: TranslatedType?
250+
public var hasParent: Bool { parentName != nil }
251+
252+
/// This is a full name such as "counter".
253+
public var identifier: String
254+
255+
/// Which accessors are we able to expose.
256+
///
257+
/// Usually this will be all the accessors the variable declares,
258+
/// however if the getter is async or throwing we may not be able to import it
259+
/// (yet), and therefore would skip it from the supported set.
260+
public var supportedAccessorKinds: Set<VariableAccessorKind> = [.get, .set]
261+
262+
/// This is the base identifier for the function, e.g., "init" for an
263+
/// initializer or "f" for "f(a:b:)".
264+
public var baseIdentifier: String {
265+
guard let idx = identifier.firstIndex(of: "(") else {
266+
return identifier
267+
}
268+
return String(identifier[..<idx])
269+
}
270+
271+
/// A display name to use to refer to the Swift declaration with its
272+
/// enclosing type, if there is one.
273+
public var displayName: String {
274+
if let parentName {
275+
return "\(parentName.swiftTypeName).\(identifier)"
276+
}
277+
278+
return identifier
279+
}
280+
281+
public var returnType: TranslatedType
282+
283+
/// Synthetic signature of an accessor function of the given kind of this property
284+
public func accessorFunc(kind: VariableAccessorKind) -> ImportedFunc? {
285+
guard self.supportedAccessorKinds.contains(kind) else {
286+
return nil
287+
}
288+
289+
switch kind {
290+
case .set:
291+
let newValueParam: FunctionParameterSyntax = "_ newValue: \(self.returnType.cCompatibleSwiftType)"
292+
var funcDecl = ImportedFunc(
293+
parentName: self.parentName,
294+
identifier: self.identifier,
295+
returnType: TranslatedType.void,
296+
parameters: [.init(param: newValueParam, type: self.returnType)])
297+
funcDecl.swiftMangledName = self.swiftMangledName + "s" // form mangled name of the getter by adding the suffix
298+
return funcDecl
299+
300+
case .get:
301+
var funcDecl = ImportedFunc(
302+
parentName: self.parentName,
303+
identifier: self.identifier,
304+
returnType: self.returnType,
305+
parameters: [])
306+
funcDecl.swiftMangledName = self.swiftMangledName + "g" // form mangled name of the getter by adding the suffix
307+
return funcDecl
308+
}
309+
}
310+
311+
public func effectiveAccessorParameters(_ kind: VariableAccessorKind, selfVariant: SelfParameterVariant?) -> [ImportedParam] {
312+
var params: [ImportedParam] = []
313+
314+
if kind == .set {
315+
let newValueParam: FunctionParameterSyntax = "_ newValue: \(raw: self.returnType.swiftTypeName)"
316+
params.append(
317+
ImportedParam(
318+
param: newValueParam,
319+
type: self.returnType)
320+
)
321+
}
322+
323+
if let parentName {
324+
// Add `self: Self` for method calls on a member
325+
//
326+
// allocating initializer takes a Self.Type instead, but it's also a pointer
327+
switch selfVariant {
328+
case nil, .wrapper:
329+
break
330+
331+
case .pointer:
332+
let selfParam: FunctionParameterSyntax = "self$: $swift_pointer"
333+
params.append(
334+
ImportedParam(
335+
param: selfParam,
336+
type: parentName
337+
)
338+
)
339+
340+
case .memorySegment:
341+
let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment"
342+
var parentForSelf = parentName
343+
parentForSelf.javaType = .javaForeignMemorySegment
344+
params.append(
345+
ImportedParam(
346+
param: selfParam,
347+
type: parentForSelf
348+
)
349+
)
350+
}
351+
}
352+
353+
return params
354+
}
355+
356+
public var swiftMangledName: String = ""
357+
358+
public var syntax: VariableDeclSyntax? = nil
359+
360+
public init(
361+
parentName: TranslatedType?,
362+
identifier: String,
363+
returnType: TranslatedType
364+
) {
365+
self.parentName = parentName
366+
self.identifier = identifier
367+
self.returnType = returnType
368+
}
369+
370+
public var description: String {
371+
"""
372+
ImportedFunc {
373+
mangledName: \(swiftMangledName)
374+
identifier: \(identifier)
375+
returnType: \(returnType)
376+
377+
Swift mangled name:
378+
Imported from:
379+
\(syntax?.description ?? "<no swift source>")
225380
}
226381
"""
227382
}

Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ extension Swift2JavaTranslator {
437437
* Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}.
438438
*
439439
* {@snippet lang=swift :
440-
* \(decl.swiftDeclRaw ?? "")
440+
* \(decl.syntax ?? "")
441441
* }
442442
*/
443443
public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) {
@@ -470,7 +470,7 @@ extension Swift2JavaTranslator {
470470
/**
471471
* Function descriptor for:
472472
* {@snippet lang=swift :
473-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
473+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
474474
* }
475475
*/
476476
public static FunctionDescriptor \(decl.baseIdentifier)$descriptor() {
@@ -484,7 +484,7 @@ extension Swift2JavaTranslator {
484484
/**
485485
* Downcall method handle for:
486486
* {@snippet lang=swift :
487-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
487+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
488488
* }
489489
*/
490490
public static MethodHandle \(decl.baseIdentifier)$handle() {
@@ -498,7 +498,7 @@ extension Swift2JavaTranslator {
498498
/**
499499
* Address for:
500500
* {@snippet lang=swift :
501-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
501+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
502502
* }
503503
*/
504504
public static MemorySegment \(decl.baseIdentifier)$address() {
@@ -557,7 +557,7 @@ extension Swift2JavaTranslator {
557557
"""
558558
/**
559559
* {@snippet lang=swift :
560-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
560+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
561561
* }
562562
*/
563563
public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) {
@@ -572,7 +572,60 @@ extension Swift2JavaTranslator {
572572
"""
573573
/**
574574
* {@snippet lang=swift :
575-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
575+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
576+
* }
577+
*/
578+
public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) {
579+
var mh$ = \(decl.baseIdentifier).HANDLE;
580+
try {
581+
if (TRACE_DOWNCALLS) {
582+
traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment)));
583+
}
584+
\(maybeReturnCast) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: selfVariant)));
585+
} catch (Throwable ex$) {
586+
throw new AssertionError("should not reach here", ex$);
587+
}
588+
}
589+
"""
590+
)
591+
}
592+
593+
public func printPropertyAccessorDowncallMethod(
594+
_ printer: inout CodePrinter,
595+
decl: ImportedFunc,
596+
selfVariant: SelfParameterVariant?
597+
) {
598+
let returnTy = decl.returnType.javaType
599+
600+
let maybeReturnCast: String
601+
if decl.returnType.javaType == .void {
602+
maybeReturnCast = "" // nothing to return or cast to
603+
} else {
604+
maybeReturnCast = "return (\(returnTy))"
605+
}
606+
607+
if selfVariant == SelfParameterVariant.wrapper {
608+
// delegate to the MemorySegment "self" accepting overload
609+
printer.print(
610+
"""
611+
/**
612+
* {@snippet lang=swift :
613+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
614+
* }
615+
*/
616+
public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) {
617+
\(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .wrapper)));
618+
}
619+
"""
620+
)
621+
return
622+
}
623+
624+
printer.print(
625+
"""
626+
/**
627+
* {@snippet lang=swift :
628+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
576629
* }
577630
*/
578631
public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) {
@@ -656,8 +709,11 @@ extension Swift2JavaTranslator {
656709
return ps.joined(separator: ", ")
657710
}
658711

659-
public func printFunctionDescriptorValue(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
660-
printer.start("public static final FunctionDescriptor DESC = ")
712+
public func printFunctionDescriptorValue(
713+
_ printer: inout CodePrinter,
714+
_ decl: ImportedFunc,
715+
fieldName: String = "DESC") {
716+
printer.start("public static final FunctionDescriptor \(fieldName) = ")
661717

662718
let parameterLayoutDescriptors = javaMemoryLayoutDescriptors(
663719
forParametersOf: decl,
@@ -692,4 +748,15 @@ extension Swift2JavaTranslator {
692748
printer.outdent();
693749
printer.print(");");
694750
}
751+
752+
public func printPropertyAccessorDescriptorValue(
753+
_ printer: inout CodePrinter,
754+
_ decl: ImportedVariable,
755+
_ kind: VariableAccessorKind) {
756+
guard let funcDecl = decl.accessorFunc(kind: kind) else {
757+
return
758+
}
759+
760+
printFunctionDescriptorValue(&printer, funcDecl, fieldName: kind.renderDescFieldName)
761+
}
695762
}

0 commit comments

Comments
 (0)