Overloading operations via extension functions.

Also inline useless TranslationUtils#zeroLiteral. Eliminate dead code.
This commit is contained in:
Pavel V. Talanov
2012-07-19 20:40:03 +04:00
parent 36184ded3b
commit 803be4b0d5
9 changed files with 110 additions and 53 deletions
@@ -103,4 +103,20 @@ public final class OperatorOverloadingTest extends SingleFileTranslationTest {
public void testOverloadPlusAssignArrayList() throws Exception {
checkFooBoxIsOk("overloadPlusAssignArrayList.kt");
}
public void testOverloadPlusAssignViaExtensionFunction() throws Exception {
fooBoxTest();
}
public void testOverloadPlusViaExtensionFunction() throws Exception {
fooBoxTest();
}
public void testOverloadPlusAssignViaPlusExtensionFunction() throws Exception {
fooBoxTest();
}
public void testOverloadUnaryOperationsViaExtensionFunctions() throws Exception {
fooBoxTest();
}
}
@@ -25,7 +25,6 @@ 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.general.AbstractTranslator;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isCompareTo;
@@ -69,6 +68,6 @@ public final class CompareToTranslator extends AbstractTranslator {
private JsExpression translate() {
JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(getOperationToken(expression));
JsExpression methodCall = BinaryOperationTranslator.translateAsOverloadedCall(expression, context());
return new JsBinaryOperation(correspondingOperator, methodCall, TranslationUtils.zeroLiteral(context()));
return new JsBinaryOperation(correspondingOperator, methodCall, context().program().getNumberLiteral(0));
}
}
@@ -17,14 +17,12 @@
package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodReferenceForOverloadedOperation;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import org.jetbrains.k2js.translate.utils.BindingUtils;
/**
* @author Pavel Talanov
@@ -33,17 +31,20 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
@NotNull
public static JsExpression doTranslate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
return (new OverloadedAssignmentTranslator(expression, context)).translate();
}
@NotNull
private final JsNameRef operationReference;
private final FunctionDescriptor operationDescriptor;
private OverloadedAssignmentTranslator(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
super(expression, context);
this.operationReference = getMethodReferenceForOverloadedOperation(context, expression);
FunctionDescriptor functionDescriptor =
BindingUtils.getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null : "";
this.operationDescriptor = functionDescriptor;
}
@NotNull
@@ -61,8 +62,10 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsExpression overloadedMethodInvocation() {
setQualifier(operationReference, accessTranslator.translateAsGet());
return AstUtil.newInvocation(operationReference, right);
return CallBuilder.build(context())
.descriptor(operationDescriptor)
.receiver(accessTranslator.translateAsGet())
.args(right)
.translate();
}
}
@@ -17,14 +17,13 @@
package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodReferenceForOverloadedOperation;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
/**
* @author Pavel Talanov
@@ -32,20 +31,24 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodRefer
public final class OverloadedIncrementTranslator extends IncrementTranslator {
@NotNull
private final JsNameRef operationReference;
private final FunctionDescriptor operationDescriptor;
/*package*/ OverloadedIncrementTranslator(@NotNull JetUnaryExpression expression,
@NotNull TranslationContext context) {
super(expression, context);
this.operationReference = getMethodReferenceForOverloadedOperation(context, expression);
FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null : "Descriptor should not be null for overloaded increment expression.";
this.operationDescriptor = functionDescriptor;
}
@Override
@NotNull
protected JsExpression operationExpression(@NotNull JsExpression receiver) {
setQualifier(operationReference, receiver);
return AstUtil.newInvocation(operationReference);
return CallBuilder.build(context())
.receiver(receiver)
.descriptor(operationDescriptor)
.translate();
}
}
@@ -84,17 +84,6 @@ public final class TranslationUtils {
return or(isNull, isUndefined);
}
@NotNull
public static JsBinaryOperation nullCheck(@NotNull TranslationContext context,
@NotNull JsExpression expressionToCheck, boolean shouldBeNull) {
if (shouldBeNull) {
return isNullCheck(context, expressionToCheck);
}
else {
return notNullCheck(context, expressionToCheck);
}
}
@NotNull
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
@NotNull List<? extends ValueArgument> jetArguments) {
@@ -213,22 +202,6 @@ public final class TranslationUtils {
return false;
}
@NotNull
public static JsNameRef getMethodReferenceForOverloadedOperation(@NotNull TranslationContext context,
@NotNull JetOperationExpression expression) {
FunctionDescriptor overloadedOperationDescriptor = getFunctionDescriptorForOperationExpression
(context.bindingContext(), expression);
assert overloadedOperationDescriptor != null;
JsNameRef overloadedOperationReference = context.getNameForDescriptor(overloadedOperationDescriptor).makeRef();
assert overloadedOperationReference != null;
return overloadedOperationReference;
}
@NotNull
public static JsNumberLiteral zeroLiteral(@NotNull TranslationContext context) {
return context.program().getNumberLiteral(0);
}
@Nullable
public static JsExpression resolveThisObjectForResolvedCall(@NotNull ResolvedCall<?> call,
@NotNull TranslationContext context) {
@@ -240,10 +213,6 @@ public final class TranslationUtils {
return getThisObject(context, expectedThisDescriptor);
}
public static boolean isNullLiteral(@NotNull TranslationContext context, @NotNull JsExpression expression) {
return expression.equals(context.program().getNullLiteral());
}
public static void defineModule(@NotNull TranslationContext context, @NotNull List<JsStatement> statements,
String moduleId) {
statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
@@ -0,0 +1,16 @@
package foo
import java.util.*
fun <T> ArrayList<T>.plusAssign(other: Collection<T>) {
addAll(other)
}
fun box(): Boolean {
var v1 = ArrayList<String>()
val v2 = ArrayList<String>()
v1.add("foo")
v2.add("bar")
v1 += v2
return (v1.size() == 2 && v1[0] == "foo" && v1[1] == "bar")
}
@@ -0,0 +1,19 @@
package foo
import java.util.*
fun <T> ArrayList<T>.plus(other: Collection<T>): List<T> {
val c = ArrayList<T>()
c.addAll(this)
c.addAll(other)
return c
}
fun box(): Boolean {
var v1 = ArrayList<String>()
val v2 = ArrayList<String>()
v1.add("foo")
v2.add("bar")
v1 += v2
return (v1.size() == 2 && v1[0] == "foo" && v1[1] == "bar")
}
@@ -0,0 +1,20 @@
package foo
import java.util.*
fun <T> ArrayList<T>.plus(other: Collection<T>): List<T> {
val c = ArrayList<T>()
c.addAll(this)
c.addAll(other)
return c
}
fun box(): Boolean {
var v1 = ArrayList<String>()
v1.add("foo")
val v2 = ArrayList<String>()
v2.add("bar")
val v = v1 + v2
return (v.size() == 2 && v[0] == "foo" && v[1] == "bar")
}
@@ -0,0 +1,12 @@
package foo
class A(val c: Int) {}
fun A.inc() = A(5)
fun A.dec() = A(10)
fun box(): Boolean {
var a = A(1)
return ((++a).c == 5 && (a++).c == 5 && (--a).c == 10 && (a--).c == 10)
}