Mercurial > projects > ddmd
view dmd/ForeachRangeStatement.d @ 32:81796b717a39
A few bad cast fixed. TODO: either get rid of dyncast(), or derive all objects from intermediate supertype.
author | korDen |
---|---|
date | Tue, 18 May 2010 17:51:46 +0400 |
parents | 10317f0c89a5 |
children | cab4c37afb89 |
line wrap: on
line source
module dmd.ForeachRangeStatement; import dmd.Statement; import dmd.TOK; import dmd.Argument; import dmd.Expression; import dmd.Statement; import dmd.VarDeclaration; import dmd.Scope; import dmd.ExpInitializer; import dmd.Identifier; import dmd.Lexer; import dmd.ArrayTypes; import dmd.DeclarationStatement; import dmd.CompoundDeclarationStatement; import dmd.DeclarationExp; import dmd.PostExp; import dmd.VarExp; import dmd.ForStatement; import dmd.IntegerExp; import dmd.AddAssignExp; import dmd.CmpExp; import dmd.IRState; import dmd.InterState; import dmd.OutBuffer; import dmd.AddExp; import dmd.WANT; import dmd.ScopeDsymbol; import dmd.HdrGenState; import dmd.InlineScanState; import dmd.Loc; import dmd.BE; class ForeachRangeStatement : Statement { TOK op; // TOK.TOKforeach or TOK.TOKforeach_reverse Argument arg; // loop index variable Expression lwr; Expression upr; Statement body_; VarDeclaration key = null; this(Loc loc, TOK op, Argument arg, Expression lwr, Expression upr, Statement body_) { super(loc); this.op = op; this.arg = arg; this.lwr = lwr; this.upr = upr; this.body_ = body_; } Statement syntaxCopy() { ForeachRangeStatement s = new ForeachRangeStatement(loc, op, arg.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy(), body_ ? body_.syntaxCopy() : null); return s; } Statement semantic(Scope sc) { //printf("ForeachRangeStatement.semantic() %p\n", this); ScopeDsymbol sym; Statement s = this; lwr = lwr.semantic(sc); lwr = resolveProperties(sc, lwr); lwr = lwr.optimize(WANTvalue); if (!lwr.type) { error("invalid range lower bound %s", lwr.toChars()); return this; } upr = upr.semantic(sc); upr = resolveProperties(sc, upr); upr = upr.optimize(WANTvalue); if (!upr.type) { error("invalid range upper bound %s", upr.toChars()); return this; } if (arg.type) { arg.type = arg.type.semantic(loc, sc); lwr = lwr.implicitCastTo(sc, arg.type); upr = upr.implicitCastTo(sc, arg.type); } else { /* Must infer types from lwr and upr */ scope AddExp ea = new AddExp(loc, lwr, upr); ea.typeCombine(sc); arg.type = ea.type.mutableOf(); lwr = ea.e1; upr = ea.e2; } static if (true) { /* Convert to a for loop: * foreach (key; lwr .. upr) => * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) * * foreach_reverse (key; lwr .. upr) => * for (auto tmp = lwr, auto key = upr; key-- > tmp;) */ ExpInitializer ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); key = new VarDeclaration(loc, arg.type, arg.ident, ie); Identifier id = Lexer.uniqueId("__limit"); ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); VarDeclaration tmp = new VarDeclaration(loc, arg.type, id, ie); Statements cs = new Statements(); // Keep order of evaluation as lwr, then upr if (op == TOKforeach) { cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); } else { cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); } Statement forinit = new CompoundDeclarationStatement(loc, cs); Expression cond; if (op == TOKforeach_reverse) { // key-- > tmp cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); } else // key < tmp cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); Expression increment = null; if (op == TOKforeach) // key += 1 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); ForStatement fs = new ForStatement(loc, forinit, cond, increment, body_); s = fs.semantic(sc); return s; } else { if (!arg.type.isscalar()) error("%s is not a scalar type", arg.type.toChars()); sym = new ScopeDsymbol(); sym.parent = sc.scopesym; sc = sc.push(sym); sc.noctor++; key = new VarDeclaration(loc, arg.type, arg.ident, null); DeclarationExp de = new DeclarationExp(loc, key); de.semantic(sc); if (key.storage_class) error("foreach range: key cannot have storage class"); sc.sbreak = this; sc.scontinue = this; body_ = body_.semantic(sc); sc.noctor--; sc.pop(); return s; } } bool hasBreak() { assert(false); } bool hasContinue() { assert(false); } bool usesEH() { assert(false); } BE blockExit() { assert(false); } bool comeFrom() { assert(false); } Expression interpret(InterState* istate) { assert(false); } void toCBuffer(OutBuffer buf, HdrGenState* hgs) { assert(false); } Statement inlineScan(InlineScanState* iss) { assert(false); } void toIR(IRState* irs) { assert(false); } }