package slangc.model.statements; import java.util.ArrayList; import slangc.api.BytecodeInstructionWriter; import slangc.api.Reporter; import slangc.bytecode.TypeSignature; import slangc.model.ClauseModel; import slangc.model.ExpressionModel; import slangc.model.ExpressionOwner; import slangc.model.InnerTypeScope; import slangc.model.MemberModel; import slangc.model.StatementModel; import slangc.model.StatementOwner; import slangc.model.TypeModel; import slangc.model.clauses.SwitchMembers; import slangc.model.expressions.BinaryExpression; import slangc.parser.Branch; import slangc.parser.Node; public class SwitchStatement extends StatementModel implements StatementOwner, ExpressionOwner { private ExpressionModel condition; private SwitchMembers innerStatement; public SwitchStatement(StatementOwner owner, Branch source) { super(owner, source); condition = ExpressionModel.construct(this, source.getSubnode(1)); innerStatement = (SwitchMembers) ClauseModel.construct(this, source.getSubnode(3)); } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> Switch:"); condition.dump(reporter, indent + incr, incr); innerStatement.dump(reporter, indent + incr, incr); } @Override public int resolveExpressions() { return condition.resolveExpressions() + innerStatement.resolveExpressions(); } //@Override public TypeModel resolveType(Node subnode) { return getOwner().resolveType(subnode); } //@Override public MemberModel getMethodOrField() { return getOwner().getMethodOrField(); } //@Override public InnerTypeScope getTypeScope() { return getOwner().getTypeScope(); } //@Override public TypeModel getExpectedResult(ExpressionModel e) { // TODO Auto-generated method stub return null; } public int countCaseLabels() { int nlabels = 0; for (int i = 0; i < innerStatement.countMembers(); i++) { StatementModel s = innerStatement.getMember(i); if (s instanceof CaseLabelStatement) { nlabels++; } } return nlabels; } public CaseLabelStatement[] findCaseLabels() { CaseLabelStatement[] labels = new CaseLabelStatement[countCaseLabels()]; int labelIndex = 0; for (int i = 0; i < innerStatement.countMembers(); i++) { StatementModel s = innerStatement.getMember(i); if (s instanceof CaseLabelStatement) { labels[labelIndex] = (CaseLabelStatement)s; labelIndex++; } } return labels; } public DefaultLabelStatement findDefaultLabel() { for (int i = 0; i < innerStatement.countMembers(); i++) { StatementModel s = innerStatement.getMember(i); if (s instanceof DefaultLabelStatement) { return (DefaultLabelStatement) s; } } return null; } @Override public void innerGenerate(BytecodeInstructionWriter w) { BytecodeInstructionWriter.Label defaultLabelA = w.newLabel("switch_defaultA"); BytecodeInstructionWriter.Label defaultLabelB = w.newLabel("switch_defaultB"); BytecodeInstructionWriter.Label endLabel = w.newLabel("switch_end"); BytecodeInstructionWriter.Label[] caseLabelsA = new BytecodeInstructionWriter.Label[countCaseLabels()]; BytecodeInstructionWriter.Label[] caseLabelsB = new BytecodeInstructionWriter.Label[countCaseLabels()]; for (int i = 0; i < caseLabelsA.length; i++) { caseLabelsA[i] = w.newLabel("switch_casea"); caseLabelsB[i] = w.newLabel("switch_caseb"); } CaseLabelStatement[] caseLabelStatemtents = findCaseLabels(); DefaultLabelStatement defaultLabelStatement = findDefaultLabel(); w.pushBreak(endLabel); TypeSignature xt = condition.generate(w); TypeModel xtm = condition.getResult().getValueType(); for (int i = 0; i < caseLabelStatemtents.length; i++) { w.genDup(xt); CaseLabelStatement l = caseLabelStatemtents[i]; TypeSignature cxt = l.getExpression().generate(w); BinaryExpression.generateALUOp(w, xtm, "==", l.getExpression().getResult().getValueType()); w.genJump(BytecodeInstructionWriter.JumpOp.IFTRUE, caseLabelsA[i]); } //w.genDrop(xt); w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, defaultLabelA); int currentLabelIndex = 0; for (int i = 0; i < innerStatement.countMembers(); i++) { StatementModel s = innerStatement.getMember(i); if (s instanceof CaseLabelStatement) { w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, caseLabelsB[currentLabelIndex]); w.labelHere(caseLabelsA[currentLabelIndex]); w.genDrop(xt); w.labelHere(caseLabelsB[currentLabelIndex]); currentLabelIndex++; } else if (s instanceof DefaultLabelStatement) { w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, defaultLabelB); w.labelHere(defaultLabelA); w.genDrop(xt); w.labelHere(defaultLabelB); } else { s.generate(w); } } if (defaultLabelStatement == null) { w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, defaultLabelB); w.labelHere(defaultLabelA); w.genDrop(xt); w.labelHere(defaultLabelB); } w.popBreak(endLabel); w.labelHere(endLabel); } /* public MethodModel[] lookupSimpleMethod(String name) { // TODO: Better interface support return super.lookupSimpleMethod(name); } public slangc.model.Named lookupSimpleName(String name) { // TODO: Better interface support return super.lookupSimpleName(name); }*/ }