usethesource / flybytes

Flybytes is an intermediate language between JVM bytecode and software languages (DSLs, PLs), for compilation and decompilation.
BSD 2-Clause "Simplified" License
16 stars 6 forks source link

Bug: Errors when compiling/decompiling arrays #22

Closed bys1 closed 1 year ago

bys1 commented 1 year ago

I have the following module:

module Test

//imports

void compileTest() {
    Class cl = class(
        object("Test"),
        modifiers = {\public(), \final()},
        methods = [
            method(
                \public(),
                \void(),
                "test",
                [],
                [
                    \decl(
                        array(integer()),
                        "arr",
                        init = newInitArray(
                            array(integer()),
                            [
                                iconst(10),
                                iconst(20),
                                iconst(30)
                            ]
                        )
                    ),
                    \return()
                ]
            )
        ]
    );
    compileClass(cl, |cwd:///Test.class|);
}

Class decompileTest() {
    return decompile(|cwd:///Test.class|);
}

I have a simple method where I declare an array of integers and initialize it with the values 10, 20, 30. When calling compileTest, Flybytes gives the following error:

compileTest();
|jar+file:///Users/bys1/.m2/repository/org/rascalmpl/flybytes/0.1.7/flybytes-0.1.7.jar!/src/lang/flybytes/Compiler.rsc|(1637,272,<25,0>,<27,123>): Java(
  "RuntimeException",
  "java.lang.IllegalArgumentException: unknown expression: newInitArray(array(integer()),[const(integer(),10),const(integer(),20),const(integer(),30)])",
  Java("IllegalArgumentException","unknown expression: newInitArray(array(integer()),[const(integer(),10),const(integer(),20),const(integer(),30)])"))
    at lang.flybytes.internal.ClassCompiler.compileClass(|unknown:///ClassCompiler.java|(0,0,<109,0>,<109,0>))
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(|unknown:///NativeMethodAccessorImpl.java|(0,0,<0,0>,<0,0>))
    at compileClass(|jar+file:///Users/bys1/.m2/repository/org/rascalmpl/flybytes/0.1.7/flybytes-0.1.7.jar!/src/lang/flybytes/Compiler.rsc|(1902,5,<27,116>,<27,121>))
    at $shell$(|prompt:///|(0,14,<1,0>,<1,14>)ok
rascal>import Test;

I have tried this with an int array and with a java.lang.Integer array. Both give this error. When I change the array to simply initialize it without values, it compiles properly:

init = newArray(
    array(integer()),
    iconst(3)
)

However, when decompiling this, I get another error:

compileTest();
ok
rascal>decompileTest();
)
|jar+file:///Users/bys1/.m2/repository/org/rascalmpl/flybytes/0.1.7/flybytes-0.1.7.jar!/src/lang/flybytes/Disassembler.rsc|(1465,237,<18,0>,<20,75>): Java("ClassCastException","class org.objectweb.asm.tree.IntInsnNode cannot be cast to class org.objectweb.asm.tree.TypeInsnNode (org.objectweb.asm.tree.IntInsnNode and org.objectweb.asm.tree.TypeInsnNode are in unnamed module of loader \'app\')")
    at lang.flybytes.internal.ClassDisassembler.instruction(|unknown:///ClassDisassembler.java|(0,0,<588,0>,<588,0>))
    at lang.flybytes.internal.ClassDisassembler.instructions(|unknown:///ClassDisassembler.java|(0,0,<250,0>,<250,0>))
    at lang.flybytes.internal.ClassDisassembler.method(|unknown:///ClassDisassembler.java|(0,0,<190,0>,<190,0>))
    at lang.flybytes.internal.ClassDisassembler.methods(|unknown:///ClassDisassembler.java|(0,0,<178,0>,<178,0>))
    at lang.flybytes.internal.ClassDisassembler.readClass(|unknown:///ClassDisassembler.java|(0,0,<105,0>,<105,0>))
    at lang.flybytes.internal.ClassDisassembler.disassemble(|unknown:///ClassDisassembler.java|(0,0,<92,0>,<92,0>))
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(|unknown:///NativeMethodAccessorImpl.java|(0,0,<0,0>,<0,0>))
    at disassemble(|jar+file:///Users/bys1/.m2/repository/org/rascalmpl/flybytes/0.1.7/flybytes-0.1.7.jar!/src/lang/flybytes/Disassembler.rsc|(1685,5,<20,58>,<20,63>))
    at decompileTest(|file:///Users/bys1/Documents/RUG/FBEG/flybytes-evalgen/src/main/rascal/Test.rsc|(920,31,<39,11>,<39,42>))
    at $shell$(|prompt:///|(0,16,<1,0>,<1,16>)ok

This error only happens with an int array. When I change the type to array(object("java.lang.Integer")), decompilation works fine. I think this error happens with arrays of primitive types only.

jurgenvinju commented 1 year ago

Thanks; that's a missing test case too.

jurgenvinju commented 1 year ago

The newInitArray case is entirely missing from the expression compiler. weird!

jurgenvinju commented 1 year ago

Aha. The code was still written for two overloaded cases of newArray, one with a list of initializers and one with the size expression.

case "newArray":
      if (exp.get(1) instanceof IList) {
      return newArrayExp(AST.$getType(exp), AST.$getArgs(exp), line);
      }
      else {
      return newArrayExp(AST.$getType(exp), AST.$getSize(exp), line);
      }