@@ -19,7 +19,7 @@ extension Swift2JavaTranslator {
1919 _ printer: inout CodePrinter ,
2020 _ decl: ImportedFunc
2121 ) {
22- guard let _ = translatedSignature ( for: decl) else {
22+ guard let _ = translatedDecl ( for: decl) else {
2323 // Failed to translate. Skip.
2424 return
2525 }
@@ -28,6 +28,8 @@ extension Swift2JavaTranslator {
2828
2929 printJavaBindingDescriptorClass ( & printer, decl)
3030
31+ printJavaBindingWrapperHelperClass ( & printer, decl)
32+
3133 // Render the "make the downcall" functions.
3234 printJavaBindingWrapperMethod ( & printer, decl)
3335 }
@@ -38,9 +40,9 @@ extension Swift2JavaTranslator {
3840 _ decl: ImportedFunc
3941 ) {
4042 let thunkName = thunkNameRegistry. functionThunkName ( decl: decl)
41- let translatedSignature = self . translatedSignature ( for: decl) !
43+ let translated = self . translatedDecl ( for: decl) !
4244 // 'try!' because we know 'loweredSignature' can be described with C.
43- let cFunc = try ! translatedSignature . loweredSignature. cFunctionDecl ( cName: thunkName)
45+ let cFunc = try ! translated . loweredSignature. cFunctionDecl ( cName: thunkName)
4446
4547 printer. printBraceBlock (
4648 """
@@ -52,37 +54,39 @@ extension Swift2JavaTranslator {
5254 private static class \( cFunc. name)
5355 """
5456 ) { printer in
55- printFunctionDescriptorValue ( & printer, cFunc)
57+ printFunctionDescriptorDefinition ( & printer, cFunc. resultType , cFunc . parameters )
5658 printer. print (
5759 """
58- public static final MemorySegment ADDR =
60+ private static final MemorySegment ADDR =
5961 \( self . swiftModuleName) .findOrThrow( " \( cFunc. name) " );
60- public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
62+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
6163 """
6264 )
6365 printJavaBindingDowncallMethod ( & printer, cFunc)
66+ printParameterDescriptorClasses ( & printer, cFunc)
6467 }
6568 }
6669
6770 /// Print the 'FunctionDescriptor' of the lowered cdecl thunk.
68- func printFunctionDescriptorValue (
71+ func printFunctionDescriptorDefinition (
6972 _ printer: inout CodePrinter ,
70- _ cFunc: CFunction
73+ _ resultType: CType ,
74+ _ parameters: [ CParameter ]
7175 ) {
72- printer. start ( " public static final FunctionDescriptor DESC = " )
76+ printer. start ( " private static final FunctionDescriptor DESC = " )
7377
74- let isEmptyParam = cFunc . parameters. isEmpty
75- if cFunc . resultType. isVoid {
78+ let isEmptyParam = parameters. isEmpty
79+ if resultType. isVoid {
7680 printer. print ( " FunctionDescriptor.ofVoid( " , isEmptyParam ? . continue : . newLine)
7781 printer. indent ( )
7882 } else {
7983 printer. print ( " FunctionDescriptor.of( " )
8084 printer. indent ( )
8185 printer. print ( " /* -> */" , . continue)
82- printer. print ( cFunc . resultType. foreignValueLayout, . parameterNewlineSeparator( isEmptyParam) )
86+ printer. print ( resultType. foreignValueLayout, . parameterNewlineSeparator( isEmptyParam) )
8387 }
8488
85- for (param, isLast) in cFunc . parameters. withIsLast {
89+ for (param, isLast) in parameters. withIsLast {
8690 printer. print ( " /* \(param.name ?? "_"): */" , . continue)
8791 printer. print ( param. type. foreignValueLayout, . parameterNewlineSeparator( isLast) )
8892 }
@@ -124,16 +128,143 @@ extension Swift2JavaTranslator {
124128 )
125129 }
126130
131+ func printParameterDescriptorClasses(
132+ _ printer: inout CodePrinter ,
133+ _ cFunc: CFunction
134+ ) {
135+ for param in cFunc. parameters {
136+ switch param. type {
137+ case . pointer( . function) :
138+ let name = " $ \( param. name!) "
139+ printFunctionPointerParameterDescriptorClass ( & printer, name, param. type)
140+ default :
141+ continue
142+ }
143+ }
144+ }
145+
146+ /// Print a class describing a closure parameter type.
147+ /// ```
148+ /// class <paramter-name> {
149+ /// interface Function {
150+ /// <return-type> apply(<parameters>);
151+ /// }
152+ /// static final MethodDescriptor DESC = FunctionDescriptor.of(...);s
153+ /// static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC);
154+ /// static MemorySegment toUpcallStub(Function fi, Arena arena) {
155+ /// return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
156+ /// }
157+ /// }
158+ /// ```
159+ func printFunctionPointerParameterDescriptorClass(
160+ _ printer: inout CodePrinter ,
161+ _ name: String ,
162+ _ cType: CType
163+ ) {
164+ guard case . pointer( . function( let cResultType, let cParameterTypes, variadic: false ) ) = cType else {
165+ preconditionFailure ( " must be a C function pointer type " )
166+ }
167+
168+ let cParams = cParameterTypes. enumerated ( ) . map { i, ty in
169+ CParameter ( name: " _ \( i) " , type: ty)
170+ }
171+ let paramDecls = cParams. map ( { " \( $0. type. javaType) \( $0. name!) " } )
172+
173+ printer. printBraceBlock (
174+ """
175+ /**
176+ * {snippet lang=c :
177+ * \(cType)
178+ * }
179+ */
180+ private static class \( name)
181+ """
182+ ) { printer in
183+ printer. print (
184+ """
185+ public interface Function {
186+ \( cResultType. javaType) apply( \( paramDecls. joined ( separator: " , " ) ) );
187+ }
188+ """
189+ )
190+ printFunctionDescriptorDefinition ( & printer, cResultType, cParams)
191+ printer. print (
192+ """
193+ private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, " apply " , DESC);
194+ private static MemorySegment toUpcallStub(Function fi, Arena arena) {
195+ return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
196+ }
197+ """
198+ )
199+ }
200+ }
201+
202+ func printJavaBindingWrapperHelperClass(
203+ _ printer: inout CodePrinter ,
204+ _ decl: ImportedFunc
205+ ) {
206+ let translated = self . translatedDecl ( for: decl) !
207+ let bindingDescriptorName = self . thunkNameRegistry. functionThunkName ( decl: decl)
208+ if translated. functionTypes. isEmpty {
209+ return
210+ }
211+
212+ printer. printBraceBlock (
213+ """
214+ public static class \( translated. name)
215+ """
216+ ) { printer in
217+ for functionType in translated. functionTypes {
218+ printJavaBindingWrapperFunctionTypeHelper ( & printer, functionType, bindingDescriptorName)
219+ }
220+ }
221+ }
222+
223+ func printJavaBindingWrapperFunctionTypeHelper(
224+ _ printer: inout CodePrinter ,
225+ _ functionType: TranslatedFunctionType ,
226+ _ bindingDescriptorName: String
227+ ) {
228+ let cdeclDescritor = " \( bindingDescriptorName) .$ \( functionType. name) "
229+ if functionType. isTrivial {
230+ printer. print (
231+ """
232+ public interface \( functionType. name) extends \( cdeclDescritor) .Function {
233+ default MemorySegment toUpcallStub(Arena arena) {
234+ return \( bindingDescriptorName) .$ \( functionType. name) .toUpcallStub(this, arena);
235+ }
236+ }
237+ """
238+ )
239+ } else {
240+ assertionFailure ( " should be unreachable at this point " )
241+ let apiParams = functionType. parameters. flatMap {
242+ $0. javaParameters. map { param in " \( param. type) \( param. name) " }
243+ }
244+
245+ printer. print (
246+ """
247+ public interface \( functionType. name) {
248+ \( functionType. result. javaResultType) apply( \( apiParams. joined ( separator: " , " ) ) );
249+ private default MemorySegment toUpcallStub(Arena arena) {
250+ return \( cdeclDescritor) .toUpcallStub((<cdecl-params>) -> {
251+ <maybe-return> fi(<converted-args>)
252+ }, arena);
253+ }
254+ }
255+ """
256+ )
257+ }
258+ }
259+
127260 /// Print the calling body that forwards all the parameters to the `methodName`,
128261 /// with adding `SwiftArena.ofAuto()` at the end.
129262 public func printJavaBindingWrapperMethod(
130263 _ printer: inout CodePrinter ,
131- _ decl: ImportedFunc ) {
132- let methodName : String = switch decl. apiKind {
133- case . getter: " get \( decl. name. toCamelCase) "
134- case . setter: " set \( decl. name. toCamelCase) "
135- case . function, . initializer: decl. name
136- }
264+ _ decl: ImportedFunc
265+ ) {
266+ let translated = self . translatedDecl ( for: decl) !
267+ let methodName = translated. name
137268
138269 var modifiers = " public "
139270 switch decl. functionSignature. selfParameter {
@@ -143,7 +274,7 @@ extension Swift2JavaTranslator {
143274 break
144275 }
145276
146- let translatedSignature = self . translatedSignature ( for : decl ) !
277+ let translatedSignature = translated . translatedSignature
147278 let returnTy = translatedSignature. result. javaResultType
148279
149280 var paramDecls = translatedSignature. parameters
@@ -182,7 +313,7 @@ extension Swift2JavaTranslator {
182313 _ decl: ImportedFunc
183314 ) {
184315 //=== Part 1: prepare temporary arena if needed.
185- let translatedSignature = self . translatedSignature ( for: decl) !
316+ let translatedSignature = self . translatedDecl ( for: decl) !. translatedSignature
186317
187318 if translatedSignature. requiresTemporaryArena {
188319 printer. print ( " try(var arena$ = Arena.ofConfined()) { " )
@@ -273,7 +404,7 @@ extension JavaConversionStep {
273404 /// Whether the conversion uses SwiftArena.
274405 var requiresSwiftArena : Bool {
275406 switch self {
276- case . pass, . swiftValueSelfSegment, . construct, . cast, . call:
407+ case . pass, . swiftValueSelfSegment, . construct, . cast, . call, . method :
277408 return false
278409 case . constructSwiftValue:
279410 return true
@@ -285,7 +416,7 @@ extension JavaConversionStep {
285416 switch self {
286417 case . pass, . swiftValueSelfSegment, . construct, . constructSwiftValue, . cast:
287418 return false
288- case . call( _, let withArena) :
419+ case . call( _, let withArena) , . method ( _ , _ , let withArena ) :
289420 return withArena
290421 }
291422 }
@@ -297,7 +428,7 @@ extension JavaConversionStep {
297428 switch self {
298429 case . pass, . swiftValueSelfSegment:
299430 return true
300- case . cast, . construct, . constructSwiftValue, . call:
431+ case . cast, . construct, . constructSwiftValue, . call, . method :
301432 return false
302433 }
303434 }
@@ -317,6 +448,10 @@ extension JavaConversionStep {
317448 let arenaArg = withArena ? " , arena$ " : " "
318449 return " \( function) ( \( placeholder) \( arenaArg) ) "
319450
451+ case . method( let methodName, let arguments, let withArena) :
452+ let argsStr = ( arguments + ( withArena ? [ " arena$ " ] : [ ] ) ) . joined ( separator: " , " )
453+ return " \( placeholder) . \( methodName) ( \( argsStr) ) "
454+
320455 case . constructSwiftValue( let javaType) :
321456 return " new \( javaType. className!) ( \( placeholder) , swiftArena$) "
322457
0 commit comments