diff dmd/GotoStatement.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/GotoStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,133 @@
+module dmd.GotoStatement;
+
+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;
+
+class GotoStatement : Statement
+{
+    Identifier ident;
+    LabelDsymbol label = null;
+    TryFinallyStatement tf = null;
+
+    this(Loc loc, Identifier ident)
+	{
+		super(loc);
+		this.ident = ident;
+	}
+	
+    Statement syntaxCopy()
+	{
+		GotoStatement s = new GotoStatement(loc, ident);
+		return s;
+	}
+	
+    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.
+			 */
+			Statements a = new Statements();
+			Statement s;
+
+			a.push(cast(void*)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;
+	}
+
+    BE blockExit()
+	{
+		//printf("GotoStatement.blockExit(%p)\n", this);
+		return BE.BEgoto;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    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);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("goto ");
+		buf.writestring(ident.toChars());
+		buf.writebyte(';');
+		buf.writenl();
+	}
+	
+    GotoStatement isGotoStatement() { return this; }
+}
\ No newline at end of file