Mercurial > projects > ddmd
view dmd/GotoStatement.d @ 187:b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
author | Abscissa |
---|---|
date | Tue, 07 Jun 2011 23:37:34 -0400 |
parents | e3afd1303184 |
children |
line wrap: on
line source
module dmd.GotoStatement; import dmd.common; import dmd.Loc; import dmd.Scope; import dmd.Statement; import dmd.Identifier; import dmd.CompoundStatement; import dmd.LabelDsymbol; import dmd.TryFinallyStatement; import dmd.FuncDeclaration; import dmd.OutBuffer; import dmd.HdrGenState; import dmd.Expression; import dmd.InterState; import dmd.IRState; import dmd.ArrayTypes; import dmd.BE; import dmd.codegen.Util; import dmd.backend.Util; import dmd.backend.block; import dmd.backend.Blockx; import dmd.backend.BC; import dmd.DDMDExtensions; class GotoStatement : Statement { mixin insertMemberExtension!(typeof(this)); Identifier ident; LabelDsymbol label = null; TryFinallyStatement tf = null; this(Loc loc, Identifier ident) { register(); super(loc); this.ident = ident; } override Statement syntaxCopy() { GotoStatement s = new GotoStatement(loc, ident); return s; } override Statement semantic(Scope sc) { FuncDeclaration fd = sc.parent.isFuncDeclaration(); //printf("GotoStatement.semantic()\n"); tf = sc.tf; label = fd.searchLabel(ident); if (!label.statement && sc.fes) { /* Either the goto label is forward referenced or it * is in the function that the enclosing foreach is in. * Can't know yet, so wrap the goto in a compound statement * so we can patch it later, and add it to a 'look at this later' * list. */ auto a = new Statements(); Statement s; a.push(this); s = new CompoundStatement(loc, a); sc.fes.gotos.push(cast(void*)s); // 'look at this later' list return s; } if (label.statement && label.statement.tf != sc.tf) error("cannot goto in or out of finally block"); return this; } override BE blockExit() { //printf("GotoStatement.blockExit(%p)\n", this); return BE.BEgoto; } override Expression interpret(InterState istate) { assert(false); } override void toIR(IRState* irs) { block* b; block* bdest; Blockx* blx = irs.blx; if (!label.statement) { error("label %s is undefined", label.toChars()); return; } if (tf !is label.statement.tf) error("cannot goto forward out of or into finally block"); bdest = labelToBlock(loc, blx, label); if (!bdest) return; b = blx.curblock; incUsage(irs, loc); // Adjust exception handler scope index if in different try blocks if (b.Btry != bdest.Btry) { // Check that bdest is in an enclosing try block for (block* bt = b.Btry; bt != bdest.Btry; bt = bt.Btry) { if (!bt) { //printf("b.Btry = %p, bdest.Btry = %p\n", b.Btry, bdest.Btry); error("cannot goto into try block"); break; } } //setScopeIndex(blx, b, bdest.Btry ? bdest.Btry.Bscope_index : -1); } list_append(&b.Bsucc,bdest); block_next(blx,BCgoto,null); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring("goto "); buf.writestring(ident.toChars()); buf.writebyte(';'); buf.writenl(); } override GotoStatement isGotoStatement() { return this; } }