package me.tomassetti.bytecode_generation; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import java.util.Collections; import java.util.List; public class IfBS extends BytecodeSequence { private BytecodeSequence pushIfCondition; private BytecodeSequence ifBody; private BytecodeSequence elseBody; // they just push the values private List<BytecodeSequence> elifConditions; private List<BytecodeSequence> elifBodys; public IfBS(BytecodeSequence pushIfCondition, BytecodeSequence ifBody) { this(pushIfCondition, ifBody, null); } public IfBS(BytecodeSequence pushIfCondition, BytecodeSequence ifBody, BytecodeSequence elseBody) { this(pushIfCondition, ifBody, Collections.emptyList(), Collections.emptyList(), elseBody); } public IfBS(BytecodeSequence pushIfCondition, BytecodeSequence ifBody, List<BytecodeSequence> elifConditions, List<BytecodeSequence> elifBodys, BytecodeSequence elseBody) { if (elifConditions.size() != elifBodys.size()) { throw new IllegalArgumentException(); } this.pushIfCondition = pushIfCondition; this.ifBody = ifBody; this.elseBody = elseBody; this.elifConditions = elifConditions; this.elifBodys = elifBodys; } public IfBS(BytecodeSequence pushIfCondition, BytecodeSequence ifBody, List<BytecodeSequence> elifConditions, List<BytecodeSequence> elifBodys) { if (elifConditions.size() != elifBodys.size()) { throw new IllegalArgumentException(); } this.pushIfCondition = pushIfCondition; this.ifBody = ifBody; this.elifConditions = elifConditions; this.elifBodys = elifBodys; } @Override public void operate(MethodVisitor mv) { pushIfCondition.operate(mv); Label end = new Label(); // if equal to zero (if false) jump away Label ifFailed = new Label(); mv.visitJumpInsn(Opcodes.IFEQ, ifFailed); // if branch ifBody.operate(mv); mv.visitJumpInsn(Opcodes.GOTO, end); // then branch mv.visitLabel(ifFailed); for (int i=0; i<elifConditions.size();i++){ Label thisElifSkipped = new Label(); elifConditions.get(i).operate(mv); mv.visitJumpInsn(Opcodes.IFEQ, thisElifSkipped); // enter the elig elifBodys.get(i).operate(mv); mv.visitJumpInsn(Opcodes.GOTO, end); mv.visitLabel(thisElifSkipped); } // else branch if (elseBody != null) { elseBody.operate(mv); } // enf of the statement mv.visitLabel(end); } }