Skip to content

Nilsen84/kt-bytecode-dsl

Repository files navigation

Kotlin Bytecode DSL

A DSL that assists with writing bytecode in ASM

Note: This is NOT an abstraction layer, it simply reduces the amount of boilerplate you have to write

Usage

repositories {
    mavenCentral()
    maven("https://jitpack.io")
}

dependencies {
    implementation("org.ow2.asm:asm-tree:9.4")
    implementation("com.github.Nilsen84:kt-bytecode-dsl:v1.0")
}

Extensibility

This library does not come with any utility functions, though these can easily be added using extensions:

fun InsnBuilder.int(n: Int) = when (n) {
    in -1..5 -> +InsnNode(Opcodes.ICONST_0 + n)
    in Byte.MIN_VALUE..Byte.MAX_VALUE -> bipush(n)
    in Short.MIN_VALUE..Short.MAX_VALUE -> sipush(n)
    else -> ldc(n)
}
val InsnBuilder.iconst_6 get() = bipush(6)

Comparisons

Java Kotlin Kotlin + Bytecode DSL
var list = new InsnList() {{
    var start = new LabelNode();
    add(start);
    add(new FieldInsnNode(
        Opcodes.GETSTATIC,
        "java/lang/System",
        "out",
        "Ljava/io/PrintStream;"
    ));
    add(new LdcInsnNode("Hello, World!"));
    add(new MethodInsnNode(
        Opcodes.INVOKEVIRTUAL,
        "java/io/PrintStream",
        "println",
        "(Ljava/lang/String;)V"
    ));
    add(new JumpInsnNode(Opcodes.GOTO, start));
}};
val list = InsnList().apply {
    val start = LabelNode()
    add(start)
    add(FieldInsnNode(
        Opcodes.GETSTATIC,
        "java/lang/System",
        "out",
        "Ljava/io/PrintStream;"
    ))
    add(LdcInsnNode("Hello, World!"))
    add(MethodInsnNode(
        Opcodes.INVOKEVIRTUAL,
        "java/io/PrintStream",
        "println",
        "(Ljava/lang/String;)V"
    ))
    add(JumpInsnNode(Opcodes.GOTO, start))
}
val list = asm {
    val start = LabelNode()
    +start
    getstatic(
        "java/lang/System",
        "out",
        "Ljava/io/PrintStream;"
    )
    ldc("Hello, World!")
    invokevirtual(
        "java/io/PrintStream",
        "println",
        "(Ljava/lang/String;)V"
    )
    goto(start)
}