JS backend: fix KT-5772 wrong code generated when <,<=,>,>= are used with explicit Comparable type

#KT-5772 Fixed
This commit is contained in:
Michael Nedzelsky
2014-09-18 22:13:21 +04:00
parent 1d71016097
commit bdca7e0e37
8 changed files with 81 additions and 19 deletions
-5
View File
@@ -31,11 +31,6 @@ public trait Runnable {
public open fun run() : Unit;
}
library
public trait Comparable<T> {
public fun compareTo(that: T): Int
}
library
public trait Appendable {
public open fun append(csq: CharSequence?): Appendable
@@ -101,6 +101,8 @@ public final class StandardClasses {
.methods("iterator", "contains").properties("start", "end", "increment");
standardClasses.declare().forFQ("kotlin.Enum").kotlinClass("Enum");
standardClasses.declare().forFQ("kotlin.Comparable").kotlinClass("Comparable");
}
@@ -31,6 +31,7 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getTypeByReference;
@@ -92,6 +93,9 @@ public final class PatternTranslator extends AbstractTranslator {
if (NamePredicate.STRING.apply(typeName)) {
jsSTypeName = "string";
}
else if (NamePredicate.NUMBER.apply(typeName)) {
return JsAstUtils.isNumber(expressionToMatch);
}
else if (NamePredicate.PRIMITIVE_NUMBERS.apply(typeName)) {
jsSTypeName = "number";
}
@@ -34,11 +34,12 @@ import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredi
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import java.util.List;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setArguments;
public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
INSTANCE;
@@ -76,7 +77,7 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
};
@NotNull
private static final FunctionIntrinsic NUMBER_COMPARE_TO_INTRINSIC = new FunctionIntrinsic() {
private static final FunctionIntrinsic BUILTINS_COMPARE_TO_INTRINSIC = new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(
@@ -90,6 +91,21 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
}
};
@NotNull
private static final FunctionIntrinsic PRIMITIVE_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.primitiveCompareTo(receiver, arguments.get(0));
}
};
@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);
@@ -115,13 +131,18 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
@Nullable
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
if (PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS.apply(descriptor)) {
return PRIMITIVE_NUMBER_COMPARE_TO_INTRINSIC;
}
if (JsDescriptorUtils.isBuiltin(descriptor) && descriptor.getName().equals(OperatorConventions.COMPARE_TO)) {
return BUILTINS_COMPARE_TO_INTRINSIC;
}
if (!PREDICATE.apply(descriptor)) {
return null;
}
if (PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS.apply(descriptor)) {
return NUMBER_COMPARE_TO_INTRINSIC;
}
if (pattern("Int|Short|Byte.div").apply(descriptor)) {
JetType resultType = descriptor.getReturnType();
@@ -45,6 +45,9 @@ public final class NamePredicate implements Predicate<Name> {
@NotNull
public static final NamePredicate STRING = new NamePredicate("String");
@NotNull
public static final NamePredicate NUMBER = new NamePredicate("Number");
@NotNull
private final Set<Name> validNames = Sets.newHashSet();
@@ -16,18 +16,18 @@
package org.jetbrains.k2js.translate.intrinsic.operation
import com.google.common.collect.ImmutableSet
import com.google.dart.compiler.backend.js.ast.*
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.psi.JetBinaryExpression
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import org.jetbrains.k2js.translate.context.TranslationContext
import org.jetbrains.k2js.translate.operation.OperatorTable
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils
import org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lexer.JetToken
import com.google.common.collect.ImmutableSet
import org.jetbrains.k2js.translate.context.TranslationContext
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern
import org.jetbrains.k2js.translate.operation.OperatorTable
import org.jetbrains.k2js.translate.utils.JsAstUtils
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils
import org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken
object CompareToBOIF : BinaryOperationIntrinsicFactory {
@@ -39,9 +39,24 @@ object CompareToBOIF : BinaryOperationIntrinsicFactory {
}
}
private object CompareToFunctionIntrinsic : AbstractBinaryOperationIntrinsic() {
override fun apply(expression: JetBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsExpression {
val operator = OperatorTable.getBinaryOperator(getOperationToken(expression))
val compareTo = JsAstUtils.compareTo(left, right)
return JsBinaryOperation(operator, compareTo, context.program().getNumberLiteral(0))
}
}
override public fun getSupportTokens(): ImmutableSet<JetToken> = OperatorConventions.COMPARISON_OPERATIONS
override public fun getIntrinsic(descriptor: FunctionDescriptor): BinaryOperationIntrinsic? {
return if (JsDescriptorUtils.isBuiltin(descriptor)) CompareToIntrinsic else null
if (JsDescriptorUtils.isBuiltin(descriptor))
when {
pattern("Int|Short|Byte|Double|Float|Char|String|Long.compareTo").apply(descriptor) ->
return CompareToIntrinsic
else ->
return CompareToFunctionIntrinsic
}
return null
}
}
@@ -138,6 +138,16 @@ public final class JsAstUtils {
return new JsInvocation(new JsNameRef(OperatorConventions.COMPARE_TO.getIdentifier(), Namer.KOTLIN_OBJECT_REF), left, right);
}
@NotNull
public static JsExpression primitiveCompareTo(@NotNull JsExpression left, @NotNull JsExpression right) {
return new JsInvocation(new JsNameRef("primitiveCompareTo", Namer.KOTLIN_OBJECT_REF), left, right);
}
@NotNull
public static JsExpression isNumber(@NotNull JsExpression expression) {
return new JsInvocation(new JsNameRef("isNumber", Namer.KOTLIN_OBJECT_REF), expression);
}
@NotNull
public static JsPrefixOperation negated(@NotNull JsExpression expression) {
return new JsPrefixOperation(JsUnaryOperator.NOT, expression);
+12
View File
@@ -86,9 +86,21 @@
};
Kotlin.compareTo = function(a, b) {
var type = typeof a;
if (type == "number" || type == "string") {
return a < b ? -1 : a > b ? 1 : 0;
}
return a.compareTo_za3rmp$(b);
};
Kotlin.primitiveCompareTo = function(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
};
Kotlin.isNumber = function (a) {
return typeof a == "number";
};
Kotlin.toShort = function(a) {
return (a & 0xFFFF) << 16 >> 16;
};