Description
I'm trying to build the simplest possible language on top of Truffle framework, but fail. This is how my build.gradle.kts looks like:
plugins {
kotlin("jvm") version "2.0.21"
id("antlr")
id("com.strumenta.antlr-kotlin") version "1.0.0"
}
group = "pro.stery.core"
version = "1.0.2"
repositories {
mavenCentral()
}
dependencies {
antlr("org.antlr:antlr4:4.13.2")
implementation("com.strumenta:antlr-kotlin-runtime:1.0.0")
implementation("org.graalvm.sdk:graal-sdk:24.0.0")
implementation("org.graalvm.truffle:truffle-api:24.0.0")
implementation("org.graalvm.compiler:compiler:24.0.0")
implementation("javax.annotation:javax.annotation-api:1.3.2")
implementation("com.google.code.findbugs:jsr305:3.0.2")
annotationProcessor("org.graalvm.truffle:truffle-dsl-processor:24.0.0")
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation(kotlin("test"))
}
sourceSets["main"].java.srcDir("build/generated-src/antlr/main")
tasks.register<com.strumenta.antlrkotlin.gradle.AntlrKotlinTask>("generateKotlinGrammarSource") {
maxHeapSize = "64m"
packageName = "pro.stery.core.parser.antlr"
arguments = listOf("-visitor")
source = project.objects
.sourceDirectorySet("antlr", "antlr")
.srcDir("src/main/antlr").apply {
include("*.g4")
}
outputDirectory = File("build/generated-src/antlr/main")
//outputDirectory = File("src/build/generated-src")
}
tasks.named("generateGrammarSource").configure {
enabled = false
}
tasks.named("compileKotlin") {
dependsOn(tasks.named("generateKotlinGrammarSource"))
}
tasks.test {
useJUnitPlatform()
//jvmArgs("-ea", "-Dgraalvm.locatorDisabled=true", "--add-exports", "org.graalvm.truffle/com.oracle.truffle.api=ALL-UNNAMED",
//"--add-exports", "org.graalvm.truffle/com.oracle.truffle.api.nodes=ALL-UNNAMED", "--add-exports",
//"org.graalvm.truffle/com.oracle.truffle.api.staticobject=ALL-UNNAMED')")
}
tasks.withType<Test> {
testLogging {
events("passed", "skipped", "failed") // Make sure test results are shown
showStandardStreams = true // This ensures that your println statements are shown
}
}
kotlin {
jvmToolchain(21)
}
And these are my classes. First one defines some metadata about language
package pro.stery.core
object LanguageInfo {
const val ID: String = "stery"
const val NAME: String = "stery"
const val IMPLEMENTATION: String = "SteryRuntime"
const val VERSION: String = "0.0.1"
const val MIME_TYPE: String = "application/x-stery"
const val FILE_EXTENSION: String = ".stery"
}
Custome context class:
package pro.stery.core.runtime
import com.oracle.truffle.api.TruffleLanguage.ContextReference
import com.oracle.truffle.api.nodes.Node
class VmContext {
private lateinit var holder: Holder
companion object {
val REFERENCE: ContextReference<VmContext> = ContextReference.create(VmLanguage::class.java)
fun get(node: Node?): VmContext {
return REFERENCE[node]
}
}
class Holder(
) {
}
fun initialize(holder: Holder) {
this.holder = holder
}
}
And the language class itself:
package pro.stery.core.runtime
import com.oracle.truffle.api.CallTarget
import com.oracle.truffle.api.TruffleLanguage
import com.oracle.truffle.api.nodes.Node;
import pro.stery.core.LanguageInfo
@TruffleLanguage.Registration(
id = LanguageInfo.ID,
name = LanguageInfo.NAME,
version = LanguageInfo.VERSION,
characterMimeTypes = [LanguageInfo.MIME_TYPE]
)
class VmLanguage : TruffleLanguage<VmContext>() {
companion object {
val REFERENCE: LanguageReference<VmLanguage> = LanguageReference.create(VmLanguage::class.java)
fun get(node: Node?): VmLanguage {
return REFERENCE[node]
}
}
override fun createContext(env: Env?): VmContext {
return VmContext()
}
public override fun parse(request: ParsingRequest?): CallTarget {
throw UnsupportedOperationException("parse")
}
}
I just minimized it as hard as possible. And this is how I try to test it:
package pro.stery.core.runtime
import org.graalvm.polyglot.Context
import org.graalvm.polyglot.Engine
import pro.stery.core.LanguageInfo
....
val engine = Engine.newBuilder(LanguageInfo.ID).option("engine.WarnInterpreterOnly", "false").build()
val context = Context.newBuilder(LanguageInfo.ID).engine(engine).allowAllAccess(true).build()
context.initialize(LanguageInfo.ID) //this raises error message
And this is the error I get:
java.lang.IllegalArgumentException: A language with id 'stery' is not installed. Installed languages are: [].
at com.oracle.truffle.polyglot.PolyglotEngineException.illegalArgument(PolyglotEngineException.java:129)
at com.oracle.truffle.polyglot.PolyglotEngineImpl.throwNotInstalled(PolyglotEngineImpl.java:1173)
at com.oracle.truffle.polyglot.PolyglotEngineImpl.requirePublicLanguage(PolyglotEngineImpl.java:1180)
at com.oracle.truffle.polyglot.PolyglotContextImpl.requirePublicLanguage(PolyglotContextImpl.java:1704)
at com.oracle.truffle.polyglot.PolyglotContextImpl.lookupLanguageContext(PolyglotContextImpl.java:1666)
at com.oracle.truffle.polyglot.PolyglotContextImpl.initializeLanguage(PolyglotContextImpl.java:1635)
at com.oracle.truffle.polyglot.PolyglotContextDispatch.initializeLanguage(PolyglotContextDispatch.java:55)
at org.graalvm.polyglot.Context.initialize(Context.java:579)
Unfortunatelly, I can not find any working example and not sure how to effectively debug it. I wish, someone explained how we can "install" our custom language. In documentation I see, that explicit initialize is not necessary, but I also tried to invoke eval on context, without calling initialize, but still get the very same error. Thanks in advance for any help! PS. I've seen similar issue threads, but to no avail. Documentation also seems to be rather outdated. Probably, I just have to know where to look. Thanks!