KT-756 incorrect intrinsics on nullable numbers

This commit is contained in:
Alex Tkachman
2011-12-06 15:03:26 +02:00
parent 29ebb124c8
commit ecb323a13e
7 changed files with 85 additions and 25 deletions
@@ -24,20 +24,38 @@ public class Increment implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
JetExpression operand = arguments.get(0); boolean nullable = expectedType.getSort() == Type.OBJECT;
while(operand instanceof JetParenthesizedExpression) { if(nullable) {
operand = ((JetParenthesizedExpression)operand).getExpression(); expectedType = JetTypeMapper.unboxType(expectedType);
} }
if (operand instanceof JetReferenceExpression) { if(arguments.size() > 0) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand); JetExpression operand = arguments.get(0);
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) { while(operand instanceof JetParenthesizedExpression) {
return StackValue.preIncrement(index, myDelta); operand = ((JetParenthesizedExpression)operand).getExpression();
} }
if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) {
return StackValue.preIncrement(index, myDelta);
}
}
StackValue value = codegen.genQualified(receiver, operand);
value. dupReceiver(v);
value. dupReceiver(v);
value.put(expectedType, v);
plusMinus(v, expectedType);
value.store(v);
value.put(expectedType, v);
} }
StackValue value = codegen.genQualified(receiver, operand); else {
value. dupReceiver(v); receiver.put(expectedType, v);
value. dupReceiver(v); plusMinus(v, expectedType);
value.put(expectedType, v); }
return StackValue.onStack(expectedType);
}
private void plusMinus(InstructionAdapter v, Type expectedType) {
if (expectedType == Type.LONG_TYPE) { if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta); v.lconst(myDelta);
} }
@@ -51,8 +69,5 @@ public class Increment implements IntrinsicMethod {
v.iconst(myDelta); v.iconst(myDelta);
} }
v.add(expectedType); v.add(expectedType);
value.store(v);
value.put(expectedType, v);
return StackValue.onStack(expectedType);
} }
} }
@@ -23,6 +23,7 @@ import java.util.*;
*/ */
public class IntrinsicMethods { public class IntrinsicMethods {
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus(); private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus();
private static final IntrinsicMethod NUMBER_CAST = new NumberCast(); private static final IntrinsicMethod NUMBER_CAST = new NumberCast();
private static final IntrinsicMethod INV = new Inv(); private static final IntrinsicMethod INV = new Inv();
private static final IntrinsicMethod TYPEINFO = new TypeInfo(); private static final IntrinsicMethod TYPEINFO = new TypeInfo();
@@ -53,6 +54,7 @@ public class IntrinsicMethods {
} }
for (String type : PRIMITIVE_NUMBER_TYPES) { for (String type : PRIMITIVE_NUMBER_TYPES) {
declareIntrinsicFunction(type, "plus", 0, UNARY_PLUS);
declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS); declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS);
declareIntrinsicFunction(type, "inv", 0, INV); declareIntrinsicFunction(type, "inv", 0, INV);
declareIntrinsicFunction(type, "rangeTo", 1, RANGE_TO); declareIntrinsicFunction(type, "rangeTo", 1, RANGE_TO);
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -16,6 +17,10 @@ import java.util.List;
public class Inv implements IntrinsicMethod { public class Inv implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if(nullable) {
expectedType = JetTypeMapper.unboxType(expectedType);
}
receiver.put(expectedType, v); receiver.put(expectedType, v);
if(expectedType == Type.LONG_TYPE) { if(expectedType == Type.LONG_TYPE) {
v.lconst(-1L); v.lconst(-1L);
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -15,6 +16,10 @@ import java.util.List;
public class UnaryMinus implements IntrinsicMethod { public class UnaryMinus implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if(nullable) {
expectedType = JetTypeMapper.unboxType(expectedType);
}
if (arguments.size() == 1) { if (arguments.size() == 1) {
codegen.gen(arguments.get(0), expectedType); codegen.gen(arguments.get(0), expectedType);
} }
@@ -0,0 +1,27 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author alex.tkachman
*/
public class UnaryPlus implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List<JetExpression> arguments, StackValue receiver) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if(nullable) {
expectedType = JetTypeMapper.unboxType(expectedType);
}
receiver.put(expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -0,0 +1,12 @@
namespace demo_range
fun Int?.plus() : Int = this.sure().plus()
fun Int?.dec() : Int = this.sure().dec()
fun Int?.inc() : Int = this.sure().inc()
fun Int?.minus() : Int = this.sure().minus()
fun box() : String {
val x : Int? = 10
System.out?.println(x?.inv())// * x?.plus() * x?.dec() * x?.minus() as Number)
return "OK"
}
@@ -287,37 +287,31 @@ public class PrimitiveTypesTest extends CodegenTestCase {
public void testKt711 () throws Exception { public void testKt711 () throws Exception {
loadText("fun box() = if ((1 ?: 0) == 1) \"OK\" else \"fail\""); loadText("fun box() = if ((1 ?: 0) == 1) \"OK\" else \"fail\"");
// System.out.println(generateToText());
blackBox(); blackBox();
} }
public void testSureNonnull () throws Exception { public void testSureNonnull () throws Exception {
loadText("fun box() = 10.sure().toString()"); loadText("fun box() = 10.sure().toString()");
// System.out.println(generateToText());
assertFalse(generateToText().contains("IFNONNULL")); assertFalse(generateToText().contains("IFNONNULL"));
} }
public void testSureNullable () throws Exception { public void testSureNullable () throws Exception {
loadText("val a : Int? = 10; fun box() = a.sure().toString()"); loadText("val a : Int? = 10; fun box() = a.sure().toString()");
// System.out.println(generateToText());
assertTrue(generateToText().contains("IFNONNULL")); assertTrue(generateToText().contains("IFNONNULL"));
} }
public void testSafeNonnull () throws Exception { public void testSafeNonnull () throws Exception {
loadText("fun box() = 10?.toString()"); loadText("fun box() = 10?.toString()");
// System.out.println(generateToText());
assertFalse(generateToText().contains("IFNULL")); assertFalse(generateToText().contains("IFNULL"));
} }
public void testSafeNullable () throws Exception { public void testSafeNullable () throws Exception {
loadText("val a : Int? = 10; fun box() = a?.toString()"); loadText("val a : Int? = 10; fun box() = a?.toString()");
// System.out.println(generateToText());
assertTrue(generateToText().contains("IFNULL")); assertTrue(generateToText().contains("IFNULL"));
} }
public void testKt737() throws Exception { public void testKt737() throws Exception {
loadText("fun box() = if(3.compareTo(2) != 1) \"fail\" else if(5.byt.compareTo(10.lng) >= 0) \"fail\" else \"OK\""); loadText("fun box() = if(3.compareTo(2) != 1) \"fail\" else if(5.byt.compareTo(10.lng) >= 0) \"fail\" else \"OK\"");
// System.out.println(generateToText());
assertEquals("OK", blackBox()); assertEquals("OK", blackBox());
} }
@@ -334,27 +328,27 @@ public class PrimitiveTypesTest extends CodegenTestCase {
" System.out?.println(f(six))\n" + " System.out?.println(f(six))\n" +
" return \"OK\"" + " return \"OK\"" +
"}"); "}");
// System.out.println(generateToText());
blackBox(); blackBox();
} }
public void testKt752 () { public void testKt752 () {
blackBoxFile("regressions/kt752.jet"); blackBoxFile("regressions/kt752.jet");
// System.out.println(generateToText());
} }
public void testKt753 () { public void testKt753 () {
blackBoxFile("regressions/kt753.jet"); blackBoxFile("regressions/kt753.jet");
// System.out.println(generateToText());
} }
public void testKt684 () { public void testKt684 () {
blackBoxFile("regressions/kt684.jet"); blackBoxFile("regressions/kt684.jet");
// System.out.println(generateToText()); }
public void testKt756 () {
blackBoxFile("regressions/kt756.jet");
System.out.println(generateToText());
} }
public void testKt757 () { public void testKt757 () {
blackBoxFile("regressions/kt757.jet"); blackBoxFile("regressions/kt757.jet");
// System.out.println(generateToText());
} }
} }