package me.august.lumen.compile.parser.ast.stmt;
import me.august.lumen.compile.analyze.ASTVisitor;
import me.august.lumen.compile.analyze.VisitorConsumer;
import me.august.lumen.compile.codegen.BuildContext;
import me.august.lumen.compile.parser.ast.CodeBlock;
import me.august.lumen.compile.parser.ast.expr.RangeExpr;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class ForStmt implements CodeBlock, VisitorConsumer, Loop {
private String ident;
private RangeExpr range;
private Body body;
private Label repeat;
private Label exit;
private int counterIndex;
private int boundIndex;
public ForStmt(String ident, RangeExpr range, Body body) {
this.ident = ident;
this.range = range;
this.body = body;
}
@Override
public Label getRepeatLabel() {
return repeat;
}
@Override
public Label getExitLabel() {
return exit;
}
public String getIdent() {
return ident;
}
public void setCounterIndex(int counterIndex) {
this.counterIndex = counterIndex;
}
public void setBoundIndex(int boundIndex) {
this.boundIndex = boundIndex;
}
@Override
public void generate(MethodVisitor visitor, BuildContext context) {
repeat = new Label();
exit = new Label();
range.getLeft().generate(visitor, context);
visitor.visitVarInsn(Opcodes.ISTORE, counterIndex);
range.getRight().generate(visitor, context);
visitor.visitVarInsn(Opcodes.ISTORE, boundIndex);
visitor.visitLabel(repeat);
visitor.visitVarInsn(Opcodes.ILOAD, counterIndex);
visitor.visitVarInsn(Opcodes.ILOAD, boundIndex);
int opcode = range.isExclusive() ? Opcodes.IF_ICMPGE
: Opcodes.IF_ICMPGT;
visitor.visitJumpInsn(opcode, exit);
body.generate(visitor, context);
visitor.visitIincInsn(counterIndex, 1);
visitor.visitJumpInsn(Opcodes.GOTO, repeat);
visitor.visitLabel(exit);
}
@Override
public void accept(ASTVisitor visitor) {
range.getLeft().accept(visitor);
range.getRight().accept(visitor);
visitor.visitForStmt(this);
body.accept(visitor);
}
}