Mercurial > projects > ddmd
view dmd/ForStatement.d @ 94:3a0b150c9841
Objects -> Vector!Object iteration 1
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 30 Aug 2010 23:00:34 +0100 |
parents | 43073c7c7769 |
children | e28b18c23469 |
line wrap: on
line source
module dmd.ForStatement; import dmd.Statement; import dmd.Expression; import dmd.Loc; import dmd.Scope; import dmd.InterState; import dmd.OutBuffer; import dmd.HdrGenState; import dmd.InlineScanState; import dmd.WANT; import dmd.ScopeDsymbol; import dmd.IRState; import dmd.BE; import dmd.backend.Blockx; import dmd.backend.block; import dmd.backend.Util; import dmd.backend.BC; class ForStatement : Statement { Statement init; Expression condition; Expression increment; Statement body_; this(Loc loc, Statement init, Expression condition, Expression increment, Statement body_) { super(loc); this.init = init; this.condition = condition; this.increment = increment; this.body_ = body_; } override Statement syntaxCopy() { Statement i = null; if (init) i = init.syntaxCopy(); Expression c = null; if (condition) c = condition.syntaxCopy(); Expression inc = null; if (increment) inc = increment.syntaxCopy(); ForStatement s = new ForStatement(loc, i, c, inc, body_.syntaxCopy()); return s; } override Statement semantic(Scope sc) { ScopeDsymbol sym = new ScopeDsymbol(); sym.parent = sc.scopesym; sc = sc.push(sym); if (init) init = init.semantic(sc); sc.noctor++; if (condition) { condition = condition.semantic(sc); condition = resolveProperties(sc, condition); condition = condition.optimize(WANTvalue); condition = condition.checkToBoolean(); } if (increment) { increment = increment.semantic(sc); increment = resolveProperties(sc, increment); increment = increment.optimize(0); } sc.sbreak = this; sc.scontinue = this; if (body_) body_ = body_.semantic(sc); sc.noctor--; sc.pop(); return this; } override void scopeCode(Scope sc, Statement* sentry, Statement* sexception, Statement* sfinally) { //printf("ForStatement::scopeCode()\n"); //print(); if (init) init.scopeCode(sc, sentry, sexception, sfinally); else Statement.scopeCode(sc, sentry, sexception, sfinally); } override bool hasBreak() { //printf("ForStatement.hasBreak()\n"); return true; } override bool hasContinue() { return true; } override bool usesEH() { return (init && init.usesEH()) || body_.usesEH(); } override BE blockExit() { BE result = BE.BEfallthru; if (init) { result = init.blockExit(); if (!(result & BE.BEfallthru)) return result; } if (condition) { if (condition.canThrow()) result |= BE.BEthrow; if (condition.isBool(true)) result &= ~BE.BEfallthru; else if (condition.isBool(false)) return result; } else result &= ~BE.BEfallthru; // the body must do the exiting if (body_) { int r = body_.blockExit(); if (r & (BE.BEbreak | BE.BEgoto)) result |= BE.BEfallthru; result |= r & ~(BE.BEfallthru | BE.BEbreak | BE.BEcontinue); } if (increment && increment.canThrow()) result |= BE.BEthrow; return result; } override bool comeFrom() { //printf("ForStatement.comeFrom()\n"); if (body_) { bool result = body_.comeFrom(); //printf("result = %d\n", result); return result; } return false; } override Expression interpret(InterState istate) { assert(false); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring("for ("); if (init) { hgs.FLinit.init++; init.toCBuffer(buf, hgs); hgs.FLinit.init--; } else buf.writebyte(';'); if (condition) { buf.writebyte(' '); condition.toCBuffer(buf, hgs); } buf.writebyte(';'); if (increment) { buf.writebyte(' '); increment.toCBuffer(buf, hgs); } buf.writebyte(')'); buf.writenl(); buf.writebyte('{'); buf.writenl(); body_.toCBuffer(buf, hgs); buf.writebyte('}'); buf.writenl(); } override Statement inlineScan(InlineScanState* iss) { if (init) init = init.inlineScan(iss); if (condition) condition = condition.inlineScan(iss); if (increment) increment = increment.inlineScan(iss); if (body_) body_ = body_.inlineScan(iss); return this; } override void toIR(IRState* irs) { Blockx* blx = irs.blx; IRState mystate = IRState(irs,this); mystate.breakBlock = block_calloc(blx); mystate.contBlock = block_calloc(blx); if (init) init.toIR(&mystate); block* bpre = blx.curblock; block_next(blx,BCgoto,null); block* bcond = blx.curblock; list_append(&bpre.Bsucc, bcond); list_append(&mystate.contBlock.Bsucc, bcond); if (condition) { incUsage(irs, condition.loc); block_appendexp(bcond, condition.toElem(&mystate)); block_next(blx,BCiftrue,null); list_append(&bcond.Bsucc, blx.curblock); list_append(&bcond.Bsucc, mystate.breakBlock); } else { /* No conditional, it's a straight goto */ block_next(blx,BCgoto,null); list_append(&bcond.Bsucc, blx.curblock); } if (body_) body_.toIR(&mystate); /* End of the body goes to the continue block */ list_append(&blx.curblock.Bsucc, mystate.contBlock); block_next(blx, BCgoto, mystate.contBlock); if (increment) { incUsage(irs, increment.loc); block_appendexp(mystate.contBlock, increment.toElem(&mystate)); } /* The 'break' block follows the for statement. */ block_next(blx,BCgoto, mystate.breakBlock); } }