mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
native: pass argument specs in order to support varadic ffi
This commit is contained in:
parent
8d310e337a
commit
2ee1565fb5
@ -9,7 +9,7 @@ class FunctionContext(val compilationUnitContext: CompilationUnitContext, val no
|
|||||||
val native = node.native!!
|
val native = node.native!!
|
||||||
val nativeFunctionProvider =
|
val nativeFunctionProvider =
|
||||||
compilationUnitContext.evaluator.nativeFunctionProvider(native.form.id)
|
compilationUnitContext.evaluator.nativeFunctionProvider(native.form.id)
|
||||||
nativeFunctionProvider.provideNativeFunction(native.definition.text)
|
nativeFunctionProvider.provideNativeFunction(native.definition.text, node.arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val nativeCached by lazy { resolveMaybeNative() }
|
private val nativeCached by lazy { resolveMaybeNative() }
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package gay.pizza.pork.evaluator
|
package gay.pizza.pork.evaluator
|
||||||
|
|
||||||
|
import gay.pizza.pork.ast.ArgumentSpec
|
||||||
|
|
||||||
class InternalNativeProvider(val quiet: Boolean = false) : NativeProvider {
|
class InternalNativeProvider(val quiet: Boolean = false) : NativeProvider {
|
||||||
private val functions = mutableMapOf(
|
private val functions = mutableMapOf(
|
||||||
"print" to CallableFunction(::printValues),
|
"print" to CallableFunction(::printValues),
|
||||||
"println" to CallableFunction(::printLine)
|
"println" to CallableFunction(::printLine)
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
override fun provideNativeFunction(definition: String, arguments: List<ArgumentSpec>): CallableFunction {
|
||||||
return functions[definition] ?: throw RuntimeException("Unknown Internal Function: $definition")
|
return functions[definition] ?: throw RuntimeException("Unknown Internal Function: $definition")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package gay.pizza.pork.evaluator
|
package gay.pizza.pork.evaluator
|
||||||
|
|
||||||
|
import gay.pizza.pork.ast.ArgumentSpec
|
||||||
|
|
||||||
interface NativeProvider {
|
interface NativeProvider {
|
||||||
fun provideNativeFunction(definition: String): CallableFunction
|
fun provideNativeFunction(definition: String, arguments: List<ArgumentSpec>): CallableFunction
|
||||||
}
|
}
|
||||||
|
5
examples/printf.pork
Normal file
5
examples/printf.pork
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import std ffi.printf
|
||||||
|
|
||||||
|
export func main() {
|
||||||
|
printf("Hello World: %s\n", "Jolk")
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package gay.pizza.pork.ffi
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
|
import gay.pizza.pork.ast.ArgumentSpec
|
||||||
import gay.pizza.pork.evaluator.CallableFunction
|
import gay.pizza.pork.evaluator.CallableFunction
|
||||||
import gay.pizza.pork.evaluator.NativeProvider
|
import gay.pizza.pork.evaluator.NativeProvider
|
||||||
import gay.pizza.pork.evaluator.None
|
import gay.pizza.pork.evaluator.None
|
||||||
@ -9,7 +10,7 @@ import java.lang.invoke.MethodType
|
|||||||
class JavaNativeProvider : NativeProvider {
|
class JavaNativeProvider : NativeProvider {
|
||||||
private val lookup = MethodHandles.lookup()
|
private val lookup = MethodHandles.lookup()
|
||||||
|
|
||||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
override fun provideNativeFunction(definition: String, arguments: List<ArgumentSpec>): CallableFunction {
|
||||||
val functionDefinition = JavaFunctionDefinition.parse(definition)
|
val functionDefinition = JavaFunctionDefinition.parse(definition)
|
||||||
val javaClass = lookupClass(functionDefinition.type)
|
val javaClass = lookupClass(functionDefinition.type)
|
||||||
val returnTypeClass = lookupClass(functionDefinition.returnType)
|
val returnTypeClass = lookupClass(functionDefinition.returnType)
|
||||||
@ -21,7 +22,7 @@ class JavaNativeProvider : NativeProvider {
|
|||||||
returnTypeClass,
|
returnTypeClass,
|
||||||
parameterClasses
|
parameterClasses
|
||||||
)
|
)
|
||||||
return CallableFunction { arguments -> handle.invokeWithArguments(arguments.values) ?: None }
|
return CallableFunction { functionArguments -> handle.invokeWithArguments(functionArguments.values) ?: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lookupClass(name: String): Class<*> = when (name) {
|
private fun lookupClass(name: String): Class<*> = when (name) {
|
||||||
|
@ -1,19 +1,31 @@
|
|||||||
package gay.pizza.pork.ffi
|
package gay.pizza.pork.ffi
|
||||||
|
|
||||||
import com.sun.jna.Function
|
import com.sun.jna.Function
|
||||||
|
import gay.pizza.pork.ast.ArgumentSpec
|
||||||
import gay.pizza.pork.evaluator.CallableFunction
|
import gay.pizza.pork.evaluator.CallableFunction
|
||||||
import gay.pizza.pork.evaluator.NativeProvider
|
import gay.pizza.pork.evaluator.NativeProvider
|
||||||
|
|
||||||
class JnaNativeProvider : NativeProvider {
|
class JnaNativeProvider : NativeProvider {
|
||||||
override fun provideNativeFunction(definition: String): CallableFunction {
|
override fun provideNativeFunction(definition: String, arguments: List<ArgumentSpec>): CallableFunction {
|
||||||
val functionDefinition = FfiFunctionDefinition.parse(definition)
|
val functionDefinition = FfiFunctionDefinition.parse(definition)
|
||||||
val function = Function.getFunction(functionDefinition.library, functionDefinition.function)
|
val function = Function.getFunction(functionDefinition.library, functionDefinition.function)
|
||||||
return CallableFunction {
|
return CallableFunction { functionArgs ->
|
||||||
invoke(function, it.values.toTypedArray(), functionDefinition.returnType)
|
val ffiArgs = mutableListOf<Any?>()
|
||||||
|
for ((index, spec) in arguments.withIndex()) {
|
||||||
|
if (spec.multiple) {
|
||||||
|
val variableArguments = functionArgs.values
|
||||||
|
.subList(index, functionArgs.values.size)
|
||||||
|
ffiArgs.addAll(variableArguments)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
ffiArgs.add(functionArgs.values[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invoke(function, ffiArgs.toTypedArray(), functionDefinition.returnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invoke(function: Function, values: Array<Any>, type: String): Any = when (type) {
|
private fun invoke(function: Function, values: Array<Any?>, type: String): Any = when (type) {
|
||||||
"void*" -> function.invokePointer(values)
|
"void*" -> function.invokePointer(values)
|
||||||
"int" -> function.invokeInt(values)
|
"int" -> function.invokeInt(values)
|
||||||
"long" -> function.invokeLong(values)
|
"long" -> function.invokeLong(values)
|
||||||
|
2
stdlib/src/main/pork/ffi/printf.pork
Normal file
2
stdlib/src/main/pork/ffi/printf.pork
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export func printf(format, arguments...)
|
||||||
|
native ffi "c:printf:int:char*,..."
|
Loading…
Reference in New Issue
Block a user