-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ffi: support for java native functions
- Loading branch information
Showing
6 changed files
with
100 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
func java_system_err() | ||
native java "java.lang.System:static-getter:err:java.io.PrintStream" | ||
|
||
func print_stream_println(stream, line) | ||
native java "java.io.PrintStream:virtual:println:void:java.lang.String" | ||
|
||
export func main() { | ||
let error = java_system_err() | ||
print_stream_println(error, "Hello World") | ||
} |
20 changes: 20 additions & 0 deletions
20
ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiFunctionDefinition.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package gay.pizza.pork.ffi | ||
|
||
class FfiFunctionDefinition( | ||
val library: String, | ||
val function: String, | ||
val returnType: String | ||
) { | ||
companion object { | ||
fun parse(def: String): FfiFunctionDefinition { | ||
val parts = def.split(":", limit = 3) | ||
if (parts.size != 3 || parts.any { it.trim().isEmpty() }) { | ||
throw RuntimeException( | ||
"FFI function definition is invalid, " + | ||
"excepted format is 'library:function:return-type' but '${def}' was specified") | ||
} | ||
val (library, function, returnType) = parts | ||
return FfiFunctionDefinition(library, function, returnType) | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaFunctionDefinition.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package gay.pizza.pork.ffi | ||
|
||
class JavaFunctionDefinition( | ||
val type: String, | ||
val kind: String, | ||
val symbol: String, | ||
val returnType: String, | ||
val parameters: List<String> | ||
) { | ||
companion object { | ||
fun parse(def: String): JavaFunctionDefinition { | ||
val parts = def.split(":", limit = 5) | ||
if (!(parts.size == 4 || parts.size == 5) || parts.any { it.trim().isEmpty() }) { | ||
throw RuntimeException( | ||
"Java function definition is invalid, " + | ||
"excepted format is 'type:kind:symbol:return-type:(optional)parameters' but '${def}' was specified") | ||
} | ||
val (type, kind, symbol, returnType) = parts | ||
val parameters = if (parts.size > 4) parts[4].split(",") else emptyList() | ||
return JavaFunctionDefinition(type, kind, symbol, returnType, parameters) | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package gay.pizza.pork.ffi | ||
|
||
import gay.pizza.pork.evaluator.CallableFunction | ||
import gay.pizza.pork.evaluator.NativeFunctionProvider | ||
import gay.pizza.pork.evaluator.None | ||
import java.lang.invoke.MethodHandles | ||
import java.lang.invoke.MethodType | ||
|
||
class JavaNativeProvider : NativeFunctionProvider { | ||
private val lookup = MethodHandles.lookup() | ||
|
||
override fun provideNativeFunction(definition: String): CallableFunction { | ||
val functionDefinition = JavaFunctionDefinition.parse(definition) | ||
val javaClass = lookupClass(functionDefinition.type) | ||
val returnTypeClass = lookupClass(functionDefinition.returnType) | ||
val parameterClasses = functionDefinition.parameters.map { lookup.findClass(it) } | ||
val handle = mapKindToHandle( | ||
functionDefinition.kind, | ||
functionDefinition.symbol, | ||
javaClass, | ||
returnTypeClass, | ||
parameterClasses | ||
) | ||
return CallableFunction { arguments -> handle.invokeWithArguments(arguments.values) ?: None } | ||
} | ||
|
||
private fun lookupClass(name: String): Class<*> = when (name) { | ||
"void" -> Void.TYPE | ||
else -> lookup.findClass(name) | ||
} | ||
|
||
private fun mapKindToHandle(kind: String, symbol: String, javaClass: Class<*>, returnType: Class<*>, parameterTypes: List<Class<*>>) = when (kind) { | ||
"getter" -> lookup.findGetter(javaClass, symbol, returnType) | ||
"setter" -> lookup.findSetter(javaClass, symbol, returnType) | ||
"constructor" -> lookup.findConstructor(javaClass, MethodType.methodType(returnType, parameterTypes)) | ||
"static" -> lookup.findStatic(javaClass, symbol, MethodType.methodType(returnType, parameterTypes)) | ||
"virtual" -> lookup.findVirtual(javaClass, symbol, MethodType.methodType(returnType, parameterTypes)) | ||
"static-getter" -> lookup.findStaticGetter(javaClass, symbol, returnType) | ||
"static-setter" -> lookup.findStaticSetter(javaClass, symbol, returnType) | ||
else -> throw RuntimeException("Unknown Handle Kind: $kind") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters