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;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
@@ -53,6 +51,17 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
@NotNull
|
||||
public static final KotlinFunctionIntrinsic EQUALS = new KotlinFunctionIntrinsic("equals");
|
||||
@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() {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -120,6 +129,7 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
private TopLevelFIF() {
|
||||
add(pattern("jet", "toString").receiverExists(), new KotlinFunctionIntrinsic("toString"));
|
||||
add(pattern("jet", "equals").receiverExists(), EQUALS);
|
||||
add(pattern("jet", "identityEquals").receiverExists(), IDENTITY_EQUALS);
|
||||
add(pattern(NamePredicate.PRIMITIVE_NUMBERS, "equals"), EQUALS);
|
||||
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
|
||||
add(pattern("jet", "arrayOfNulls"), new KotlinFunctionIntrinsic("nullArray"));
|
||||
|
||||
+21
-3
@@ -16,6 +16,7 @@
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
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.PsiUtils.getBaseExpression;
|
||||
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.translateExclForBinaryEqualLikeExpr;
|
||||
|
||||
public final class UnaryOperationTranslator {
|
||||
private UnaryOperationTranslator() {
|
||||
@@ -46,7 +49,12 @@ public final class UnaryOperationTranslator {
|
||||
if (IncrementTranslator.isIncrement(expression)) {
|
||||
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) {
|
||||
@@ -58,11 +66,21 @@ public final class UnaryOperationTranslator {
|
||||
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
|
||||
private static JsExpression translateAsCall(@NotNull JetUnaryExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
@NotNull TranslationContext context,
|
||||
@NotNull JsExpression baseExpression) {
|
||||
return CallBuilder.build(context)
|
||||
.receiver(TranslationUtils.translateBaseExpression(context, expression))
|
||||
.receiver(baseExpression)
|
||||
.args(Collections.<JsExpression>emptyList())
|
||||
.resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference()))
|
||||
.type(CallType.NORMAL).translate();
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
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.JsAstUtils.assignment;
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
public static JsBinaryOperation isNullCheck(@NotNull JsExpression expressionToCheck) {
|
||||
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