Mercurial > projects > ddmd
diff dmd/TryCatchStatement.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | cab4c37afb89 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TryCatchStatement.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,201 @@ +module dmd.TryCatchStatement; + +import dmd.Statement; +import dmd.Array; +import dmd.Loc; +import dmd.Id; +import dmd.Identifier; +import dmd.Scope; +import dmd.InlineScanState; +import dmd.IRState; +import dmd.OutBuffer; +import dmd.Catch; +import dmd.HdrGenState; +import dmd.BE; + +import dmd.backend.BC; +import dmd.codegen.Util; +import dmd.backend.Util; +import dmd.backend.Blockx; +import dmd.backend.block; +import dmd.backend.mTY; +import dmd.backend.TYM; + +class TryCatchStatement : Statement +{ + Statement body_; + Array catches; + + this(Loc loc, Statement body_, Array catches) + { + super(loc); + this.body_ = body_; + this.catches = catches; + } + + Statement syntaxCopy() + { + assert(false); + } + + Statement semantic(Scope sc) + { + body_ = body_.semanticScope(sc, null /*this*/, null); + + /* Even if body is null, still do semantic analysis on catches + */ + for (size_t i = 0; i < catches.dim; i++) + { + Catch c = cast(Catch)catches.data[i]; + c.semantic(sc); + + // Determine if current catch 'hides' any previous catches + for (size_t j = 0; j < i; j++) + { + Catch cj = cast(Catch)catches.data[j]; + string si = c.loc.toChars(); + string sj = cj.loc.toChars(); + + if (c.type.toBasetype().implicitConvTo(cj.type.toBasetype())) + error("catch at %s hides catch at %s", sj, si); + } + } + + if (!body_ || body_.isEmpty()) + { + return null; + } + return this; + } + + bool hasBreak() + { + assert(false); + } + + bool usesEH() + { + assert(false); + } + + BE blockExit() + { + assert(body_); + BE result = body_.blockExit(); + + BE catchresult = BE.BEnone; + for (size_t i = 0; i < catches.dim; i++) + { + Catch c = cast(Catch)catches.data[i]; + catchresult |= c.blockExit(); + + /* If we're catching Object, then there is no throwing + */ + Identifier id = c.type.toBasetype().isClassHandle().ident; + if (i == 0 && + (id is Id.Object_ || id is Id.Throwable || id is Id.Exception)) + { + result &= ~BE.BEthrow; + } + } + return result | catchresult; + } + + Statement inlineScan(InlineScanState* iss) + { + if (body_) + body_ = body_.inlineScan(iss); + if (catches) + { + for (int i = 0; i < catches.dim; i++) + { + Catch c = cast(Catch)catches.data[i]; + + if (c.handler) + c.handler = c.handler.inlineScan(iss); + } + } + return this; + } + + /*************************************** + * Builds the following: + * _try + * block + * jcatch + * handler + * A try-catch statement. + */ + void toIR(IRState *irs) + { + Blockx *blx = irs.blx; + + version (SEH) { + nteh_declarvars(blx); + } + + IRState mystate = IRState(irs, this); + + block* tryblock = block_goto(blx,BCgoto,null); + + int previndex = blx.scope_index; + tryblock.Blast_index = previndex; + blx.scope_index = tryblock.Bscope_index = blx.next_index++; + + // Set the current scope index + setScopeIndex(blx,tryblock,tryblock.Bscope_index); + + // This is the catch variable + tryblock.jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr)); + + blx.tryblock = tryblock; + block *breakblock = block_calloc(blx); + block_goto(blx,BC_try,null); + if (body_) + { + body_.toIR(&mystate); + } + blx.tryblock = tryblock.Btry; + + // break block goes here + block_goto(blx, BCgoto, breakblock); + + setScopeIndex(blx,blx.curblock, previndex); + blx.scope_index = previndex; + + // create new break block that follows all the catches + breakblock = block_calloc(blx); + + list_append(&blx.curblock.Bsucc, breakblock); + block_next(blx,BCgoto,null); + + assert(catches); + for (int i = 0 ; i < catches.dim; i++) + { + Catch cs = cast(Catch)(catches.data[i]); + if (cs.var) + cs.var.csym = tryblock.jcatchvar; + block* bcatch = blx.curblock; + if (cs.type) + bcatch.Bcatchtype = cs.type.toBasetype().toSymbol(); + list_append(&tryblock.Bsucc,bcatch); + block_goto(blx,BCjcatch,null); + if (cs.handler !is null) + { + IRState catchState = IRState(irs, this); + cs.handler.toIR(&catchState); + } + list_append(&blx.curblock.Bsucc, breakblock); + block_next(blx, BCgoto, null); + } + + block_next(blx,cast(BC)blx.curblock.BC, breakblock); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + + TryCatchStatement isTryCatchStatement() { return this; } +} \ No newline at end of file