package org.develnext.jphp.core.compiler.jvm.statement.expr; import org.develnext.jphp.core.compiler.jvm.misc.LocalVariable; import org.develnext.jphp.core.compiler.jvm.statement.ExpressionStmtCompiler; import org.develnext.jphp.core.tokenizer.token.stmt.BodyStmtToken; import org.develnext.jphp.core.tokenizer.token.stmt.CaseStmtToken; import org.develnext.jphp.core.tokenizer.token.stmt.SwitchStmtToken; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.LineNumberNode; import php.runtime.Memory; import static org.objectweb.asm.Opcodes.GOTO; import static org.objectweb.asm.Opcodes.IFEQ; public class SwitchCompiler extends BaseStatementCompiler<SwitchStmtToken> { public SwitchCompiler(ExpressionStmtCompiler exprCompiler) { super(exprCompiler); } @Override public void write(SwitchStmtToken token) { expr.writeDefineVariables(token.getLocal()); LabelNode l = new LabelNode(); LabelNode end = new LabelNode(); add(l); LocalVariable switchValue = method.addLocalVariable( "~switch~" + method.nextStatementIndex(Memory.class), l, Memory.class ); switchValue.setEndLabel(end); LabelNode[][] jumps = new LabelNode[token.getCases().size() + 1][2]; int i = 0; for(CaseStmtToken one : token.getCases()) { jumps[i] = new LabelNode[]{ new LabelNode(), new LabelNode() }; // checkLabel, bodyLabel if (i == jumps.length - 1) jumps[i] = new LabelNode[]{ end, end }; i++; } jumps[jumps.length - 1] = new LabelNode[]{end, end}; method.pushJump(end, end); expr.writeExpression(token.getValue(), true, false); expr.writePopBoxing(); expr.writeVarStore(switchValue, false, false); i = 0; for(CaseStmtToken one : token.getCases()){ add(jumps[i][0]); // conditional if (one.getConditional() != null){ expr.writeVarLoad(switchValue); expr.writeExpression(one.getConditional(), true, false); expr.writeSysDynamicCall(Memory.class, "equal", Boolean.TYPE, expr.stackPeek().type.toClass()); add(new JumpInsnNode(IFEQ, jumps[i + 1][0])); expr.stackPop(); } add(new JumpInsnNode(GOTO, jumps[i][1])); // if is done... i++; } i = 0; for(CaseStmtToken one : token.getCases()){ add(jumps[i][1]); expr.writeDefineVariables(one.getLocals()); expr.write(BodyStmtToken.class, one.getBody()); i++; expr.writeUndefineVariables(one.getLocals()); } method.popJump(); add(end); add(new LineNumberNode(token.getMeta().getEndLine(), end)); method.prevStatementIndex(Memory.class); expr.writeUndefineVariables(token.getLocal()); } }