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.dart.compiler.backend.js.ast.*; 020import com.intellij.openapi.util.Pair; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.annotations.Nullable; 023import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; 024import org.jetbrains.jet.lang.psi.JetExpression; 025import org.jetbrains.jet.lang.psi.JetForExpression; 026import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 027import org.jetbrains.k2js.translate.context.TranslationContext; 028import org.jetbrains.k2js.translate.general.Translation; 029import org.jetbrains.k2js.translate.reference.CallBuilder; 030 031import static org.jetbrains.k2js.translate.utils.BindingUtils.*; 032import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange; 033 034public final class IteratorForTranslator extends ForTranslator { 035 @NotNull 036 private final Pair<JsVars.JsVar, JsExpression> iterator; 037 038 @NotNull 039 public static JsStatement doTranslate(@NotNull JetForExpression expression, 040 @NotNull TranslationContext context) { 041 return (new IteratorForTranslator(expression, context).translate()); 042 } 043 044 private IteratorForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) { 045 super(forExpression, context); 046 iterator = context.dynamicContext().createTemporary(iteratorMethodInvocation()); 047 } 048 049 @NotNull 050 private JsBlock translate() { 051 return new JsBlock(new JsVars(iterator.first), new JsWhile(hasNextMethodInvocation(), translateBody(nextMethodInvocation()))); 052 } 053 054 @NotNull 055 private JsExpression nextMethodInvocation() { 056 return translateMethodInvocation(iterator.second, getNextFunction(bindingContext(), getLoopRange(expression))); 057 } 058 059 @NotNull 060 private JsExpression hasNextMethodInvocation() { 061 ResolvedCall<FunctionDescriptor> resolvedCall = getHasNextCallable(bindingContext(), getLoopRange(expression)); 062 return translateMethodInvocation(iterator.second, resolvedCall); 063 } 064 065 @NotNull 066 private JsExpression iteratorMethodInvocation() { 067 JetExpression rangeExpression = getLoopRange(expression); 068 JsExpression range = Translation.translateAsExpression(rangeExpression, context()); 069 ResolvedCall<FunctionDescriptor> resolvedCall = getIteratorFunction(bindingContext(), rangeExpression); 070 return translateMethodInvocation(range, resolvedCall); 071 } 072 073 @NotNull 074 private JsExpression translateMethodInvocation(@Nullable JsExpression receiver, 075 @NotNull ResolvedCall<FunctionDescriptor> resolvedCall) { 076 return CallBuilder.build(context()) 077 .resolvedCall(resolvedCall) 078 .receiver(receiver) 079 .translate(); 080 } 081}