Package-level declarations
Information about Inikio's compiler plug-in, that creates Builder
s automatically for your initial-style DSLs.
Step 1, add the plug-in to your build
The plug-in is based on KSP. If you are using Gradle you need to add the following to your build file.
repositories {
mavenCentral()
maven(url = "https://jitpack.io")
}
plugins {
id("com.google.devtools.ksp") version "2.0.20-1.0.24"
}
dependencies {
implementation("com.github.serras.inikio:inikio-core:$inikioVersion")
ksp("com.github.serras.inikio:inikio-ksp:$inikioVersion")
}
If IntelliJ is your IDE of choice, we recommend configuring your build to make it aware of KSP.
Step 2, annotate your DSLs
You only need to add the @InitialStyleDSL
annotation to the top of your hierarchy. Remember that you need to have one "finished" variant, in the example below is Done
.
@InitialStyleDSL
sealed interface Casino<out A>
data class Done<out A>(val result: A): Casino<A>
data class FlipCoin<out A>(val next: (Outcome) -> Casino<A>): Casino<A> {
enum class Outcome { HEADS, TAILS }
}
Step 3, enjoy your new Builder
From the definition above the plug-in generates a Builder
class and a runner function.
The
Builder
class contains a method for each variant in the DSL, that is, for each basic instruction in your DSL.class CasinoBuilder<A> {
suspend fun flipCoin(): FlipCoin.Outcome
}Content copied to clipboardThe runner function takes a block with the
Builder
as receiver, and converts it into the initial-style DSL.fun <A> casino(block: CasinoBuilder<A>.() -> A): Casino<A>
Content copied to clipboard
You can use the combination of the runner and the Builder
methods to create values of your initial-style DSL. For example, the following defines a game when only two heads win.
val doubleCoin = casino {
val o1 = flipCoin()
val o2 = flipCoin()
if (o1 == Outcome.HEADS && o2 == Outcome.HEADS) WIN
else LOSE
}
Note the much nicer syntax with suspend
that what you'd get with the data classes themselves. In particular, all the nesting is gone, and there's no need to call the final Done
. The code above is equivalent to the following.
val casino =
FlipCoin { o1 ->
FlipCoin { o2 ->
if (o1 == Outcome.HEADS && o2 == Outcome.HEADS)
Done(WIN)
else
Done(LOSE)
}
}
Types
Indicates that this DSL has a fixed result type, instead of being polymorphic on the result type.
Instructs Inikio's KSP plug-in to create a Builder based on this hierarchy.