Skip to content

Commit 20e3f76

Browse files
committed
Prepare accessor function descriptors for properties: get set
1 parent ddef48a commit 20e3f76

File tree

6 files changed

+393
-48
lines changed

6 files changed

+393
-48
lines changed

Sources/JExtractSwift/ImportedDecls.swift

Lines changed: 152 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,155 @@ 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+
public var supportedAccessorKinds: Set<VariableAccessorKind> = [.get, .set]
256+
257+
/// This is the base identifier for the function, e.g., "init" for an
258+
/// initializer or "f" for "f(a:b:)".
259+
public var baseIdentifier: String {
260+
guard let idx = identifier.firstIndex(of: "(") else {
261+
return identifier
262+
}
263+
return String(identifier[..<idx])
264+
}
265+
266+
/// A display name to use to refer to the Swift declaration with its
267+
/// enclosing type, if there is one.
268+
public var displayName: String {
269+
if let parentName {
270+
return "\(parentName.swiftTypeName).\(identifier)"
271+
}
272+
273+
return identifier
274+
}
275+
276+
public var returnType: TranslatedType
277+
278+
/// Synthetic signature of an accessor function of the given kind of this property
279+
public func accessorFunc(kind: VariableAccessorKind) -> ImportedFunc? {
280+
guard self.supportedAccessorKinds.contains(kind) else {
281+
return nil
282+
}
283+
284+
switch kind {
285+
case .set:
286+
let newValueParam: FunctionParameterSyntax = "_ newValue: \(self.returnType.cCompatibleSwiftType)"
287+
var funcDecl = ImportedFunc(
288+
parentName: self.parentName,
289+
identifier: self.identifier,
290+
returnType: TranslatedType.void,
291+
parameters: [.init(param: newValueParam, type: self.returnType)])
292+
funcDecl.swiftMangledName = self.swiftMangledName + "s" // form mangled name of the getter by adding the suffix
293+
return funcDecl
294+
295+
case .get:
296+
var funcDecl = ImportedFunc(
297+
parentName: self.parentName,
298+
identifier: self.identifier,
299+
returnType: self.returnType,
300+
parameters: [])
301+
funcDecl.swiftMangledName = self.swiftMangledName + "g" // form mangled name of the getter by adding the suffix
302+
return funcDecl
303+
}
304+
}
305+
306+
public func effectiveAccessorParameters(_ kind: VariableAccessorKind, selfVariant: SelfParameterVariant?) -> [ImportedParam] {
307+
var params: [ImportedParam] = []
308+
309+
if kind == .set {
310+
let newValueParam: FunctionParameterSyntax = "_ newValue: \(raw: self.returnType.swiftTypeName)"
311+
params.append(
312+
ImportedParam(
313+
param: newValueParam,
314+
type: self.returnType)
315+
)
316+
}
317+
318+
if let parentName {
319+
// Add `self: Self` for method calls on a member
320+
//
321+
// allocating initializer takes a Self.Type instead, but it's also a pointer
322+
switch selfVariant {
323+
case nil, .wrapper:
324+
break
325+
326+
case .pointer:
327+
let selfParam: FunctionParameterSyntax = "self$: $swift_pointer"
328+
params.append(
329+
ImportedParam(
330+
param: selfParam,
331+
type: parentName
332+
)
333+
)
334+
335+
case .memorySegment:
336+
let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment"
337+
var parentForSelf = parentName
338+
parentForSelf.javaType = .javaForeignMemorySegment
339+
params.append(
340+
ImportedParam(
341+
param: selfParam,
342+
type: parentForSelf
343+
)
344+
)
345+
}
346+
}
347+
348+
return params
349+
}
350+
351+
public var swiftMangledName: String = ""
352+
353+
public var syntax: VariableDeclSyntax? = nil
354+
355+
public init(
356+
parentName: TranslatedType?,
357+
identifier: String,
358+
returnType: TranslatedType
359+
) {
360+
self.parentName = parentName
361+
self.identifier = identifier
362+
self.returnType = returnType
363+
}
364+
365+
public var description: String {
366+
"""
367+
ImportedFunc {
368+
mangledName: \(swiftMangledName)
369+
identifier: \(identifier)
370+
returnType: \(returnType)
371+
372+
Swift mangled name:
373+
Imported from:
374+
\(syntax?.description ?? "<no swift source>")
225375
}
226376
"""
227377
}

Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ extension Swift2JavaTranslator {
428428
* Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}.
429429
*
430430
* {@snippet lang=swift :
431-
* \(decl.swiftDeclRaw ?? "")
431+
* \(decl.syntax ?? "")
432432
* }
433433
*/
434434
public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) {
@@ -461,7 +461,7 @@ extension Swift2JavaTranslator {
461461
/**
462462
* Function descriptor for:
463463
* {@snippet lang=swift :
464-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
464+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
465465
* }
466466
*/
467467
public static FunctionDescriptor \(decl.baseIdentifier)$descriptor() {
@@ -475,7 +475,7 @@ extension Swift2JavaTranslator {
475475
/**
476476
* Downcall method handle for:
477477
* {@snippet lang=swift :
478-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
478+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
479479
* }
480480
*/
481481
public static MethodHandle \(decl.baseIdentifier)$handle() {
@@ -489,7 +489,7 @@ extension Swift2JavaTranslator {
489489
/**
490490
* Address for:
491491
* {@snippet lang=swift :
492-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
492+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
493493
* }
494494
*/
495495
public static MemorySegment \(decl.baseIdentifier)$address() {
@@ -548,7 +548,7 @@ extension Swift2JavaTranslator {
548548
"""
549549
/**
550550
* {@snippet lang=swift :
551-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
551+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
552552
* }
553553
*/
554554
public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) {
@@ -563,7 +563,60 @@ extension Swift2JavaTranslator {
563563
"""
564564
/**
565565
* {@snippet lang=swift :
566-
* \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "")
566+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
567+
* }
568+
*/
569+
public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) {
570+
var mh$ = \(decl.baseIdentifier).HANDLE;
571+
try {
572+
if (TRACE_DOWNCALLS) {
573+
traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment)));
574+
}
575+
\(maybeReturnCast) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: selfVariant)));
576+
} catch (Throwable ex$) {
577+
throw new AssertionError("should not reach here", ex$);
578+
}
579+
}
580+
"""
581+
)
582+
}
583+
584+
public func printPropertyAccessorDowncallMethod(
585+
_ printer: inout CodePrinter,
586+
decl: ImportedFunc,
587+
selfVariant: SelfParameterVariant?
588+
) {
589+
let returnTy = decl.returnType.javaType
590+
591+
let maybeReturnCast: String
592+
if decl.returnType.javaType == .void {
593+
maybeReturnCast = "" // nothing to return or cast to
594+
} else {
595+
maybeReturnCast = "return (\(returnTy))"
596+
}
597+
598+
if selfVariant == SelfParameterVariant.wrapper {
599+
// delegate to the MemorySegment "self" accepting overload
600+
printer.print(
601+
"""
602+
/**
603+
* {@snippet lang=swift :
604+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
605+
* }
606+
*/
607+
public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) {
608+
\(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .wrapper)));
609+
}
610+
"""
611+
)
612+
return
613+
}
614+
615+
printer.print(
616+
"""
617+
/**
618+
* {@snippet lang=swift :
619+
* \(/*TODO: make a printSnippet func*/decl.syntax ?? "")
567620
* }
568621
*/
569622
public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) {
@@ -647,8 +700,11 @@ extension Swift2JavaTranslator {
647700
return ps.joined(separator: ", ")
648701
}
649702

650-
public func printFunctionDescriptorValue(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
651-
printer.start("public static final FunctionDescriptor DESC = ")
703+
public func printFunctionDescriptorValue(
704+
_ printer: inout CodePrinter,
705+
_ decl: ImportedFunc,
706+
fieldName: String = "DESC") {
707+
printer.start("public static final FunctionDescriptor \(fieldName) = ")
652708

653709
let parameterLayoutDescriptors = javaMemoryLayoutDescriptors(
654710
forParametersOf: decl,
@@ -683,4 +739,15 @@ extension Swift2JavaTranslator {
683739
printer.outdent();
684740
printer.print(");");
685741
}
742+
743+
public func printPropertyAccessorDescriptorValue(
744+
_ printer: inout CodePrinter,
745+
_ decl: ImportedVariable,
746+
_ kind: VariableAccessorKind) {
747+
guard let funcDecl = decl.accessorFunc(kind: kind) else {
748+
return
749+
}
750+
751+
printFunctionDescriptorValue(&printer, funcDecl, fieldName: kind.renderDescFieldName)
752+
}
686753
}

0 commit comments

Comments
 (0)