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