Simn / genjvm

13 stars 1 forks source link

Increment issues #29

Closed Simn closed 5 years ago

Simn commented 5 years ago
class Main {
    static public function main() {
        x++;
    }

    static var x:Null<Int> = 0;
}

Fails in the generator with:

Stack error
        ops      :
                   3                  getstatic Main.x:Ljava/lang/Integer; [Ljava/lang/Integer;]
                   3 invokestatic haxe/jvm/Jvm.toInt:(Ljava/lang/Object;)I [I]
                   3                                              iconst_1 [I, I]
                   3                                                  iadd [I]
             line: 3
        operation: putstatic Main.x:Ljava/lang/Integer;
        expected : [Ljava/lang/Integer;]
        actual   : [I]
Method Main.main

I think it's because the TUnop itself is typed as Int:

            [Unop:Int]
                ++
                Postfix
                [Field:Null<Int>]
                    [TypeExpr Main:Class<Main>]
                    [FStatic:Null<Int>]
                        Main
                        x:Null<Int>
Simn commented 5 years ago

Also:

class Main {
    static public function main() {
        var x:Null<Int> = 0;
        x++;
    }
}
java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    Main.main([Ljava/lang/String;)V @5: iinc
  Reason:
    Type 'java/lang/Integer' (current frame, locals[1]) is not assignable to integer
  Current Frame:
    bci: @5
    flags: { }
    locals: { '[Ljava/lang/String;', 'java/lang/Integer' }
    stack: { }

We can only use iinc if we have strictly Int and none of that wrapped Nullshit.

Simn commented 5 years ago

And one more:

class Main {
    static public function main() {
        var n:Dynamic = 0;
        n++;
    }
}
src/Main.hx:4: characters 3-4 : Unuspported unop on Ljava/lang/Object;

Not quite sure what to actually generate here.

nadako commented 5 years ago

So if the type of unop should be Int, then for n++ we have to generate something like this, right?

var tmp = n.intValue();
n = Integer.valueOf(tmp + 1);
tmp;

(but in terms of stack and in instructions)

nadako commented 5 years ago

For Dynamic, well:

var tmp = n;
n = Runtime.castToNumberThenAddOneAndWrapBackIntoTheSameType(n);
tmp;

What type does Dynamic++ have? If it's not dynamic then we have to cast tmp too...

Simn commented 5 years ago

The first and second case should be fixed.

For the Dynamic version we need a run-time support function that distinguishes the applicable types.

Simn commented 5 years ago

Or maybe we can just call opAdd/opSub actually...