diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 381b9217ce2..5991d28f1f1 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -7,19 +7,14 @@ - - - - + + + - - - - - - + + @@ -90,78 +85,31 @@ - + - - + + - - - - - - - - - - - - + - - + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -170,16 +118,63 @@ - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -246,7 +241,7 @@ - + @@ -300,22 +295,22 @@ @@ -390,6 +385,46 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -900,6 +773,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + localhost @@ -1040,21 +982,21 @@ - + - + - + - - + + @@ -1098,7 +1040,7 @@ @@ -1145,116 +1087,116 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java index 09d37bbd348..1b583c11257 100644 --- a/js/src/com/google/dart/compiler/util/AstUtil.java +++ b/js/src/com/google/dart/compiler/util/AstUtil.java @@ -8,7 +8,6 @@ import com.google.dart.compiler.InternalCompilerException; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.common.SourceInfo; -import java.util.Arrays; import java.util.List; /** @@ -321,17 +320,4 @@ public class AstUtil { public static JsExpression equalsTrue(JsExpression expression, JsProgram program) { return equals(expression, program.getTrueLiteral()); } - - public static JsBinaryOperation comma(JsExpression... expressions) { - return comma(Arrays.asList(expressions)); - } - - public static JsBinaryOperation comma(List expressions) { - assert expressions.size() >= 2 : "Comma operator applicable to two or more expressions"; - JsBinaryOperation result = new JsBinaryOperation(JsBinaryOperator.COMMA, expressions.get(0), expressions.get(1)); - for (int i = 2; i < expressions.size(); ++i) { - result = new JsBinaryOperation(JsBinaryOperator.COMMA, result, expressions.get(i)); - } - return result; - } } diff --git a/translator/src/org/jetbrains/k2js/translate/InitializerGenerator.java b/translator/src/org/jetbrains/k2js/translate/InitializerGenerator.java index 2126333201f..c6a4140c269 100644 --- a/translator/src/org/jetbrains/k2js/translate/InitializerGenerator.java +++ b/translator/src/org/jetbrains/k2js/translate/InitializerGenerator.java @@ -36,6 +36,8 @@ public class InitializerGenerator { return initializer; } + //TODO: track context change points, make them consistent, make sure that inside class declaration block + // classes reference their ancestor by aliases @NotNull private JsFunction generateInitializeFunction() { AbstractInitializerVisitor visitor; diff --git a/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java index 249b50ee6a0..ccfa13639c0 100644 --- a/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/UnaryOperationTranslator.java @@ -63,7 +63,7 @@ public final class UnaryOperationTranslator extends OperationTranslator { @NotNull JsExpression translate() { - if (operationReference != null) { + if ((operationReference != null) || isPropertyAccess) { return translateOverload(); } return jsUnaryExpression(); @@ -84,18 +84,21 @@ public final class UnaryOperationTranslator extends OperationTranslator { @NotNull private JsExpression asPrefix() { if (isVariableReassignment) { - return variableReassignment(); + return variableReassignment(baseExpression); } - return overloadedMethodInvocation(baseExpression); + return operationExpression(baseExpression); } + //TODO: decide if this expression can be optimised in case of direct access (not property) @NotNull private JsExpression asPostfixWithReassignment() { // code fragment: expr(a++) - // generate: expr( (t = a, a = a.inc(), t) ) - TemporaryVariable t = declareTemporary(baseExpression); - JsExpression variableReassignment = variableReassignment(); - return AstUtil.comma(t.assignmentExpression(), variableReassignment, t.nameReference()); + // generate: expr( (t1 = a, t2 = t1, a = t1.inc(), t2) ) + TemporaryVariable t1 = declareTemporary(baseExpression); + TemporaryVariable t2 = declareTemporary(t1.nameReference()); + JsExpression variableReassignment = variableReassignment(t1.nameReference()); + return AstUtil.newSequence(t1.assignmentExpression(), t2.assignmentExpression(), + variableReassignment, t2.nameReference()); } @NotNull @@ -105,41 +108,44 @@ public final class UnaryOperationTranslator extends OperationTranslator { assert operationReference != null; TemporaryVariable t1 = declareTemporary(baseExpression); TemporaryVariable t2 = declareTemporary(t1.nameReference()); - JsExpression methodCall = overloadedMethodInvocation(t2.nameReference()); + JsExpression methodCall = operationExpression(t2.nameReference()); JsExpression returnedValue = t1.nameReference(); - return AstUtil.comma(t1.assignmentExpression(), t2.assignmentExpression(), methodCall, returnedValue); + return AstUtil.newSequence(t1.assignmentExpression(), t2.assignmentExpression(), methodCall, returnedValue); } //TODO: should modify this for properties @NotNull - private JsExpression variableReassignment() { + private JsExpression variableReassignment(@NotNull JsExpression toCallMethodUpon) { if (isPropertyAccess) { - return propertyReassignment(); + return propertyReassignment(toCallMethodUpon); } - return localVariableReassignment(); + return localVariableReassignment(toCallMethodUpon); } - private JsExpression localVariableReassignment() { + private JsExpression localVariableReassignment(@NotNull JsExpression toCallMethodUpon) { assert baseExpression instanceof JsNameRef : "Base expression should be an l-value"; - return AstUtil.newAssignment((JsNameRef) baseExpression, overloadedMethodInvocation(baseExpression)); + return AstUtil.newAssignment((JsNameRef) baseExpression, operationExpression(toCallMethodUpon)); } @NotNull - private JsExpression propertyReassignment() { + private JsExpression propertyReassignment(@NotNull JsExpression toCallMethodUpon) { JetExpression jetBaseExpression = getBaseExpression(); PropertyAccessTranslator propertyAccessTranslator = Translation.propertyAccessTranslator(translationContext()); JsInvocation setterCall = propertyAccessTranslator.translateAsPropertySetterCall(jetBaseExpression); assert propertyAccessTranslator.canBePropertyGetterCall(jetBaseExpression) : "Should be a getter call"; - JsExpression overloadedMethodCallOnPropertyGetter = overloadedMethodInvocation(baseExpression); + JsExpression overloadedMethodCallOnPropertyGetter = operationExpression(toCallMethodUpon); setterCall.setArguments(Arrays.asList(overloadedMethodCallOnPropertyGetter)); return setterCall; } @NotNull - private JsExpression overloadedMethodInvocation(@NotNull JsExpression receiver) { - AstUtil.setQualifier(operationReference, receiver); - return AstUtil.newInvocation(operationReference); + private JsExpression operationExpression(@NotNull JsExpression receiver) { + if (operationReference != null) { + AstUtil.setQualifier(operationReference, receiver); + return AstUtil.newInvocation(operationReference); + } + return new JsPrefixOperation(OperatorTable.getUnaryOperator(getOperationToken()), receiver); } @NotNull diff --git a/translator/test/org/jetbrains/k2js/test/FunctionTest.java b/translator/test/org/jetbrains/k2js/test/FunctionTest.java index 3b41d6d0a41..b5155e10af0 100644 --- a/translator/test/org/jetbrains/k2js/test/FunctionTest.java +++ b/translator/test/org/jetbrains/k2js/test/FunctionTest.java @@ -54,4 +54,5 @@ public class FunctionTest extends AbstractExpressionTest { testFooBoxIsOk("closureWithParameterAndBoxing.jet"); } + } diff --git a/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java b/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java index 60c4a939d53..217c25e0bbd 100644 --- a/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java +++ b/translator/test/org/jetbrains/k2js/test/OperatorOverloadingTest.java @@ -43,4 +43,14 @@ public class OperatorOverloadingTest extends TranslationTest { public void postfixOnProperty() throws Exception { testFooBoxIsTrue("postfixOnProperty.kt"); } + + @Test + public void operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce() throws Exception { + testFooBoxIsTrue("operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce.kt"); + } + + @Test + public void unaryOnIntProperty() throws Exception { + testFooBoxIsTrue("unaryOnIntProperty.kt"); + } } diff --git a/translator/testFiles/operatorOverloading/cases/operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce.kt b/translator/testFiles/operatorOverloading/cases/operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce.kt new file mode 100644 index 00000000000..0a4f4fc0045 --- /dev/null +++ b/translator/testFiles/operatorOverloading/cases/operatorOverloadOnPropertyCallGetterAndSetterOnlyOnce.kt @@ -0,0 +1,32 @@ +namespace foo + +class MyInt(i : Int) { + var b = i + fun inc() : MyInt { + b = b + 1; + return this; + } +} + +class A() { + + var gc = 0 + var sc = 0 + + + var b = MyInt(0) + get() { + gc = gc + 1; + return $b; + } + set(a : MyInt) { + sc = sc + 1; + } +} + + +fun box() : Boolean { + val t = A() + val d = t.b++; + return (t.sc == 1) && (t.gc == 1); +} \ No newline at end of file diff --git a/translator/testFiles/operatorOverloading/cases/unaryOnIntProperty.kt b/translator/testFiles/operatorOverloading/cases/unaryOnIntProperty.kt new file mode 100644 index 00000000000..1deb16a8d6d --- /dev/null +++ b/translator/testFiles/operatorOverloading/cases/unaryOnIntProperty.kt @@ -0,0 +1,15 @@ +namespace foo + +class MyInt(i : Int) { + var b = i + fun inc() : MyInt { + b = b++; + return this; + } +} + +fun box() : Boolean { + var t = MyInt(0) + t++; + return (t.b == 0) +} \ No newline at end of file