001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.js.translate.operation;
018    
019    import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
020    import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
021    import com.google.dart.compiler.backend.js.ast.JsExpression;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.kotlin.js.translate.context.TranslationContext;
024    import org.jetbrains.kotlin.lexer.KtToken;
025    import org.jetbrains.kotlin.psi.KtBinaryExpression;
026    import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
027    import org.jetbrains.kotlin.types.expressions.OperatorConventions;
028    
029    import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
030    import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
031    
032    public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
033    
034    
035        @NotNull
036        public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
037                                               @NotNull TranslationContext context) {
038            return (new IntrinsicAssignmentTranslator(expression, context)).translate();
039        }
040    
041        private IntrinsicAssignmentTranslator(@NotNull KtBinaryExpression expression,
042                                              @NotNull TranslationContext context) {
043            super(expression, context);
044        }
045    
046        @NotNull
047        private JsExpression translate() {
048            if (isAssignment(getOperationToken(expression))) {
049                return translateAsPlainAssignment();
050            }
051            return translateAsAssignmentOperation();
052        }
053    
054        @NotNull
055        private JsExpression translateAsAssignmentOperation() {
056            if (expression.getLeft() instanceof KtSimpleNameExpression) {
057                return translateAsPlainAssignmentOperation();
058            }
059            return translateAsAssignToCounterpart();
060        }
061    
062        @NotNull
063        private JsExpression translateAsAssignToCounterpart() {
064            JsBinaryOperator operator = getCounterpartOperator();
065            JsBinaryOperation counterpartOperation =
066                    new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
067            return accessTranslator.translateAsSet(counterpartOperation);
068        }
069    
070        @NotNull
071        private JsBinaryOperator getCounterpartOperator() {
072            KtToken assignmentOperationToken = getOperationToken(expression);
073            assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(assignmentOperationToken);
074            KtToken counterpartToken = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(assignmentOperationToken);
075            assert OperatorTable.hasCorrespondingBinaryOperator(counterpartToken) :
076                    "Unsupported token encountered: " + counterpartToken.toString();
077            return OperatorTable.getBinaryOperator(counterpartToken);
078        }
079    
080        @NotNull
081        private JsExpression translateAsPlainAssignmentOperation() {
082            JsBinaryOperator operator = getAssignmentOperator();
083            return new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
084        }
085    
086        @NotNull
087        private JsBinaryOperator getAssignmentOperator() {
088            KtToken token = getOperationToken(expression);
089            assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(token);
090            assert OperatorTable.hasCorrespondingBinaryOperator(token) :
091                    "Unsupported token encountered: " + token.toString();
092            return OperatorTable.getBinaryOperator(token);
093        }
094    
095        @NotNull
096        private JsExpression translateAsPlainAssignment() {
097            return accessTranslator.translateAsSet(right);
098        }
099    }