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 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -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