JS backend: added identityEquals support.
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.k2js.test.semantics;
|
||||||
|
|
||||||
|
public class IdentityEqualsTest extends AbstractExpressionTest {
|
||||||
|
public IdentityEqualsTest() {
|
||||||
|
super("identityEquals/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIdentityEqualsMethod() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIdentityEqualsMethodForPrimitives() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-3
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.k2js.translate.intrinsic.functions.factories;
|
package org.jetbrains.k2js.translate.intrinsic.functions.factories;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
@@ -53,6 +51,17 @@ public final class TopLevelFIF extends CompositeFIF {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static final KotlinFunctionIntrinsic EQUALS = new KotlinFunctionIntrinsic("equals");
|
public static final KotlinFunctionIntrinsic EQUALS = new KotlinFunctionIntrinsic("equals");
|
||||||
@NotNull
|
@NotNull
|
||||||
|
public static final FunctionIntrinsic IDENTITY_EQUALS = new FunctionIntrinsic() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public JsExpression apply(
|
||||||
|
@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments, @NotNull TranslationContext context
|
||||||
|
) {
|
||||||
|
assert arguments.size() == 1 : "Unexpected argument size for jet.identityEquals: " + arguments.size();
|
||||||
|
return new JsBinaryOperation(JsBinaryOperator.REF_EQ, receiver, arguments.get(0));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@NotNull
|
||||||
private static final FunctionIntrinsic RETURN_RECEIVER_INTRINSIC = new FunctionIntrinsic() {
|
private static final FunctionIntrinsic RETURN_RECEIVER_INTRINSIC = new FunctionIntrinsic() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@@ -120,6 +129,7 @@ public final class TopLevelFIF extends CompositeFIF {
|
|||||||
private TopLevelFIF() {
|
private TopLevelFIF() {
|
||||||
add(pattern("jet", "toString").receiverExists(), new KotlinFunctionIntrinsic("toString"));
|
add(pattern("jet", "toString").receiverExists(), new KotlinFunctionIntrinsic("toString"));
|
||||||
add(pattern("jet", "equals").receiverExists(), EQUALS);
|
add(pattern("jet", "equals").receiverExists(), EQUALS);
|
||||||
|
add(pattern("jet", "identityEquals").receiverExists(), IDENTITY_EQUALS);
|
||||||
add(pattern(NamePredicate.PRIMITIVE_NUMBERS, "equals"), EQUALS);
|
add(pattern(NamePredicate.PRIMITIVE_NUMBERS, "equals"), EQUALS);
|
||||||
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
|
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
|
||||||
add(pattern("jet", "arrayOfNulls"), new KotlinFunctionIntrinsic("nullArray"));
|
add(pattern("jet", "arrayOfNulls"), new KotlinFunctionIntrinsic("nullArray"));
|
||||||
|
|||||||
+21
-3
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.k2js.translate.operation;
|
package org.jetbrains.k2js.translate.operation;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
|
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
|
||||||
@@ -31,7 +32,9 @@ import static org.jetbrains.k2js.translate.general.Translation.translateAsExpres
|
|||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
|
import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
|
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
|
||||||
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isEqualLikeOperator;
|
||||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.sure;
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.sure;
|
||||||
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateExclForBinaryEqualLikeExpr;
|
||||||
|
|
||||||
public final class UnaryOperationTranslator {
|
public final class UnaryOperationTranslator {
|
||||||
private UnaryOperationTranslator() {
|
private UnaryOperationTranslator() {
|
||||||
@@ -46,7 +49,12 @@ public final class UnaryOperationTranslator {
|
|||||||
if (IncrementTranslator.isIncrement(expression)) {
|
if (IncrementTranslator.isIncrement(expression)) {
|
||||||
return IncrementTranslator.translate(expression, context);
|
return IncrementTranslator.translate(expression, context);
|
||||||
}
|
}
|
||||||
return translateAsCall(expression, context);
|
|
||||||
|
JsExpression baseExpression = TranslationUtils.translateBaseExpression(context, expression);
|
||||||
|
if (isExclForBinaryEqualLikeExpr(expression, baseExpression)) {
|
||||||
|
return translateExclForBinaryEqualLikeExpr((JsBinaryOperation) baseExpression);
|
||||||
|
}
|
||||||
|
return translateAsCall(expression, context, baseExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isExclExcl(@NotNull JetUnaryExpression expression) {
|
private static boolean isExclExcl(@NotNull JetUnaryExpression expression) {
|
||||||
@@ -58,11 +66,21 @@ public final class UnaryOperationTranslator {
|
|||||||
return sure(translateAsExpression(getBaseExpression(expression), context), context);
|
return sure(translateAsExpression(getBaseExpression(expression), context), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isExclForBinaryEqualLikeExpr(@NotNull JetUnaryExpression expression, @NotNull JsExpression baseExpression) {
|
||||||
|
if (getOperationToken(expression).equals(JetTokens.EXCL)) {
|
||||||
|
if (baseExpression instanceof JsBinaryOperation) {
|
||||||
|
return isEqualLikeOperator(((JsBinaryOperation) baseExpression).getOperator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsExpression translateAsCall(@NotNull JetUnaryExpression expression,
|
private static JsExpression translateAsCall(@NotNull JetUnaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context,
|
||||||
|
@NotNull JsExpression baseExpression) {
|
||||||
return CallBuilder.build(context)
|
return CallBuilder.build(context)
|
||||||
.receiver(TranslationUtils.translateBaseExpression(context, expression))
|
.receiver(baseExpression)
|
||||||
.args(Collections.<JsExpression>emptyList())
|
.args(Collections.<JsExpression>emptyList())
|
||||||
.resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference()))
|
.resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference()))
|
||||||
.type(CallType.NORMAL).translate();
|
.type(CallType.NORMAL).translate();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.google.dart.compiler.backend.js.ast.JsBinaryOperator.*;
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.createDataDescriptor;
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.createDataDescriptor;
|
||||||
@@ -62,6 +63,31 @@ public final class TranslationUtils {
|
|||||||
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
|
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsExpression translateExclForBinaryEqualLikeExpr(@NotNull JsBinaryOperation baseBinaryExpression) {
|
||||||
|
return new JsBinaryOperation(notOperator(baseBinaryExpression.getOperator()), baseBinaryExpression.getArg1(), baseBinaryExpression.getArg2());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEqualLikeOperator(@NotNull JsBinaryOperator operator) {
|
||||||
|
return notOperator(operator) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JsBinaryOperator notOperator(@NotNull JsBinaryOperator operator) {
|
||||||
|
switch (operator) {
|
||||||
|
case REF_EQ:
|
||||||
|
return REF_NEQ;
|
||||||
|
case REF_NEQ:
|
||||||
|
return REF_EQ;
|
||||||
|
case EQ:
|
||||||
|
return NEQ;
|
||||||
|
case NEQ:
|
||||||
|
return EQ;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsBinaryOperation isNullCheck(@NotNull JsExpression expressionToCheck) {
|
public static JsBinaryOperation isNullCheck(@NotNull JsExpression expressionToCheck) {
|
||||||
return nullCheck(expressionToCheck, false);
|
return nullCheck(expressionToCheck, false);
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class X
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = X()
|
||||||
|
val b = X()
|
||||||
|
if (!a.identityEquals(a)) return "a !== a"
|
||||||
|
if (a.identityEquals(b)) return "X() === X()"
|
||||||
|
val c = a
|
||||||
|
if (!c.identityEquals(a)) return "c = a; c !== a"
|
||||||
|
|
||||||
|
if (X() identityEquals a) return "X() identityEquals a"
|
||||||
|
|
||||||
|
val t = !(X() identityEquals a)
|
||||||
|
if (!t) return "t = !(X() identityEquals a); t == false"
|
||||||
|
|
||||||
|
val f = !!(X() identityEquals a)
|
||||||
|
if (f) return "f = !!(X() identityEquals null); f == true"
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (!null.identityEquals(null)) return "null !== null"
|
||||||
|
if (!("ab" identityEquals "ab")) return "ab !== ab"
|
||||||
|
if (("ab" identityEquals "a")) return "ab === a"
|
||||||
|
|
||||||
|
if ("0" identityEquals 0) return "'0' === 0"
|
||||||
|
if (!(0 identityEquals 0)) return "0 !== 0"
|
||||||
|
if (0 identityEquals 1) return "0 === 1"
|
||||||
|
|
||||||
|
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user