diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 6b42a67e176..23395ef3d72 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -8,9 +8,14 @@
-
+
+
+
-
+
+
+
+
@@ -82,85 +87,13 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
@@ -181,91 +114,91 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -292,22 +225,22 @@
@@ -457,32 +390,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -502,28 +409,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -573,10 +458,6 @@
-
-
-
-
@@ -997,21 +878,21 @@
-
+
-
+
-
+
-
-
+
+
@@ -1102,51 +983,86 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1158,64 +1074,29 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
-
-
-
-
-
-
diff --git a/js/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java b/js/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java
index 40cb649319c..777c33730d0 100644
--- a/js/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java
+++ b/js/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java
@@ -5,6 +5,7 @@
package com.google.dart.compiler.backend.js.ast;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -65,4 +66,8 @@ public final class JsInvocation extends JsExpression implements HasArguments {
assert this.args.isEmpty() : "Arguments already set.";
this.args.addAll(arguments);
}
+
+ public void setArguments(JsExpression... arguments) {
+ setArguments(Arrays.asList(arguments));
+ }
}
diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java
index 1b583c11257..eca3f62f74b 100644
--- a/js/src/com/google/dart/compiler/util/AstUtil.java
+++ b/js/src/com/google/dart/compiler/util/AstUtil.java
@@ -278,7 +278,7 @@ public class AstUtil {
}
public static JsExpression extractExpressionFromStatement(JsStatement statement) {
- assert statement instanceof JsExprStmt : "Cannot extract exprssion form statement: " + statement;
+ assert statement instanceof JsExprStmt : "Cannot extract expression from statement: " + statement;
return (((JsExprStmt) statement).getExpression());
}
diff --git a/translator/src/org/jetbrains/k2js/translate/BinaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/BinaryOperationTranslator.java
index 4e87c499524..921d4bd4777 100644
--- a/translator/src/org/jetbrains/k2js/translate/BinaryOperationTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/BinaryOperationTranslator.java
@@ -11,8 +11,6 @@ import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lexer.JetToken;
-import java.util.Arrays;
-
/**
* @author Talanov Pavel
*/
@@ -26,49 +24,56 @@ public final class BinaryOperationTranslator extends OperationTranslator {
@NotNull
private final JetBinaryExpression expression;
+ private final boolean isPropertyOnTheLeft;
+ private final boolean isVariableReassignment;
+ @NotNull
+ private final JsExpression left;
+ @NotNull
+ private final JsExpression right;
+ @Nullable
+ private final JsNameRef operationReference;
private BinaryOperationTranslator(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
super(context);
this.expression = expression;
+ this.isPropertyOnTheLeft = isPropertyAccess(expression.getLeft());
+ this.isVariableReassignment = isVariableReassignment(expression);
+ this.operationReference = getOverloadedOperationReference(expression);
+ this.right = translateRightExpression();
+ //TODO: decide whether it is harmful to possibly translate left expression more than once
+ this.left = translateLeftExpression();
}
@NotNull
JsExpression translate() {
- JsInvocation setterCall = translateAsSetterCall();
- if (setterCall != null) {
- return setterCall;
+ if (operationReference != null) {
+ return asOverloadedMethodCall();
}
- return translateAsBinaryOperation();
- }
-
- //TODO: method too long
- @Nullable
- public JsInvocation translateAsSetterCall() {
- JetToken jetOperationToken = getOperationToken();
- if (!OperatorTable.isAssignment(jetOperationToken)) {
- return null;
- }
- JetExpression leftExpression = expression.getLeft();
- PropertyAccessTranslator propertyAccessTranslator = Translation.propertyAccessTranslator(translationContext());
- if (!propertyAccessTranslator.canBePropertySetterCall(leftExpression)) {
- return null;
- }
- JsInvocation setterCall = propertyAccessTranslator.translateAsPropertySetterCall(leftExpression);
- JsExpression right = translateRightExpression();
- setterCall.setArguments(Arrays.asList(right));
- return setterCall;
+ return asBinaryOperation();
}
@NotNull
- private JsExpression translateAsBinaryOperation() {
+ private JsExpression asOverloadedMethodCall() {
+ if (isPropertyOnTheLeft) {
+ return overloadOnProperty();
+ }
+ return overloadedMethodInvocation();
+ }
- JsExpression left = Translation.translateAsExpression(expression.getLeft(), translationContext());
- JsExpression right = translateRightExpression();
+ @NotNull
+ private JsExpression overloadOnProperty() {
+ if (isVariableReassignment) {
+ return setterCall(overloadedMethodInvocation());
+ } else {
+ return overloadedMethodInvocation();
+ }
+ }
- JsNameRef operationReference = getOverloadedOperationReference(expression);
- if (operationReference != null) {
- return overloadedMethodInvocation(left, right, operationReference);
+ @NotNull
+ private JsExpression asBinaryOperation() {
+ if (isPropertyOnTheLeft && OperatorTable.isAssignment(getOperationToken())) {
+ return setterCall(right);
}
JetToken token = getOperationToken();
if (OperatorTable.hasCorrespondingBinaryOperator(token)) {
@@ -76,15 +81,18 @@ public final class BinaryOperationTranslator extends OperationTranslator {
}
if (OperatorTable.hasCorrespondingFunctionInvocation(token)) {
JsInvocation functionInvocation = OperatorTable.getCorrespondingFunctionInvocation(token);
- functionInvocation.setArguments(Arrays.asList(left, right));
+ functionInvocation.setArguments(left, right);
return functionInvocation;
}
throw new AssertionError("Unsupported token encountered: " + token.toString());
}
+ private JsExpression translateLeftExpression() {
+ return Translation.translateAsExpression(expression.getLeft(), translationContext());
+ }
+
@NotNull
- private JsExpression overloadedMethodInvocation(@NotNull JsExpression left, @NotNull JsExpression right,
- @NotNull JsNameRef operationReference) {
+ private JsExpression overloadedMethodInvocation() {
AstUtil.setQualifier(operationReference, left);
return AstUtil.newInvocation(operationReference, right);
}
@@ -101,5 +109,13 @@ public final class BinaryOperationTranslator extends OperationTranslator {
return (JetToken) expression.getOperationToken();
}
+ @NotNull
+ public JsInvocation setterCall(@NotNull JsExpression assignTo) {
+ PropertyAccessTranslator propertyAccessTranslator = Translation.propertyAccessTranslator(translationContext());
+ JsInvocation setterCall = propertyAccessTranslator.translateAsPropertySetterCall(expression.getLeft());
+ setterCall.setArguments(assignTo);
+ return setterCall;
+ }
+
}
diff --git a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java
index f122d2f8dcf..b66ede09aab 100644
--- a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java
@@ -48,6 +48,17 @@ public class OperationTranslator extends AbstractTranslator {
}
+ protected boolean isPropertyAccess(@NotNull JetExpression expression) {
+ return Translation.propertyAccessTranslator(translationContext()).canBePropertyAccess(expression);
+
+ }
+
+ protected boolean isVariableReassignment(@NotNull JetExpression expression) {
+ return BindingUtils.isVariableReassignment
+ (translationContext().bindingContext(), expression);
+ }
+
+
protected final class TemporaryVariable {
@NotNull
diff --git a/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java
index 29a0b954858..72d924d32a8 100644
--- a/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java
@@ -9,7 +9,6 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
-import java.util.Arrays;
/**
* @author Talanov Pavel
@@ -48,20 +47,10 @@ public final class UnaryOperationTranslator extends OperationTranslator {
this.isVariableReassignment = isVariableReassignment(expression);
this.isStatement = BindingUtils.isStatement(translationContext().bindingContext(), expression);
this.baseExpression = translateBaseExpression();
- this.isPropertyAccess = isPropertyAccess();
+ this.isPropertyAccess = isPropertyAccess(getBaseExpression());
this.operationReference = getOverloadedOperationReference(expression);
}
- private boolean isPropertyAccess() {
- return Translation.propertyAccessTranslator(translationContext()).canBePropertyAccess(getBaseExpression());
-
- }
-
- private boolean isVariableReassignment(JetUnaryExpression expression) {
- return BindingUtils.isVariableReassignment
- (translationContext().bindingContext(), expression);
- }
-
@NotNull
JsExpression translate() {
if ((operationReference != null) || isPropertyAccess) {
@@ -136,7 +125,7 @@ public final class UnaryOperationTranslator extends OperationTranslator {
JsInvocation setterCall = propertyAccessTranslator.translateAsPropertySetterCall(jetBaseExpression);
assert propertyAccessTranslator.canBePropertyGetterCall(jetBaseExpression) : "Should be a getter call";
JsExpression overloadedMethodCallOnPropertyGetter = operationExpression(toCallMethodUpon);
- setterCall.setArguments(Arrays.asList(overloadedMethodCallOnPropertyGetter));
+ setterCall.setArguments(overloadedMethodCallOnPropertyGetter);
return setterCall;
}
diff --git a/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java b/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java
index e78656b5a9b..42f663d3f15 100644
--- a/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java
+++ b/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java
@@ -58,4 +58,19 @@ public class OperatorOverloadingTest extends TranslationTest {
public void unaryOnIntPropertyAsStatement() throws Exception {
testFooBoxIsTrue("unaryOnIntProperty2.kt");
}
+
+ @Test
+ public void binaryDivOverload() throws Exception {
+ testFooBoxIsTrue("binaryDivOverload.kt");
+ }
+
+ @Test
+ public void plusAssignNoReassign() throws Exception {
+ testFooBoxIsTrue("plusAssignNoReassign.kt");
+ }
+
+ @Test
+ public void plusAssignReassign() throws Exception {
+ testFooBoxIsTrue("plusAssignReassign.kt");
+ }
}
diff --git a/translator/testFiles/operatorOverloading/cases/binaryDivOverload.kt b/translator/testFiles/operatorOverloading/cases/binaryDivOverload.kt
new file mode 100644
index 00000000000..71612acf1e1
--- /dev/null
+++ b/translator/testFiles/operatorOverloading/cases/binaryDivOverload.kt
@@ -0,0 +1,9 @@
+namespace foo
+
+class A() {
+
+ fun div(other : A) = "hooray"
+
+}
+
+fun box() = ((A() / A()) == "hooray")
\ No newline at end of file
diff --git a/translator/testFiles/operatorOverloading/cases/plusAssignNoReassign.kt b/translator/testFiles/operatorOverloading/cases/plusAssignNoReassign.kt
new file mode 100644
index 00000000000..2c5c3771caa
--- /dev/null
+++ b/translator/testFiles/operatorOverloading/cases/plusAssignNoReassign.kt
@@ -0,0 +1,17 @@
+namespace foo
+
+class A() {
+
+ var message = ""
+ fun plusAssign(other : A) {
+ message = message + "!"
+ }
+
+}
+
+fun box() : Boolean {
+ var c = A()
+ c += A()
+ c += A()
+ return c.message == "!!"
+}
\ No newline at end of file
diff --git a/translator/testFiles/operatorOverloading/cases/plusAssignReassign.kt b/translator/testFiles/operatorOverloading/cases/plusAssignReassign.kt
new file mode 100644
index 00000000000..a1f83bb2481
--- /dev/null
+++ b/translator/testFiles/operatorOverloading/cases/plusAssignReassign.kt
@@ -0,0 +1,16 @@
+namespace foo
+
+class A(i : Int) {
+
+ val a = i
+
+ fun plusAssign(other : A) = A(this.a + other.a)
+
+}
+
+fun box() : Boolean {
+ var c = A(2)
+ val d = c
+ c += A(3)
+ return (c.a == 5) && (d.a == 2) && (d != c)
+}
\ No newline at end of file