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 017package org.jetbrains.k2js.translate.expression.foreach; 018 019import com.google.common.collect.Lists; 020import com.google.dart.compiler.backend.js.ast.*; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.jet.lang.psi.JetExpression; 023import org.jetbrains.jet.lang.psi.JetForExpression; 024import org.jetbrains.jet.lang.types.JetType; 025import org.jetbrains.k2js.translate.context.TemporaryVariable; 026import org.jetbrains.k2js.translate.context.TranslationContext; 027import org.jetbrains.k2js.translate.general.Translation; 028import org.jetbrains.k2js.translate.utils.BindingUtils; 029 030import java.util.List; 031 032import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType; 033import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; 034import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; 035import static org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization; 036 037public final class RangeForTranslator extends ForTranslator { 038 039 @NotNull 040 public static JsStatement doTranslate(@NotNull JetForExpression expression, 041 @NotNull TranslationContext context) { 042 return (new RangeForTranslator(expression, context).translate()); 043 } 044 045 public static boolean isApplicable(@NotNull JetForExpression expression, 046 @NotNull TranslationContext context) { 047 JetExpression loopRange = getLoopRange(expression); 048 JetType rangeType = BindingUtils.getTypeForExpression(context.bindingContext(), loopRange); 049 //TODO: better check 050 //TODO: long range? 051 return getClassDescriptorForType(rangeType).getName().asString().equals("IntRange"); 052 } 053 054 @NotNull 055 private final TemporaryVariable rangeExpression; 056 @NotNull 057 private final TemporaryVariable start; 058 @NotNull 059 private final TemporaryVariable end; 060 @NotNull 061 private final TemporaryVariable increment; 062 063 private RangeForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) { 064 super(forExpression, context); 065 rangeExpression = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context)); 066 start = context().declareTemporary(callFunction("get_start")); 067 end = context().declareTemporary(callFunction("get_end")); 068 increment = context().declareTemporary(callFunction("get_increment")); 069 } 070 071 @NotNull 072 private JsBlock translate() { 073 List<JsStatement> blockStatements = Lists.newArrayList(); 074 blockStatements.add(temporariesInitialization(rangeExpression, start, end, increment).makeStmt()); 075 blockStatements.add(generateForExpression()); 076 return new JsBlock(blockStatements); 077 } 078 079 @NotNull 080 private JsFor generateForExpression() { 081 JsFor result = new JsFor(initExpression(), getCondition(), getIncrExpression()); 082 result.setBody(translateOriginalBodyExpression()); 083 return result; 084 } 085 086 @NotNull 087 private JsVars initExpression() { 088 return newVar(parameterName, start.reference()); 089 } 090 091 @NotNull 092 private JsExpression getCondition() { 093 return lessThanEq(parameterName.makeRef(), end.reference()); 094 } 095 096 @NotNull 097 private JsExpression getIncrExpression() { 098 return addAssign(parameterName.makeRef(), increment.reference()); 099 } 100 101 @NotNull 102 private JsExpression callFunction(@NotNull String funName) { 103 return new JsInvocation(new JsNameRef(funName, rangeExpression.reference())); 104 } 105}