forConditions are conditions (bounds) for the iterator (from i 0 to 10 ).

Labeling rules with = is going to improve readability of the parser.

the iterator must be a name of the variable (the var may not exist in the scope. In this case the variable is declared behind the scenes)

The startExpression’s value is used for initializing the iterator.

The endExpressions’s value is the stop value for the iterator.

The result parse tree for the statement:
for (i from 0 to 5) print i
is:

Mapping antlr context objects

The antlr generates ForStatementContext class from the grammar specification.
It is good idea to map it into more compiler-friendly class.
While mapping why not solve the problem described in the previous section (undeclared iterator variable)?

publicclassForStatementVisitorextendsEnkelBaseVisitor<RangedForStatement>{//other stuff@OverridepublicRangedForStatementvisitForStatement(@NotNullForStatementContextctx){EnkelParser.ForConditionsContextforExpressionContext=ctx.forConditions();ExpressionstartExpression=forExpressionContext.startExpr.accept(expressionVisitor);ExpressionendExpression=forExpressionContext.endExpr.accept(expressionVisitor);VarReferenceContextiterator=forExpressionContext.iterator;StringvarName=iterator.getText();//If variable referenced by iterator already exists in the scopeif(scope.localVariableExists(varName)){//register new variable valueStatementiteratorVariable=newAssignmentStatement(varName,startExpression);//get the statement (usually block))Statementstatement=ctx.statement().accept(statementVisitor);returnnewRangedForStatement(iteratorVariable,startExpression,endExpression,statement,varName,scope);//Variable has not been declared in the scope}else{//create new local variable and add to the scopescope.addLocalVariable(newLocalVariable(varName,startExpression.getType()));//register variable declaration statementStatementiteratorVariable=newVariableDeclarationStatement(varName,startExpression);Statementstatement=ctx.statement().accept(statementVisitor);returnnewRangedForStatement(iteratorVariable,startExpression,endExpression,statement,varName,scope);}}}

The iterator variable may or may not exist in the scope.
Both statements below should be handled:

variterator=0for(iteratorfrom0to5)printiterator

Iterator was already declared. Assign it to the the startExpression (value 0) : new AssignmentStatement(varName, startExpression);.

for(iteratorfrom0to5)printiterator

Iterator is not yet declared. Declare and assign it to the startExpression (value 0) : new VariableDeclarationStatement(varName,startExpression);.

Generating bytecode

Once the RangedForStatement has been created it is time to pull some information
from it and generate bytecode.

publicvoidgenerate(RangedForStatementrangedForStatement){ScopenewScope=rangedForStatement.getScope();StatementGeneratorscopeGeneratorWithNewScope=newStatementGenerator(methodVisitor,newScope);ExpressionGenratorexprGeneratorWithNewScope=newExpressionGenrator(methodVisitor,newScope);Statementiterator=rangedForStatement.getIteratorVariableStatement();LabelincrementationSection=newLabel();LabeldecrementationSection=newLabel();LabelendLoopSection=newLabel();StringiteratorVarName=rangedForStatement.getIteratorVarName();ExpressionendExpression=rangedForStatement.getEndExpression();ExpressioniteratorVariable=newVarReference(iteratorVarName,rangedForStatement.getType());ConditionalExpressioniteratorGreaterThanEndConditional=newConditionalExpression(iteratorVariable,endExpression,CompareSign.GREATER);ConditionalExpressioniteratorLessThanEndConditional=newConditionalExpression(iteratorVariable,endExpression,CompareSign.LESS);//generates varaible declaration or variable reference (istore)iterator.accept(scopeGeneratorWithNewScope);//Section below checks whether the loop should be iterating or decrementing//If the range start is smaller than range end (i from 0 to 5) then iterate (++)//If the range start is greater than range end (i from 5 to 0) then decrement (--)//Pushes 0 or 1 onto the stack iteratorLessThanEndConditional.accept(exprGeneratorWithNewScope);//IFNE - is value on the stack (result of conditional) different than 0 (success)?methodVisitor.visitJumpInsn(Opcodes.IFNE,incrementationSection);iteratorGreaterThanEndConditional.accept(exprGeneratorWithNewScope);methodVisitor.visitJumpInsn(Opcodes.IFNE,decrementationSection);//Incrementation sectionmethodVisitor.visitLabel(incrementationSection);rangedForStatement.getStatement().accept(scopeGeneratorWithNewScope);//execute the bodymethodVisitor.visitIincInsn(newScope.getLocalVariableIndex(iteratorVarName),1);//increment iteratoriteratorGreaterThanEndConditional.accept(exprGeneratorWithNewScope);//is iterator greater than range end?methodVisitor.visitJumpInsn(Opcodes.IFEQ,incrementationSection);//if it is not go back loop again //the iterator is greater than end range. Break out of the loop, skipping decrementation sectionmethodVisitor.visitJumpInsn(Opcodes.GOTO,endLoopSection);//Decrementation sectionmethodVisitor.visitLabel(decrementationSection);rangedForStatement.getStatement().accept(scopeGeneratorWithNewScope);methodVisitor.visitIincInsn(newScope.getLocalVariableIndex(iteratorVarName),-1);//decrement iteratoriteratorLessThanEndConditional.accept(exprGeneratorWithNewScope);methodVisitor.visitJumpInsn(Opcodes.IFEQ,decrementationSection);methodVisitor.visitLabel(endLoopSection);}

This may seem a little bit complicated because the decision whether the loop
should be incremented or decremented needs to be taken at runtime.

Let’s analyze how the method actually choose the right iteration type in this example for (i from 0 to 5):

Declare iterator varaible i and assign start value (0).

Check if iterator value (0) is less than end range value (5)

Because the 0 (range start) is less than 5 (range end) the iterator should be incremented. Jump to incrementation section.

Execute the actual statements in the loop.

increment iterator by 1

Check if iterator is greater than range end (5).

If it is not then go back to the point 4.

Once the loop has been executed 5 times (the iterator is 6) go to end section (skip decrementation section)

Example

Let’s compile the following Enkel class:

Loops{main(string[]args){forifrom1to5{printi}}}

To better present how the iteration type is inferred I decompiled
the Enkel.class file using Intellij Idea’s decompiler:

//Enkel.class file decompiled to Java using Intellij Idea's decompilerpublicclassLoops{publicstaticvoidmain(String[]var0){intvar1=1;if(var1>=5){//should it be decremented?do{System.out.println(var1);--var1;}while(var1>=5);}else{//should it be incremented?do{System.out.println(var1);++var1;}while(var1<=5);}}}