@@ -32,22 +32,29 @@ public record ArithmeticExpr(
32
32
) implements IrNode {
33
33
34
34
private static final CallTarget MATH_POW = CallTarget .staticMethod (Type .of (Math .class ), Type .DOUBLE , "pow" , Type .DOUBLE , Type .DOUBLE );
35
- private static final CallTarget MATH_ABS = CallTarget .staticMethod (Type .of (Math .class ), Type .DOUBLE , "abs" , Type .DOUBLE );
36
- private static final CallTarget FLOOR_DIV = CallTarget .staticMethod (Type .of (ArithmeticExpr .class ), Type .DOUBLE , "floorDivide" , Type .DOUBLE , Type .DOUBLE );
35
+ private static final CallTarget MATH_ABS_INT = CallTarget .staticMethod (Type .of (Math .class ), Type .INT , "abs" , Type .INT );
36
+ private static final CallTarget MATH_ABS_DOUBLE = CallTarget .staticMethod (Type .of (Math .class ), Type .DOUBLE , "abs" , Type .DOUBLE );
37
+ private static final CallTarget FLOOR_DIV_INTS = CallTarget .staticMethod (Type .of (ArithmeticExpr .class ), Type .INT , "floorDivide" , Type .INT , Type .INT );
38
+ private static final CallTarget FLOOR_DIV_DOUBLES = CallTarget .staticMethod (Type .of (ArithmeticExpr .class ), Type .DOUBLE , "floorDivide" , Type .DOUBLE , Type .DOUBLE );
37
39
private static final MethodHandles .Lookup LOOKUP = MethodHandles .lookup ();
38
40
39
41
public enum Kind {
40
- POWER (MATH_POW ::call , "power" , "__pow" ),
42
+ POWER ((lhs , rhs ) -> {
43
+ // Math.pow() does not have integer variant
44
+ return MATH_POW .call (lhs .cast (Type .DOUBLE ), rhs .cast (Type .DOUBLE ));
45
+ }, "power" , "__pow" ),
41
46
MULTIPLY (Arithmetic ::multiply , "multiply" , "__mul" ),
42
47
DIVIDE ((lhs , rhs ) -> {
43
48
// Lua uses float division unless integer division is explicitly request (see below)
44
49
return Arithmetic .divide (lhs .cast (Type .DOUBLE ), rhs .cast (Type .DOUBLE ));
45
50
}, "divide" , "__div" ),
46
- FLOOR_DIVIDE (FLOOR_DIV ::call , "floorDivide" , "__idiv" ),
51
+ FLOOR_DIVIDE ((lhs , rhs )
52
+ -> lhs .type ().equals (Type .INT ) ? FLOOR_DIV_INTS .call (lhs , rhs ) : FLOOR_DIV_DOUBLES .call (lhs , rhs ),
53
+ "floorDivide" , "__idiv" ),
47
54
MODULO ((lhs , rhs ) -> (block -> {
48
55
// Lua expects modulo to be always positive; Java's remainder can return negative values
49
56
var remainder = block .add (Arithmetic .remainder (lhs , rhs ));
50
- return block .add (MATH_ABS .call (remainder ));
57
+ return block .add (remainder . type (). equals ( Type . INT ) ? MATH_ABS_INT . call ( remainder ) : MATH_ABS_DOUBLE .call (remainder ));
51
58
}), "modulo" , "__mod" ),
52
59
ADD (Arithmetic ::add , "add" , "__add" ),
53
60
SUBTRACT (Arithmetic ::subtract , "subtract" , "__sub" );
@@ -156,6 +163,12 @@ public Value emit(LuaContext ctx, Block block) {
156
163
var rhsValue = rhs .emit (ctx , block );
157
164
if (outputType (ctx ).isNumber ()) {
158
165
// Both arguments are known to be numbers; emit arithmetic operation directly
166
+ // Just make sure that if either side is double, the other side is too
167
+ if (lhsValue .type ().equals (Type .INT ) && rhsValue .type ().equals (Type .DOUBLE )) {
168
+ lhsValue = lhsValue .cast (Type .DOUBLE );
169
+ } else if (rhsValue .type ().equals (Type .INT ) && lhsValue .type ().equals (Type .DOUBLE )) {
170
+ rhsValue = rhsValue .cast (Type .DOUBLE );
171
+ }
159
172
return block .add (kind .directEmitter .apply (lhsValue , rhsValue ));
160
173
} else {
161
174
// Types are unknown compile-time; use invokedynamic
0 commit comments