package slangc.model.statements; 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.LocalVariableSlot; import slangc.model.MemberModel; import slangc.model.Named; import slangc.model.StatementModel; import slangc.model.StatementOwner; import slangc.model.TypeModel; import slangc.model.clauses.Expressions; import slangc.model.clauses.ExpressionsOrVariables; import slangc.model.clauses.Variables; import slangc.parser.Branch; import slangc.parser.Node; public class ForStatement extends StatementModel implements StatementOwner, ExpressionOwner { private ExpressionsOrVariables initials; private Expressions conditions; // Note: should probably contain exactly 0 or 1 expressions! private Expressions increments; private StatementModel innerStatement; public ForStatement(StatementOwner owner, Branch source) { super(owner, source); initials = (ExpressionsOrVariables) ClauseModel.construct(this, (Branch) source.getSubnode(2)); conditions = (Expressions) ClauseModel.construct(this, (Branch) source.getSubnode(4)); increments = (Expressions) ClauseModel.construct(this, (Branch) source.getSubnode(6)); innerStatement = StatementModel.construct(this, source.getSubnode(8)); } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> For:"); initials.dump(reporter, indent + incr, incr); conditions.dump(reporter, indent + incr, incr); increments.dump(reporter, indent + incr, incr); innerStatement.dump(reporter, indent + incr, incr); } @Override public int resolveExpressions() { return initials.resolveExpressions() + conditions.resolveExpressions() + increments.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; } @Override public Named lookupSimpleName(String name) { if (initials instanceof Variables) { Variables vars = (Variables) initials; if (vars.hasVariable(name)) { return vars.getVariable(name); } } return super.lookupSimpleName(name); } public MethodModel[] lookupSimpleMethod(String name) { // TODO: Better interface support return super.lookupSimpleMethod(name); } @Override public void innerGenerate(BytecodeInstructionWriter w) { BytecodeInstructionWriter.Label beginLabel = w.newLabel("for_begin"); BytecodeInstructionWriter.Label endLabel = w.newLabel("for_end"); w.pushContinue(beginLabel); w.pushBreak(endLabel); if (initials instanceof Expressions) { for (int i = 0; i < ((Expressions)initials).countExpressions(); i++) { TypeSignature cr = ((Expressions)initials).getExpression(i).generate(w); if (!cr.mappableEquals(TypeSignature.VOID)) { w.genDrop(cr); } } } else { for (int i = 0; i < ((Variables)initials).countVariables(); i++) { LocalVariableSlot s = ((Variables)initials).getVariable(i); w.genDeclareLocal(s.getStorageType().getTypeSignature(), s.getIndex()); } for (int i = 0; i < ((Variables)initials).countVariables(); i++) { LocalVariableSlot s = ((Variables)initials).getVariable(i); if (s.hasInitialiser()) { s.getInitialiser().generate(w); w.genStoreLocalOrParam(s.getStorageType().getTypeSignature(), s.getIndex()); } } } w.labelHere(beginLabel); if (conditions.countExpressions() != 0) { TypeSignature xt = conditions.getExpression(0).generate(w); w.genJump(BytecodeInstructionWriter.JumpOp.IFFALSE, endLabel); } getInnerStatement().generate(w); for (int i = 0; i < increments.countExpressions(); i++) { TypeSignature cr = increments.getExpression(i).generate(w); if (!cr.mappableEquals(TypeSignature.VOID)) { w.genDrop(cr); } } w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, beginLabel); w.labelHere(endLabel); w.popBreak(endLabel); w.popContinue(beginLabel); } public StatementModel getInnerStatement() { return innerStatement; } }