JS backend: fix KT-4601 JS: compareTo doesn't work on Numbers

#KT-4601 Fixed
This commit is contained in:
Michael Nedzelsky
2014-09-06 11:38:05 +04:00
parent 145050b3d1
commit a632e9e21d
5 changed files with 108 additions and 2 deletions
@@ -65,4 +65,8 @@ public final class NumberTest extends SingleFileTranslationTest {
Assert.assertTrue(cause.getMessage().startsWith("Unsupported long constant "));
}
}
public void testNumberCompareTo() throws Exception {
checkFooBoxIsOk();
}
}
@@ -39,7 +39,7 @@ import java.util.List;
import static org.jetbrains.k2js.translate.intrinsic.functions.factories.NumberConversionFIF.INTEGER_NUMBER_TYPES;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setArguments;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
INSTANCE;
@@ -76,9 +76,26 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
}
};
@NotNull
private static final FunctionIntrinsic NUMBER_COMPARE_TO_INTRINSIC = new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(
@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context
) {
assert receiver != null;
assert arguments.size() == 1;
return JsAstUtils.compareTo(receiver, arguments.get(0), context);
}
};
@NotNull
private static final NamePredicate BINARY_OPERATIONS = new NamePredicate(OperatorConventions.BINARY_OPERATION_NAMES.values());
private static final DescriptorPredicate PRIMITIVE_NUMBERS_BINARY_OPERATIONS = pattern(NamePredicate.PRIMITIVE_NUMBERS, BINARY_OPERATIONS);
private static final DescriptorPredicate PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS =
pattern(NamePredicate.PRIMITIVE_NUMBERS, "compareTo");
private static final DescriptorPredicate INT_WITH_BIT_OPERATIONS = pattern("Int.or|and|xor|shl|shr|ushr");
private static final DescriptorPredicate BOOLEAN_OPERATIONS = pattern("Boolean.or|and|xor");
private static final DescriptorPredicate STRING_PLUS = pattern("String.plus");
@@ -93,7 +110,8 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
.build();
private static final Predicate<FunctionDescriptor> PREDICATE = Predicates.or(PRIMITIVE_NUMBERS_BINARY_OPERATIONS, BOOLEAN_OPERATIONS,
STRING_PLUS, INT_WITH_BIT_OPERATIONS);
STRING_PLUS, INT_WITH_BIT_OPERATIONS,
PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS);
@Nullable
@Override
@@ -102,6 +120,10 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
return null;
}
if (PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS.apply(descriptor)) {
return NUMBER_COMPARE_TO_INTRINSIC;
}
if (pattern(INTEGER_NUMBER_TYPES + ".div").apply(descriptor)) {
JetType resultType = descriptor.getReturnType();
if (!KotlinBuiltIns.getInstance().getFloatType().equals(resultType) &&
@@ -20,6 +20,7 @@ import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -122,6 +123,11 @@ public final class JsAstUtils {
return new JsBinaryOperation(JsBinaryOperator.BIT_OR, expression, context.program().getNumberLiteral(0));
}
@NotNull
public static JsExpression compareTo(@NotNull JsExpression left, @NotNull JsExpression right) {
return new JsInvocation(new JsNameRef(OperatorConventions.COMPARE_TO.getIdentifier(), Namer.KOTLIN_OBJECT_REF), left, right);
}
@NotNull
public static JsPrefixOperation negated(@NotNull JsExpression expression) {
return new JsPrefixOperation(JsUnaryOperator.NOT, expression);
@@ -171,6 +177,16 @@ public final class JsAstUtils {
return new JsBinaryOperation(JsBinaryOperator.LTE, arg1, arg2);
}
@NotNull
public static JsBinaryOperation lessThan(@NotNull JsExpression arg1, @NotNull JsExpression arg2) {
return new JsBinaryOperation(JsBinaryOperator.LT, arg1, arg2);
}
@NotNull
public static JsBinaryOperation greaterThan(@NotNull JsExpression arg1, @NotNull JsExpression arg2) {
return new JsBinaryOperation(JsBinaryOperator.GT, arg1, arg2);
}
@NotNull
public static JsExpression assignment(@NotNull JsExpression left, @NotNull JsExpression right) {
return new JsBinaryOperation(JsBinaryOperator.ASG, left, right);
+4
View File
@@ -85,6 +85,10 @@
return "[" + a.join(", ") + "]";
};
Kotlin.compareTo = function(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
};
Kotlin.intUpto = function (from, to) {
return new Kotlin.NumberRange(from, to);
};
@@ -0,0 +1,60 @@
package foo
var global: String = ""
fun id(s: String, value: Int): Int {
global += s
return value
}
fun box(): String {
assertEquals(-1, 1.compareTo(2))
assertEquals(-1, 1 compareTo 2)
assertEquals(-1, 1 compareTo (2:Short))
assertEquals(-1, 1 compareTo (2:Byte))
assertEquals(-1, 1 compareTo 2.0)
assertEquals(-1, 1 compareTo 2.0f)
assertEquals(1, 10 compareTo 2)
assertEquals(1, 10 compareTo (2:Short))
assertEquals(1, 10 compareTo (2:Byte))
assertEquals(1, 10 compareTo 2.0)
assertEquals(1, 10 compareTo 2.0f)
assertEquals(0, 2 compareTo 2)
assertEquals(0, 2 compareTo (2:Short))
assertEquals(0, 2 compareTo (2:Byte))
assertEquals(0, 2 compareTo 2.0)
assertEquals(0, 2 compareTo 2.0f)
assertEquals(-1, (1: Short) compareTo 2)
assertEquals(-1, (1: Short) compareTo (2:Short))
assertEquals(-1, (1: Short) compareTo (2:Byte))
assertEquals(-1, (1: Short) compareTo 2.0)
assertEquals(-1, (1: Short) compareTo 2.0f)
assertEquals(1, (10: Byte) compareTo 2)
assertEquals(1, (10: Byte) compareTo (2:Short))
assertEquals(1, (10: Byte) compareTo (2:Byte))
assertEquals(1, (10: Byte) compareTo 2.0)
assertEquals(1, (10: Byte) compareTo 2.0f)
assertEquals(0, 2.0 compareTo 2)
assertEquals(0, 2.0 compareTo (2:Short))
assertEquals(0, 2.0 compareTo (2:Byte))
assertEquals(0, 2.0 compareTo 2.0)
assertEquals(0, 2.0 compareTo 2.0f)
assertEquals(1, 3.0f compareTo 2)
assertEquals(1, 3.0f compareTo (2:Short))
assertEquals(1, 3.0f compareTo (2:Byte))
assertEquals(1, 3.0f compareTo 2.0)
assertEquals(1, 3.0f compareTo 2.0f)
assertEquals(1, id("A", 10) compareTo id("B", 5))
assertEquals("AB", global)
return "OK"
}