001    /*
002     * Copyright 2010-2013 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.k2js.translate.expression.foreach;
018    
019    import com.google.dart.compiler.backend.js.ast.JsBlock;
020    import com.google.dart.compiler.backend.js.ast.JsExpression;
021    import com.google.dart.compiler.backend.js.ast.JsName;
022    import com.google.dart.compiler.backend.js.ast.JsStatement;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.jet.lang.psi.JetForExpression;
025    import org.jetbrains.k2js.translate.context.TranslationContext;
026    import org.jetbrains.k2js.translate.general.AbstractTranslator;
027    import org.jetbrains.k2js.translate.general.Translation;
028    
029    import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
030    import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
031    import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter;
032    
033    public abstract class ForTranslator extends AbstractTranslator {
034    
035        @NotNull
036        public static JsStatement translate(@NotNull JetForExpression expression,
037                                            @NotNull TranslationContext context) {
038            if (RangeLiteralForTranslator.isApplicable(expression, context)) {
039                return RangeLiteralForTranslator.doTranslate(expression, context);
040            }
041            if (RangeForTranslator.isApplicable(expression, context)) {
042                return RangeForTranslator.doTranslate(expression, context);
043            }
044            if (ArrayForTranslator.isApplicable(expression, context)) {
045                return ArrayForTranslator.doTranslate(expression, context);
046            }
047            return IteratorForTranslator.doTranslate(expression, context);
048        }
049    
050        @NotNull
051        protected final JetForExpression expression;
052        @NotNull
053        protected final JsName parameterName;
054    
055        protected ForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
056            super(context);
057            this.expression = forExpression;
058            this.parameterName = declareParameter();
059        }
060    
061        @NotNull
062        private JsName declareParameter() {
063            return context().getNameForElement(getLoopParameter(expression));
064        }
065    
066        @NotNull
067        protected JsStatement translateOriginalBodyExpression() {
068            return Translation.translateAsStatement(getLoopBody(expression), context());
069        }
070    
071        @NotNull
072        protected JsStatement translateBody(JsExpression itemValue) {
073            JsStatement currentVar = newVar(parameterName, itemValue);
074            JsStatement realBody = translateOriginalBodyExpression();
075            if (realBody instanceof JsBlock) {
076                JsBlock block = (JsBlock) realBody;
077                block.getStatements().add(0, currentVar);
078                return block;
079            }
080            else {
081                return new JsBlock(currentVar, realBody);
082            }
083        }
084    }