Hi :wave: I'm working on a small project to create...
# compiler
l
Hi 👋 I'm working on a small project to create a rules engine. The users of the API would be able to submit snippets of code as well as a data schema, which would then be compiled into bytes and returned. A separate API would receive the compiled bytes and run it. I was originally looking at using Google CELs java library and C# Roslyn to achieve my goals but I'd prefer to do it in Kotlin utilizing the K2 compiler. I have a fairly simplistic initial implementation with a hardcoded schema:
Copy code
data class UserSchema(
    val foo: String,
    val bar: Long,
)

class RuntimeKotlinCompiler {
    private class ByteArrayClassLoader(private val classBytes: ByteArray) : ClassLoader() {
        override fun findClass(name: String): Class<*> {
            return defineClass(name, classBytes, 0, classBytes.size)
        }
    }

    private val template = """
        import kotlin.Boolean
        
        class UserRule {
            fun evaluate(transaction: ${UserSchema::class.qualifiedName}): Boolean {
                return %s
            }
        }
    """.trimIndent()

    fun compileKotlinCode(userCode: String): ByteArray {
        val fullCode = template.format(userCode)
        val tempDir = createTempDirectory()
        val sourceFile = File(tempDir, "UserRule.kt").apply {
            writeText(fullCode)
        }

        val messageCollector = object : MessageCollector {
            override fun clear() {}
            override fun hasErrors(): Boolean = false
            override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
                if (severity == CompilerMessageSeverity.ERROR) {
                    throw RuntimeException("Compilation error: $message")
                }
            }
        }

        val compiler = K2JVMCompiler()
        val arguments = K2JVMCompilerArguments().apply {
            destination = tempDir.absolutePath
            classpath = System.getProperty("java.class.path")
            jvmTarget = "1.8"
            noStdlib = true
            noReflect = true
            freeArgs = listOf(sourceFile.absolutePath)
        }

        val exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments)
        if (exitCode.code != 0) {
            throw RuntimeException("Compilation failed with exit code: $exitCode")
        }

        val compiledFile = File(tempDir, "UserRule.class")
        return compiledFile.readBytes().also {
            tempDir.deleteRecursively()
        }
    }

    private fun createTempDirectory(): File {
        return File.createTempFile("kotlin-compiler", "").let { file ->
            file.delete()
            file.mkdir()
            file
        }
    }

    fun executeCompiledCode(compiledBytes: ByteArray, userSchema: UserSchema): Boolean {
        val classLoader = ByteArrayClassLoader(compiledBytes)
        val userRuleClass = classLoader.loadClass("UserRule")
        val instance = userRuleClass.getDeclaredConstructor().newInstance()
        val evaluateMethod = userRuleClass.getMethod("evaluate", UserSchema::class.java)

        return evaluateMethod.invoke(instance, userSchema) as Boolean
    }
}
The newb help link in the channel is 4 years old now. I'm wondering where the best resources are now for getting to grips with the compiler for this type of project so i can expand on it?