diff --git a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/AdaptedNativeProvider.kt b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/AdaptedNativeProvider.kt index b82a229..c7d3ece 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/AdaptedNativeProvider.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/AdaptedNativeProvider.kt @@ -1,7 +1,9 @@ package gay.pizza.pork.evaluator import gay.pizza.pork.ast.gen.ArgumentSpec +import gay.pizza.pork.execution.NativeFunction import gay.pizza.pork.execution.NativeProvider +import gay.pizza.pork.execution.NativeType class AdaptedNativeProvider(val provider: NativeProvider) : ExpandedNativeProvider { override fun provideNativeFunction( @@ -12,4 +14,12 @@ class AdaptedNativeProvider(val provider: NativeProvider) : ExpandedNativeProvid val function = provider.provideNativeFunction(definitions) return CallableFunction { args, _ -> function.invoke(args) } } + + override fun provideNativeFunction(definitions: List): NativeFunction { + return provider.provideNativeFunction(definitions) + } + + override fun provideNativeType(definitions: List): NativeType { + return provider.provideNativeType(definitions) + } } diff --git a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/ExpandedNativeProvider.kt b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/ExpandedNativeProvider.kt index 4b44dbb..f4b7b64 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/ExpandedNativeProvider.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/ExpandedNativeProvider.kt @@ -1,7 +1,12 @@ package gay.pizza.pork.evaluator import gay.pizza.pork.ast.gen.ArgumentSpec +import gay.pizza.pork.execution.NativeProvider -interface ExpandedNativeProvider { - fun provideNativeFunction(definitions: List, arguments: List, inside: SlabContext): CallableFunction +interface ExpandedNativeProvider: NativeProvider { + fun provideNativeFunction(definitions: List, arguments: List, inside: SlabContext): CallableFunction { + val function = provideNativeFunction(definitions) + return CallableFunction { arguments, _ -> function.invoke(arguments) } + } } + diff --git a/examples/java.pork b/examples/java.pork index f99437b..3f20968 100644 --- a/examples/java.pork +++ b/examples/java.pork @@ -3,6 +3,7 @@ import java java.lang.System import java java.io.PrintStream export func main() { + println(java_lang_System) let stream = java_lang_System_err_get() java_io_PrintStream_println_string(stream, "Hello World") let pi = java_lang_Math_PI_get() diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaAutogen.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaAutogen.kt index d56b4bc..98c9e3c 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaAutogen.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaAutogen.kt @@ -11,7 +11,18 @@ class JavaAutogen(val javaClass: Class<*>) { fun generateCompilationUnit(): CompilationUnit { return CompilationUnit( declarations = listOf(), - definitions = generateFunctionDefinitions() + definitions = generateFunctionDefinitions() + generateTypeDefinition() + ) + } + + fun generateTypeDefinition(): TypeDefinition { + return TypeDefinition( + modifiers = DefinitionModifiers(export = true), + symbol = Symbol(prefix), + nativeTypeDescriptor = NativeTypeDescriptor( + form = Symbol("java"), + definitions = listOf(StringLiteral(javaClass.name)), + ) ) } @@ -50,7 +61,9 @@ class JavaAutogen(val javaClass: Class<*>) { if (Modifier.isStatic(method.modifiers)) { definitions[name] = function(name, parameterNames, form("static")) } else { - definitions[name] = function(name, parameterNames, form("virtual")) + val finalParameterNames = parameterNames.toMutableList() + finalParameterNames.add(0, "__instance") + definitions[name] = function(name, finalParameterNames, form("virtual")) } } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt index e388ea9..11b7c5a 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeProvider.kt @@ -1,8 +1,5 @@ package gay.pizza.pork.ffi -import gay.pizza.pork.ast.gen.ArgumentSpec -import gay.pizza.pork.evaluator.CallableFunction -import gay.pizza.pork.evaluator.SlabContext import gay.pizza.pork.evaluator.ExpandedNativeProvider import gay.pizza.pork.execution.NativeFunction import gay.pizza.pork.execution.NativeProvider @@ -14,25 +11,6 @@ import java.lang.invoke.MethodType class JavaNativeProvider : ExpandedNativeProvider, NativeProvider { private val lookup = MethodHandles.lookup() - override fun provideNativeFunction( - definitions: List, - arguments: List, - inside: SlabContext - ): CallableFunction { - val functionDefinition = JavaFunctionDefinition.parse(definitions) - val javaClass = lookupClass(functionDefinition.type) - val returnTypeClass = lookupClass(functionDefinition.returnType) - val parameterClasses = functionDefinition.parameters.map { lookupClass(it) } - val handle = mapKindToHandle( - functionDefinition.kind, - functionDefinition.symbol, - javaClass, - returnTypeClass, - parameterClasses - ) - return CallableFunction { functionArguments, _ -> handle.invokeWithArguments(functionArguments) ?: None } - } - private fun lookupClass(name: String): Class<*> = when (name) { "void" -> Void.TYPE "String" -> String::class.java @@ -67,10 +45,23 @@ class JavaNativeProvider : ExpandedNativeProvider, NativeProvider { } override fun provideNativeFunction(definitions: List): NativeFunction { - throw RuntimeException("Invalid Native Function Usage") + val functionDefinition = JavaFunctionDefinition.parse(definitions) + val javaClass = lookupClass(functionDefinition.type) + val returnTypeClass = lookupClass(functionDefinition.returnType) + val parameterClasses = functionDefinition.parameters.map { lookupClass(it) } + val handle = mapKindToHandle( + functionDefinition.kind, + functionDefinition.symbol, + javaClass, + returnTypeClass, + parameterClasses + ) + return NativeFunction { functionArguments -> handle.invokeWithArguments(functionArguments) ?: None } } override fun provideNativeType(definitions: List): NativeType { - throw RuntimeException("Invalid Native Type Usage") + val className = definitions[0] + val javaClass = Class.forName(className) + return JavaNativeType(javaClass) } } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeType.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeType.kt new file mode 100644 index 0000000..74f40be --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JavaNativeType.kt @@ -0,0 +1,9 @@ +package gay.pizza.pork.ffi + +import gay.pizza.pork.execution.NativeType + +class JavaNativeType(val wrappedJavaClass: Class<*>) : NativeType { + override fun value(): Any { + return wrappedJavaClass + } +} diff --git a/frontend/src/main/kotlin/gay/pizza/pork/frontend/scope/ExternalSymbolUsageAnalyzer.kt b/frontend/src/main/kotlin/gay/pizza/pork/frontend/scope/ExternalSymbolUsageAnalyzer.kt index 5f01bc5..8c67376 100644 --- a/frontend/src/main/kotlin/gay/pizza/pork/frontend/scope/ExternalSymbolUsageAnalyzer.kt +++ b/frontend/src/main/kotlin/gay/pizza/pork/frontend/scope/ExternalSymbolUsageAnalyzer.kt @@ -12,7 +12,9 @@ class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor() { override fun visitFunctionDefinition(node: FunctionDefinition) { for (argument in node.arguments) { - visit(argument.typeSpec!!) + if (argument.typeSpec != null) { + visit(argument.typeSpec!!) + } } if (node.returnType != null) {