diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2f2649adf2b..bd85c49fbca 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,11 +6,13 @@ - + + - - + + + @@ -48,7 +50,7 @@ - + - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -159,6 +188,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -168,60 +224,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -229,7 +231,7 @@ - + @@ -337,22 +339,22 @@ @@ -998,6 +1000,7 @@ + @@ -1012,7 +1015,6 @@ - @@ -1048,7 +1050,7 @@ @@ -1089,13 +1092,6 @@ - - - - - - - @@ -1103,86 +1099,9 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1194,15 +1113,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java index bfe784e5906..7060a164e84 100644 --- a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java @@ -314,10 +314,19 @@ public final class ExpressionVisitor extends TranslatorVisitor { return selector; } + @Override @NotNull - public JsNode visitPrefixExpression(@NotNull JetUnaryExpression expression, + public JsNode visitPrefixExpression(@NotNull JetPrefixExpression expression, @NotNull TranslationContext context) { - return Translation.operationTranslator(context).translate(expression); + return Translation.operationTranslator(context).translatePrefixOperation(expression); + + } + + @Override + @NotNull + public JsNode visitPostfixExpression(@NotNull JetPostfixExpression expression, + @NotNull TranslationContext context) { + return Translation.operationTranslator(context).translatePostfixOperation(expression); } diff --git a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java index 784ec969fe3..de55d7f3302 100644 --- a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java @@ -1,14 +1,11 @@ package org.jetbrains.k2js.translate; -import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsInvocation; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; +import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetBinaryExpression; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetUnaryExpression; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lexer.JetToken; import java.util.Arrays; @@ -23,13 +20,38 @@ public final class OperationTranslator extends AbstractTranslator { return new OperationTranslator(context); } - private OperationTranslator(TranslationContext context) { + private OperationTranslator(@NotNull TranslationContext context) { super(context); } @NotNull - JsExpression translate(JetUnaryExpression expression) { - return translationContext().program().getBooleanLiteral(false); + JsPostfixOperation translatePostfixOperation(@NotNull JetPostfixExpression expression) { + JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); + JsExpression baseExpression = translateBaseExpression(expression); + return new JsPostfixOperation(operator, baseExpression); + } + + @NotNull + JsPrefixOperation translatePrefixOperation(@NotNull JetPrefixExpression expression) { + JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); + JsExpression baseExpression = translateBaseExpression(expression); + return new JsPrefixOperation(operator, baseExpression); + } + + @NotNull + private JsExpression translateBaseExpression(@NotNull JetUnaryExpression expression) { + JetExpression baseExpression = expression.getBaseExpression(); + assert baseExpression != null : "Unary operation should have not null base expression"; + return AstUtil.convertToExpression + (Translation.translateExpression(baseExpression, translationContext())); + } + + @NotNull + private JetToken getOperationToken(@NotNull JetUnaryExpression expression) { + JetSimpleNameExpression operationExpression = expression.getOperationSign(); + IElementType elementType = operationExpression.getReferencedNameElementType(); + assert elementType instanceof JetToken : "Unary operation should have IElementType of type JetToken"; + return (JetToken) elementType; } @NotNull @@ -41,11 +63,9 @@ public final class OperationTranslator extends AbstractTranslator { return translateAsBinaryOperation(expression); } - - //TODO method too long @Nullable public JsInvocation translateAsSetterCall(@NotNull JetBinaryExpression expression) { - JetToken jetOperationToken = (JetToken) expression.getOperationToken(); + JetToken jetOperationToken = getOperationToken(expression); if (!OperatorTable.isAssignment(jetOperationToken)) { return null; } @@ -55,24 +75,31 @@ public final class OperationTranslator extends AbstractTranslator { if (setterCall == null) { return null; } - JetExpression rightExpression = expression.getRight(); - assert rightExpression != null : "Selector should not be null"; - JsExpression right = AstUtil.convertToExpression - (Translation.translateExpression(rightExpression, translationContext())); + JsExpression right = translateRightExpression(expression); setterCall.setArguments(Arrays.asList(right)); return setterCall; } + @NotNull + private JetToken getOperationToken(@NotNull JetBinaryExpression expression) { + return (JetToken) expression.getOperationToken(); + } + @NotNull private JsExpression translateAsBinaryOperation(@NotNull JetBinaryExpression expression) { JsExpression left = AstUtil.convertToExpression (Translation.translateExpression(expression.getLeft(), translationContext())); + JsExpression right = translateRightExpression(expression); + JetToken jetOperationToken = getOperationToken(expression); + return new JsBinaryOperation(OperatorTable.getBinaryOperator(jetOperationToken), left, right); + } + + @NotNull + private JsExpression translateRightExpression(@NotNull JetBinaryExpression expression) { JetExpression rightExpression = expression.getRight(); assert rightExpression != null : "Binary expression should have a right expression"; - JsExpression right = AstUtil.convertToExpression + return AstUtil.convertToExpression (Translation.translateExpression(rightExpression, translationContext())); - JetToken jetOperationToken = (JetToken) expression.getOperationToken(); - return new JsBinaryOperation(OperatorTable.getBinaryOperator(jetOperationToken), left, right); } diff --git a/translator/src/org/jetbrains/k2js/translate/OperatorTable.java b/translator/src/org/jetbrains/k2js/translate/OperatorTable.java index e8f490b8791..040da982e21 100644 --- a/translator/src/org/jetbrains/k2js/translate/OperatorTable.java +++ b/translator/src/org/jetbrains/k2js/translate/OperatorTable.java @@ -1,7 +1,8 @@ package org.jetbrains.k2js.translate; import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; -import com.google.dart.compiler.backend.js.ast.JsOperator; +import com.google.dart.compiler.backend.js.ast.JsUnaryOperator; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; @@ -14,30 +15,43 @@ import java.util.Map; public final class OperatorTable { - private static Map map = new HashMap(); + private static Map binaryOperatorsMap = new HashMap(); + private static Map unaryOperatorsMap = new HashMap(); static { - map.put(JetTokens.PLUS, JsBinaryOperator.ADD); - map.put(JetTokens.MINUS, JsBinaryOperator.SUB); - map.put(JetTokens.MUL, JsBinaryOperator.MUL); - map.put(JetTokens.DIV, JsBinaryOperator.DIV); - map.put(JetTokens.EQ, JsBinaryOperator.ASG); - map.put(JetTokens.GT, JsBinaryOperator.GT); - map.put(JetTokens.GTEQ, JsBinaryOperator.GTE); - map.put(JetTokens.LT, JsBinaryOperator.LT); - map.put(JetTokens.LTEQ, JsBinaryOperator.LTE); - map.put(JetTokens.EQEQ, JsBinaryOperator.EQ); - map.put(JetTokens.ANDAND, JsBinaryOperator.AND); - map.put(JetTokens.EXCLEQ, JsBinaryOperator.NEQ); + unaryOperatorsMap.put(JetTokens.PLUSPLUS, JsUnaryOperator.INC); //++ + unaryOperatorsMap.put(JetTokens.MINUSMINUS, JsUnaryOperator.DEC); //-- + unaryOperatorsMap.put(JetTokens.EXCL, JsUnaryOperator.NOT); //! + unaryOperatorsMap.put(JetTokens.MINUS, JsUnaryOperator.NEG); //- + unaryOperatorsMap.put(JetTokens.PLUS, JsUnaryOperator.POS); //+ } - public static JsBinaryOperator getBinaryOperator(JetToken token) { - assert JetTokens.OPERATIONS.contains(token) : "Token should represent a binary operation!"; - JsOperator result = map.get(token); - if (result instanceof JsBinaryOperator) { - return (JsBinaryOperator) result; - } - throw new AssertionError("Invalid map: should contain token: " + token.toString()); + //TODO : not all operators + static { + binaryOperatorsMap.put(JetTokens.PLUS, JsBinaryOperator.ADD); + binaryOperatorsMap.put(JetTokens.MINUS, JsBinaryOperator.SUB); + binaryOperatorsMap.put(JetTokens.MUL, JsBinaryOperator.MUL); + binaryOperatorsMap.put(JetTokens.DIV, JsBinaryOperator.DIV); + binaryOperatorsMap.put(JetTokens.EQ, JsBinaryOperator.ASG); + binaryOperatorsMap.put(JetTokens.GT, JsBinaryOperator.GT); + binaryOperatorsMap.put(JetTokens.GTEQ, JsBinaryOperator.GTE); + binaryOperatorsMap.put(JetTokens.LT, JsBinaryOperator.LT); + binaryOperatorsMap.put(JetTokens.LTEQ, JsBinaryOperator.LTE); + binaryOperatorsMap.put(JetTokens.EQEQ, JsBinaryOperator.EQ); + binaryOperatorsMap.put(JetTokens.ANDAND, JsBinaryOperator.AND); + binaryOperatorsMap.put(JetTokens.EXCLEQ, JsBinaryOperator.NEQ); + } + + @NotNull + public static JsBinaryOperator getBinaryOperator(@NotNull JetToken token) { + assert JetTokens.OPERATIONS.contains(token) : "Token should represent an operation!"; + return binaryOperatorsMap.get(token); + } + + @NotNull + public static JsUnaryOperator getUnaryOperator(@NotNull JetToken token) { + assert JetTokens.OPERATIONS.contains(token) : "Token should represent an operation!"; + return unaryOperatorsMap.get(token); } public static boolean isAssignment(JetToken token) { diff --git a/translator/test/org/jetbrains/k2js/test/ExpressionTest.java b/translator/test/org/jetbrains/k2js/test/ExpressionTest.java index 9cbeaaa964c..c716e9c6972 100644 --- a/translator/test/org/jetbrains/k2js/test/ExpressionTest.java +++ b/translator/test/org/jetbrains/k2js/test/ExpressionTest.java @@ -85,4 +85,14 @@ public final class ExpressionTest extends TranslationTest { public void functionWithTwoParametersCall() throws Exception { testFooBoxIsTrue("functionWithTwoParametersCall.kt"); } + + @Test + public void prefixIntOperations() throws Exception { + testFooBoxIsTrue("prefixIntOperations.kt"); + } + + @Test + public void postfixIntOperations() throws Exception { + testFooBoxIsTrue("postfixIntOperations.kt"); + } } diff --git a/translator/testFiles/expression/cases/postfixIntOperations.kt b/translator/testFiles/expression/cases/postfixIntOperations.kt new file mode 100644 index 00000000000..0c73eb6d786 --- /dev/null +++ b/translator/testFiles/expression/cases/postfixIntOperations.kt @@ -0,0 +1,10 @@ +namespace foo + +fun box() : Boolean { + var a = 3; + val b = a++; + a--; + a--; + return (a++ == 2) && (b == 3) +} + diff --git a/translator/testFiles/expression/cases/prefixIntOperations.kt b/translator/testFiles/expression/cases/prefixIntOperations.kt new file mode 100644 index 00000000000..c1a568b0e02 --- /dev/null +++ b/translator/testFiles/expression/cases/prefixIntOperations.kt @@ -0,0 +1,10 @@ +namespace foo + +fun box() : Boolean { + var a = 3; + val b = ++a; + --a; + --a; + return (--a == 1) && (b == 4) +} +