JS backend: refactor LoopTranslator, add function translateForExpression

This commit is contained in:
Michael Nedzelsky
2014-08-22 20:11:03 +04:00
parent 478d3baf59
commit 40e5d6c8f5
2 changed files with 160 additions and 303 deletions
@@ -32,7 +32,6 @@ import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.declaration.ClassTranslator; import org.jetbrains.k2js.translate.declaration.ClassTranslator;
import org.jetbrains.k2js.translate.expression.loopTranslator.ForTranslator;
import org.jetbrains.k2js.translate.expression.loopTranslator.LoopTranslatorPackage; import org.jetbrains.k2js.translate.expression.loopTranslator.LoopTranslatorPackage;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.general.TranslatorVisitor; import org.jetbrains.k2js.translate.general.TranslatorVisitor;
@@ -428,7 +427,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull @NotNull
public JsNode visitForExpression(@NotNull JetForExpression expression, public JsNode visitForExpression(@NotNull JetForExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return ForTranslator.OBJECT$.translate(expression, context).source(expression); return LoopTranslatorPackage.translateForExpression(expression, context).source(expression);
} }
@Override @Override
@@ -16,357 +16,215 @@
package org.jetbrains.k2js.translate.expression.loopTranslator package org.jetbrains.k2js.translate.expression.loopTranslator
import org.jetbrains.jet.lang.psi.JetWhileExpressionBase import com.google.dart.compiler.backend.js.ast.*
import org.jetbrains.k2js.translate.context.TranslationContext
import com.google.dart.compiler.backend.js.ast.JsNode
import com.google.dart.compiler.backend.js.ast.JsBlock
import org.jetbrains.k2js.translate.general.Translation
import com.google.dart.compiler.backend.js.ast.JsIf
import org.jetbrains.k2js.translate.utils.JsAstUtils
import com.google.dart.compiler.backend.js.ast.JsLiteral
import com.google.dart.compiler.backend.js.ast.JsBreak
import com.google.dart.compiler.backend.js.ast.JsDoWhile
import com.google.dart.compiler.backend.js.ast.JsWhile
import com.google.dart.compiler.backend.js.ast.JsStatement
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.psi.JetForExpression
import com.google.dart.compiler.backend.js.ast.JsExpression
import org.jetbrains.k2js.translate.context.TemporaryVariable
import org.jetbrains.jet.lang.psi.JetBinaryExpression
import org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody
import org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter
import org.jetbrains.k2js.translate.utils.PsiUtils.getLoopRange
import org.jetbrains.k2js.translate.utils.TranslationUtils
import com.google.dart.compiler.backend.js.ast.JsFor
import com.google.dart.compiler.backend.js.ast.JsVars
import org.jetbrains.jet.lexer.JetTokens
import com.google.dart.compiler.backend.js.ast.JsUnaryOperator
import com.google.dart.compiler.backend.js.ast.JsPostfixOperation
import org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization
import com.google.dart.compiler.backend.js.ast.JsNameRef
import org.jetbrains.k2js.translate.utils.BindingUtils.*
import org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType
import org.jetbrains.k2js.translate.intrinsic.functions.factories.CompositeFIF
import com.google.dart.compiler.backend.js.ast.JsArrayAccess
import com.google.dart.compiler.backend.js.ast.JsPrefixOperation
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.k2js.translate.callTranslator.CallTranslator import org.jetbrains.k2js.translate.callTranslator.CallTranslator
import org.jetbrains.k2js.translate.general.AbstractTranslator import org.jetbrains.k2js.translate.context.TemporaryVariable
import com.google.dart.compiler.backend.js.ast.JsName import org.jetbrains.k2js.translate.context.TranslationContext
import org.jetbrains.jet.lang.psi.JetMultiDeclaration
import org.jetbrains.k2js.translate.expression.MultiDeclarationTranslator import org.jetbrains.k2js.translate.expression.MultiDeclarationTranslator
import org.jetbrains.k2js.translate.general.AbstractTranslator
import org.jetbrains.k2js.translate.general.Translation
import org.jetbrains.k2js.translate.intrinsic.functions.factories.CompositeFIF
import org.jetbrains.k2js.translate.utils.BindingUtils.*
import org.jetbrains.k2js.translate.utils.JsAstUtils.*
import org.jetbrains.k2js.translate.utils.PsiUtils.*
import org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization
import org.jetbrains.k2js.translate.utils.TranslationUtils
public fun createWhile(doWhile: Boolean, expression: JetWhileExpressionBase, context: TranslationContext): JsNode { public fun createWhile(doWhile: Boolean, expression: JetWhileExpressionBase, context: TranslationContext): JsNode {
val conditionExpression = expression.getCondition() ?: val conditionExpression = expression.getCondition() ?:
throw IllegalArgumentException("condition expression should not be null: ${expression.getText()}") throw IllegalArgumentException("condition expression should not be null: ${expression.getText()}")
val conditionBlock = JsBlock() val conditionBlock = JsBlock()
var jsCondition = Translation.translateAsExpression(conditionExpression, context, conditionBlock) var jsCondition = Translation.translateAsExpression(conditionExpression, context, conditionBlock)
var bodyStatement = translateNullableExpressionAsNotNullStatement(expression.getBody(), context) val body = expression.getBody()
var bodyStatement =
if (body != null)
Translation.translateAsStatement(body, context)
else
context.program().getEmptyStatement()
if (!conditionBlock.isEmpty()) { if (!conditionBlock.isEmpty()) {
val IfStatement = JsIf(JsAstUtils.not(jsCondition), JsBreak()) val breakIfConditionIsFalseStatement = JsIf(not(jsCondition), JsBreak())
val bodyBlock = JsAstUtils.convertToBlock(bodyStatement) val bodyBlock = convertToBlock(bodyStatement)
jsCondition = JsLiteral.TRUE jsCondition = JsLiteral.TRUE
if (doWhile) { if (doWhile) {
// translate to: tmpSecondRun = false; do { if(tmpSecondRun) { <expr> if(!tmpExprVar) break; } else tmpSecondRun=true; <body> } while(true) // translate to: tmpSecondRun = false; do { if(tmpSecondRun) { <expr> if(!tmpExprVar) break; } else tmpSecondRun=true; <body> } while(true)
val secondRun = context.declareTemporary(JsLiteral.FALSE) val secondRun = context.declareTemporary(JsLiteral.FALSE)
context.addStatementToCurrentBlock(secondRun.assignmentExpression().makeStmt()) context.addStatementToCurrentBlock(secondRun.assignmentExpression().makeStmt())
conditionBlock.getStatements().add(IfStatement) conditionBlock.getStatements().add(breakIfConditionIsFalseStatement)
bodyBlock.getStatements().add(0, JsIf(secondRun.reference(), val ifStatement = JsIf(secondRun.reference(), conditionBlock, assignment(secondRun.reference(), JsLiteral.TRUE).makeStmt())
conditionBlock, bodyBlock.getStatements().add(0, ifStatement)
JsAstUtils.assignment(secondRun.reference(), JsLiteral.TRUE).makeStmt()))
} }
else { else {
// translate to: while (true) { <expr> if(!tmpExprVar) break; <body> } // translate to: while (true) { <expr> if(!tmpExprVar) break; <body> }
conditionBlock.getStatements().add(IfStatement) conditionBlock.getStatements().add(breakIfConditionIsFalseStatement)
bodyBlock.getStatements().addAll(0, conditionBlock.getStatements()) bodyBlock.getStatements().addAll(0, conditionBlock.getStatements())
} }
bodyStatement = bodyBlock bodyStatement = bodyBlock
} }
val result = if (doWhile) JsDoWhile() else JsWhile() val result = if (doWhile) JsDoWhile() else JsWhile()
result.setCondition(jsCondition) result.setCondition(jsCondition)
result.setBody(bodyStatement) result.setBody(bodyStatement)
return result.source(expression)!! return result.source(expression)!!
} }
private fun translateNullableExpressionAsNotNullStatement(nullableExpression: JetExpression?, context: TranslationContext): JsStatement = public fun translateForExpression(expression: JetForExpression, context: TranslationContext): JsStatement {
if (nullableExpression == null) val loopRange = getLoopRange(expression)
context.program().getEmptyStatement() val rangeType = getTypeForExpression(context.bindingContext(), loopRange)
else
Translation.translateAsStatement(nullableExpression, context)
fun isForOverRange(): Boolean {
// TODO: implement reverse semantics //TODO: better check
public class RangeLiteralForTranslator private(forExpression: JetForExpression, context: TranslationContext) : ForTranslator(forExpression, context) { //TODO: long range?
return getClassDescriptorForType(rangeType).getName().asString() == "IntRange"
private val rangeStart: JsExpression
private val rangeEnd: TemporaryVariable
{
val loopRange = getLoopRange(expression)
assert(loopRange is JetBinaryExpression)
val loopRangeAsBinary = (loopRange as JetBinaryExpression)
val startBlock = JsBlock()
var rangeStartExpression = TranslationUtils.translateLeftExpression(context, loopRangeAsBinary, startBlock)
val endBlock = JsBlock()
val rightExpression = TranslationUtils.translateRightExpression(context(), loopRangeAsBinary, endBlock)
if (TranslationUtils.isCacheNeeded(rangeStartExpression)) {
val startVar = context.declareTemporary(rangeStartExpression)
rangeStartExpression = startVar.reference()
context.addStatementToCurrentBlock(startVar.assignmentExpression().makeStmt())
}
rangeStart = rangeStartExpression
context.addStatementsToCurrentBlockFrom(startBlock)
context.addStatementsToCurrentBlockFrom(endBlock)
rangeEnd = context.declareTemporary(rightExpression)
} }
private fun translate(): JsStatement { fun isForOverRangeLiteral(): Boolean =
context().addStatementToCurrentBlock(temporariesInitialization(rangeEnd).makeStmt()) loopRange is JetBinaryExpression && loopRange.getOperationToken() == JetTokens.RANGE && isForOverRange()
return JsFor(initExpression(), getCondition(), getIncrExpression(), translateBody(null))
fun isForOverArray(): Boolean {
//TODO: better check
//TODO: IMPORTANT!
return getClassDescriptorForType(rangeType).getName().asString() == "Array" ||
getClassDescriptorForType(rangeType).getName().asString() == "IntArray"
} }
private fun initExpression(): JsVars { val multiParameter: JetMultiDeclaration? = expression.getMultiParameter();
return JsAstUtils.newVar(parameterName, rangeStart)
}
private fun getCondition(): JsExpression { fun declareParameter(): JsName {
return JsAstUtils.lessThanEq(parameterName.makeRef(), rangeEnd.reference())
}
private fun getIncrExpression(): JsExpression {
return JsPostfixOperation(JsUnaryOperator.INC, parameterName.makeRef())
}
class object {
public fun doTranslate(expression: JetForExpression, context: TranslationContext): JsStatement {
return (RangeLiteralForTranslator(expression, context).translate())
}
public fun isApplicable(expression: JetForExpression, context: TranslationContext): Boolean {
val loopRange = getLoopRange(expression)
if (loopRange !is JetBinaryExpression) {
return false
}
val isRangeToOperation = (loopRange as JetBinaryExpression).getOperationToken() == JetTokens.RANGE
return isRangeToOperation && RangeForTranslator.isApplicable(expression, context)
}
}
}
public class RangeForTranslator private(forExpression: JetForExpression, context: TranslationContext) : ForTranslator(forExpression, context) {
private val rangeExpression: TemporaryVariable
private val start: TemporaryVariable
private val end: TemporaryVariable
private val increment: TemporaryVariable
{
rangeExpression = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context))
start = context().declareTemporary(getProperty("start"))
end = context().declareTemporary(getProperty("end"))
increment = context().declareTemporary(getProperty("increment"))
}
private fun translate(): JsStatement {
context().addStatementToCurrentBlock(temporariesInitialization(rangeExpression, start, end, increment).makeStmt())
return generateForExpression()
}
private fun generateForExpression(): JsFor {
val result = JsFor(initExpression(), getCondition(), getIncrExpression())
result.setBody(translateBody(null))
return result
}
private fun initExpression(): JsVars {
return JsAstUtils.newVar(parameterName, start.reference())
}
private fun getCondition(): JsExpression {
return JsAstUtils.lessThanEq(parameterName.makeRef(), end.reference())
}
private fun getIncrExpression(): JsExpression {
return JsAstUtils.addAssign(parameterName.makeRef(), increment.reference())
}
private fun getProperty(funName: String): JsExpression {
return JsNameRef(funName, rangeExpression.reference())
}
class object {
public fun doTranslate(expression: JetForExpression, context: TranslationContext): JsStatement {
return (RangeForTranslator(expression, context).translate())
}
public fun isApplicable(expression: JetForExpression, context: TranslationContext): Boolean {
val loopRange = getLoopRange(expression)
val rangeType = getTypeForExpression(context.bindingContext(), loopRange)
//TODO: better check
//TODO: long range?
return getClassDescriptorForType(rangeType).getName().asString() == "IntRange"
}
}
}
public class ArrayForTranslator private(forExpression: JetForExpression, context: TranslationContext) : ForTranslator(forExpression, context) {
private val loopRange: TemporaryVariable
private val end: TemporaryVariable
private val index: TemporaryVariable
{
loopRange = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context))
val length = CompositeFIF.LENGTH_PROPERTY_INTRINSIC.apply(loopRange.reference(), listOf<JsExpression>(), context())
end = context().declareTemporary(length)
index = context().declareTemporary(program().getNumberLiteral(0))
}
private fun translate(): JsStatement {
context().addStatementToCurrentBlock(temporariesInitialization(loopRange, end).makeStmt())
return JsFor(getInitExpression(), getCondition(), getIncrementExpression(), getBody())
}
private fun getBody(): JsStatement {
val arrayAccess = JsArrayAccess(loopRange.reference(), index.reference())
return translateBody(arrayAccess)
}
private fun getInitExpression(): JsVars {
return JsAstUtils.newVar(index.name(), program().getNumberLiteral(0))
}
private fun getCondition(): JsExpression {
return JsAstUtils.inequality(index.reference(), end.reference())
}
private fun getIncrementExpression(): JsExpression {
return JsPrefixOperation(JsUnaryOperator.INC, index.reference())
}
class object {
public fun doTranslate(expression: JetForExpression, context: TranslationContext): JsStatement {
return (ArrayForTranslator(expression, context).translate())
}
public fun isApplicable(expression: JetForExpression, context: TranslationContext): Boolean {
val loopRange = getLoopRange(expression)
val rangeType = getTypeForExpression(context.bindingContext(), loopRange)
//TODO: better check
//TODO: IMPORTANT!
return getClassDescriptorForType(rangeType).getName().asString() == "Array" || getClassDescriptorForType(rangeType).getName().asString() == "IntArray"
}
}
}
public class IteratorForTranslator private(forExpression: JetForExpression, context: TranslationContext) : ForTranslator(forExpression, context) {
private val iteratorVar: TemporaryVariable
{
iteratorVar = context.declareTemporary(iteratorMethodInvocation())
}
private fun translate(): JsStatement {
context().addStatementToCurrentBlock(iteratorVar.assignmentExpression().makeStmt())
return JsWhile(hasNextMethodInvocation(), translateBody(nextMethodInvocation()))
}
private fun nextMethodInvocation(): JsExpression {
return translateMethodInvocation(iteratorVar.reference(), getNextFunction(bindingContext(), getLoopRange(expression)))
}
private fun hasNextMethodInvocation(): JsExpression {
val resolvedCall = getHasNextCallable(bindingContext(), getLoopRange(expression))
return translateMethodInvocation(iteratorVar.reference(), resolvedCall)
}
private fun iteratorMethodInvocation(): JsExpression {
val rangeExpression = getLoopRange(expression)
val range = Translation.translateAsExpression(rangeExpression, context())
val resolvedCall = getIteratorFunction(bindingContext(), rangeExpression)
return translateMethodInvocation(range, resolvedCall)
}
private fun translateMethodInvocation(receiver: JsExpression?, resolvedCall: ResolvedCall<FunctionDescriptor>): JsExpression {
return CallTranslator.translate(context(), resolvedCall, receiver)
}
class object {
public fun doTranslate(expression: JetForExpression, context: TranslationContext): JsStatement {
return (IteratorForTranslator(expression, context).translate())
}
}
}
public abstract class ForTranslator protected(protected val expression: JetForExpression, context: TranslationContext) : AbstractTranslator(context) {
protected val parameterName: JsName
protected val multiParameter: JetMultiDeclaration?
{
this.multiParameter = expression.getMultiParameter()
this.parameterName = declareParameter()
}
private fun declareParameter(): JsName {
val loopParameter = getLoopParameter(expression) val loopParameter = getLoopParameter(expression)
if (loopParameter != null) { if (loopParameter != null) {
return context().getNameForElement(loopParameter) return context.getNameForElement(loopParameter)
} }
assert(parameterIsMultiDeclaration(), "If loopParameter is null, multi parameter must be not null") assert(multiParameter != null, "If loopParameter is null, multi parameter must be not null ${expression.getText()}")
return context().scope().declareTemporary() return context.scope().declareTemporary()
} }
private fun parameterIsMultiDeclaration(): Boolean { val parameterName: JsName = declareParameter()
return multiParameter != null
}
private fun makeCurrentVarInit(itemValue: JsExpression?): JsStatement { fun translateBody(itemValue: JsExpression?): JsStatement {
if (multiParameter == null) { val realBody = Translation.translateAsStatement(getLoopBody(expression), context)
return JsAstUtils.newVar(parameterName, itemValue) if (itemValue == null && multiParameter == null) {
}
else {
return MultiDeclarationTranslator.translate(multiParameter!!, parameterName, itemValue, context())
}
}
protected fun translateBody(itemValue: JsExpression?): JsStatement {
val realBody = Translation.translateAsStatement(getLoopBody(expression), context())
if (itemValue == null && !parameterIsMultiDeclaration()) {
return realBody return realBody
} }
else { else {
val currentVarInit = makeCurrentVarInit(itemValue) val currentVarInit =
val block = JsAstUtils.convertToBlock(realBody) if (multiParameter == null)
newVar(parameterName, itemValue)
else
MultiDeclarationTranslator.translate(multiParameter, parameterName, itemValue, context)
val block = convertToBlock(realBody)
block.getStatements().add(0, currentVarInit) block.getStatements().add(0, currentVarInit)
return block return block
} }
} }
class object { // TODO: implement reverse semantics
fun translateForOverLiteralRange(): JsStatement {
if (loopRange !is JetBinaryExpression) throw IllegalStateException("expected JetBinaryExpression, but ${loopRange.getText()}")
public fun translate(expression: JetForExpression, context: TranslationContext): JsStatement { val startBlock = JsBlock()
if (RangeLiteralForTranslator.isApplicable(expression, context)) { val leftExpression = TranslationUtils.translateLeftExpression(context, loopRange, startBlock)
return RangeLiteralForTranslator.doTranslate(expression, context) val endBlock = JsBlock()
val rightExpression = TranslationUtils.translateRightExpression(context, loopRange, endBlock)
val rangeStart =
if (TranslationUtils.isCacheNeeded(leftExpression)) {
val startVar = context.declareTemporary(leftExpression)
context.addStatementToCurrentBlock(startVar.assignmentExpression().makeStmt())
startVar.reference()
} }
if (RangeForTranslator.isApplicable(expression, context)) { else {
return RangeForTranslator.doTranslate(expression, context) leftExpression
} }
if (ArrayForTranslator.isApplicable(expression, context)) { context.addStatementsToCurrentBlockFrom(startBlock)
return ArrayForTranslator.doTranslate(expression, context) context.addStatementsToCurrentBlockFrom(endBlock)
} val rangeEnd = context.declareTemporary(rightExpression)
return IteratorForTranslator.doTranslate(expression, context)
} val body = translateBody(null)
val initExpression = newVar(parameterName, rangeStart)
val conditionExpression = lessThanEq(parameterName.makeRef(), rangeEnd.reference())
val incrementExpression = JsPostfixOperation(JsUnaryOperator.INC, parameterName.makeRef())
context.addStatementToCurrentBlock(temporariesInitialization(rangeEnd).makeStmt())
return JsFor(initExpression, conditionExpression, incrementExpression, body)
} }
}
fun translateForOverRange(): JsStatement {
val rangeExpression = context.declareTemporary(Translation.translateAsExpression(loopRange, context))
fun getProperty(funName: String): JsExpression = JsNameRef(funName, rangeExpression.reference())
val start = context.declareTemporary(getProperty("start"))
val end = context.declareTemporary(getProperty("end"))
val increment = context.declareTemporary(getProperty("increment"))
val body = translateBody(null)
val initExpression = newVar(parameterName, start.reference())
val conditionExpression = lessThanEq(parameterName.makeRef(), end.reference())
val incrementExpression = addAssign(parameterName.makeRef(), increment.reference())
context.addStatementToCurrentBlock(temporariesInitialization(rangeExpression, start, end, increment).makeStmt())
return JsFor(initExpression, conditionExpression, incrementExpression, body)
}
fun translateForOverArray(): JsStatement {
val rangeExpression = context.declareTemporary(Translation.translateAsExpression(loopRange, context))
val length = CompositeFIF.LENGTH_PROPERTY_INTRINSIC.apply(rangeExpression.reference(), listOf<JsExpression>(), context)
val end = context.declareTemporary(length)
val index = context.declareTemporary(context.program().getNumberLiteral(0))
val arrayAccess = JsArrayAccess(rangeExpression.reference(), index.reference())
val body = translateBody(arrayAccess)
val initExpression = newVar(index.name(), context.program().getNumberLiteral(0))
val conditionExpression = inequality(index.reference(), end.reference())
val incrementExpression = JsPrefixOperation(JsUnaryOperator.INC, index.reference())
context.addStatementToCurrentBlock(temporariesInitialization(rangeExpression, end).makeStmt())
return JsFor(initExpression, conditionExpression, incrementExpression, body)
}
fun translateForOverIterator(): JsStatement {
fun translateMethodInvocation(receiver: JsExpression?, resolvedCall: ResolvedCall<FunctionDescriptor>): JsExpression =
CallTranslator.translate(context, resolvedCall, receiver)
fun iteratorMethodInvocation(): JsExpression {
val range = Translation.translateAsExpression(loopRange, context)
val resolvedCall = getIteratorFunction(context.bindingContext(), loopRange)
return translateMethodInvocation(range, resolvedCall)
}
val iteratorVar: TemporaryVariable = context.declareTemporary(iteratorMethodInvocation())
fun nextMethodInvocation(): JsExpression =
translateMethodInvocation(iteratorVar.reference(), getNextFunction(context.bindingContext(), loopRange))
fun hasNextMethodInvocation(): JsExpression {
val resolvedCall = getHasNextCallable(context.bindingContext(), loopRange)
return translateMethodInvocation(iteratorVar.reference(), resolvedCall)
}
context.addStatementToCurrentBlock(iteratorVar.assignmentExpression().makeStmt())
return JsWhile(hasNextMethodInvocation(), translateBody(nextMethodInvocation()))
}
return when {
isForOverRangeLiteral() ->
translateForOverLiteralRange()
isForOverRange() ->
translateForOverRange()
isForOverArray() ->
translateForOverArray()
else ->
translateForOverIterator()
}
}