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.Branch;
import me.august.lumen.compile.codegen.BuildContext;
import me.august.lumen.compile.codegen.Conditional;
import me.august.lumen.compile.codegen.MethodCodeGen;
import me.august.lumen.compile.parser.ast.CodeBlock;
import me.august.lumen.compile.parser.ast.expr.Expression;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.List;
public class IfStmt implements CodeBlock, VisitorConsumer {
private static Branch toBranch(Expression expr, MethodCodeGen ifBranch, MethodCodeGen elseBranch) {
if (expr instanceof Conditional) {
return ((Conditional) expr).branch(ifBranch, elseBranch);
} else if (expr.expressionType().getSort() == Type.BOOLEAN) {
return Branch.branchBoolean(expr, ifBranch, elseBranch);
} else {
throw new IllegalArgumentException("Incompatible types.");
}
}
private Expression condition;
private Body trueBody;
private List<ElseIf> elseIfs;
private Body elseBody;
public IfStmt(Expression condition, Body trueBody, List<ElseIf> elseIfs, Body elseBody) {
this.condition = condition;
this.trueBody = trueBody;
this.elseIfs = elseIfs;
this.elseBody = elseBody;
}
public IfStmt(Expression condition, Body trueBody) {
this(condition, trueBody, new ArrayList<>(), null);
}
@Override
public void generate(MethodVisitor visitor, BuildContext context) {
Branch branch = toBranch(condition, trueBody, elseBody);
if (elseIfs != null) {
for (ElseIf elseIf : elseIfs) {
branch.setElseBranch(
toBranch(elseIf.condition, elseIf.body, branch.getElseBranch())
);
}
}
branch.generate(visitor, context);
}
public Expression getCondition() {
return condition;
}
public Body getTrueBody() {
return trueBody;
}
public List<ElseIf> getElseIfs() {
return elseIfs;
}
public Body getElseBody() {
return elseBody;
}
@Override
public void accept(ASTVisitor visitor) {
condition.accept(visitor);
trueBody.accept(visitor);
for (ElseIf eif : elseIfs) {
eif.condition.accept(visitor);
eif.body.accept(visitor);
}
if (elseBody != null) elseBody.accept(visitor);
}
public static class ElseIf {
private Expression condition;
private Body body;
public ElseIf(Expression condition, Body body) {
this.condition = condition;
this.body = body;
}
@Override
public String toString() {
return "ElseIf{" +
"condition=" + condition +
", body=" + body +
'}';
}
}
@Override
public String toString() {
return "IfStatement{" +
"condition=" + condition +
", trueBody=" + trueBody +
", elseIfs=" + elseIfs +
", elseBody=" + elseBody +
'}';
}
}