Support for elvis operator.

This commit is contained in:
Pavel V. Talanov
2012-04-02 20:45:36 +04:00
parent 3fbbc71dcb
commit fc683e8141
3 changed files with 47 additions and 5 deletions
@@ -117,4 +117,8 @@ public final class MiscTest extends AbstractExpressionTest {
public void testWhenReturnedWithoutBlock() throws Exception {
checkFooBoxIsTrue("whenReturnedWithoutBlock.kt");
}
public void testElvis() throws Exception {
checkFooBoxIsTrue("elvis.kt");
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,6 +33,7 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import org.jetbrains.k2js.translate.reference.CallType;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import static org.jetbrains.k2js.translate.operation.AssignmentTranslator.isAssignmentOperator;
import static org.jetbrains.k2js.translate.operation.CompareToTranslator.isCompareToCall;
@@ -71,11 +73,14 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
super(context);
this.expression = expression;
this.operationDescriptor =
getFunctionDescriptorForOperationExpression(bindingContext(), expression);
getFunctionDescriptorForOperationExpression(bindingContext(), expression);
}
@NotNull
private JsExpression translate() {
if (isElvisOperator(expression)) {
return translateAsElvisOperator(expression);
}
if (isAssignmentOperator(expression)) {
return AssignmentTranslator.translate(expression, context());
}
@@ -86,13 +91,26 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
return CompareToTranslator.translate(expression, context());
}
assert operationDescriptor != null :
"Overloadable operations must have not null descriptor";
"Overloadable operations must have not null descriptor";
if (isEquals(operationDescriptor)) {
return translateAsEqualsCall();
}
return translateAsOverloadedBinaryOperation();
}
private static boolean isElvisOperator(@NotNull JetBinaryExpression expression) {
return getOperationToken(expression).equals(JetTokens.ELVIS);
}
//TODO: use some generic mechanism
@NotNull
private JsExpression translateAsElvisOperator(@NotNull JetBinaryExpression expression) {
JsExpression translatedLeft = translateLeftExpression(context(), expression);
JsExpression translatedRight = translateRightExpression(context(), expression);
JsBinaryOperation leftIsNotNull = JsAstUtils.inequality(translatedLeft, program().getNullLiteral());
return new JsConditional(leftIsNotNull, translatedLeft, translatedRight);
}
private boolean isNotOverloadable() {
return operationDescriptor == null;
}
@@ -120,9 +138,9 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
private JsExpression translateAsOverloadedBinaryOperation() {
CallBuilder callBuilder = setReceiverAndArguments();
ResolvedCall<?> resolvedCall1 =
getResolvedCall(bindingContext(), expression.getOperationReference());
getResolvedCall(bindingContext(), expression.getOperationReference());
JsExpression result = callBuilder.resolvedCall(resolvedCall1)
.type(CallType.NORMAL).translate();
.type(CallType.NORMAL).translate();
return mayBeWrapWithNegation(result);
}
@@ -150,5 +168,4 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
return result;
}
}
}
@@ -0,0 +1,21 @@
package foo
fun box() : Boolean {
if (f(null) != false) {
return false;
}
if (f(2) != true) {
return false;
}
if (f(1) != false) {
return true;
}
return true
}
fun Int.isEven() = (this % 2) == 0
fun f(a : Int?) : Boolean {
return a?.isEven() ?: false
}