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.intrinsic.functions.factories.ArrayFIF; 029import org.jetbrains.k2js.translate.utils.BindingUtils; 030 031import java.util.Collections; 032import java.util.List; 033 034import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType; 035import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; 036import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; 037import static org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization; 038 039public final class ArrayForTranslator extends ForTranslator { 040 041 @NotNull 042 public static JsStatement doTranslate(@NotNull JetForExpression expression, 043 @NotNull TranslationContext context) { 044 return (new ArrayForTranslator(expression, context).translate()); 045 } 046 047 public static boolean isApplicable(@NotNull JetForExpression expression, 048 @NotNull TranslationContext context) { 049 JetExpression loopRange = getLoopRange(expression); 050 JetType rangeType = BindingUtils.getTypeForExpression(context.bindingContext(), loopRange); 051 //TODO: better check 052 //TODO: IMPORTANT! 053 return getClassDescriptorForType(rangeType).getName().asString().equals("Array") 054 || getClassDescriptorForType(rangeType).getName().asString().equals("IntArray"); 055 } 056 057 @NotNull 058 private final TemporaryVariable loopRange; 059 060 @NotNull 061 private final TemporaryVariable end; 062 063 @NotNull 064 private final TemporaryVariable index; 065 066 private ArrayForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) { 067 super(forExpression, context); 068 loopRange = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context)); 069 070 JsExpression length = ArrayFIF.ARRAY_LENGTH_INTRINSIC.apply(loopRange.reference(), 071 Collections.<JsExpression>emptyList(), 072 context()); 073 end = context().declareTemporary(length); 074 index = context().declareTemporary(program().getNumberLiteral(0)); 075 } 076 077 @NotNull 078 private JsBlock translate() { 079 List<JsStatement> blockStatements = Lists.newArrayList(); 080 blockStatements.add(temporariesInitialization(loopRange, end).makeStmt()); 081 blockStatements.add(generateForExpression(getInitExpression(), getCondition(), getIncrementExpression(), getBody())); 082 return new JsBlock(blockStatements); 083 } 084 085 086 @NotNull 087 private JsStatement getBody() { 088 JsArrayAccess arrayAccess = new JsArrayAccess(loopRange.reference(), index.reference()); 089 JsStatement currentVar = newVar(parameterName, arrayAccess); 090 JsStatement realBody = translateOriginalBodyExpression(); 091 return new JsBlock(currentVar, realBody); 092 } 093 094 @NotNull 095 private JsVars getInitExpression() { 096 return newVar(index.name(), program().getNumberLiteral(0)); 097 } 098 099 @NotNull 100 private JsExpression getCondition() { 101 return inequality(index.reference(), end.reference()); 102 } 103 104 @NotNull 105 private JsExpression getIncrementExpression() { 106 return new JsPrefixOperation(JsUnaryOperator.INC, index.reference()); 107 } 108}