diff dmd/CaseStatement.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children a8b50ff7f201
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CaseStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,177 @@
+module dmd.CaseStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Statement;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.InlineScanState;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+import dmd.InterState;
+import dmd.BE;
+import dmd.SwitchStatement;
+import dmd.WANT;
+import dmd.TOK;
+import dmd.VarExp;
+import dmd.VarDeclaration;
+import dmd.Type;
+import dmd.TY;
+import dmd.IntegerExp;
+import dmd.GotoCaseStatement;
+
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.backend.BC;
+
+class CaseStatement : Statement
+{
+    Expression exp;
+    Statement statement;
+
+    int index = 0;			// which case it is (since we sort this)
+    block* cblock = null;	// back end: label for the block
+
+    this(Loc loc, Expression exp, Statement s)
+	{
+		super(loc);
+		
+		this.exp = exp;
+		this.statement = s;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		SwitchStatement sw = sc.sw;
+
+		//printf("CaseStatement.semantic() %s\n", toChars());
+		exp = exp.semantic(sc);
+		if (sw)
+		{
+			exp = exp.implicitCastTo(sc, sw.condition.type);
+			exp = exp.optimize(WANTvalue | WANTinterpret);
+
+			/* This is where variables are allowed as case expressions.
+			 */
+			if (exp.op == TOKvar)
+			{   VarExp ve = cast(VarExp)exp;
+				VarDeclaration v = ve.var.isVarDeclaration();
+				Type t = exp.type.toBasetype();
+				if (v && (t.isintegral() || t.ty == Tclass))
+				{
+					/* Flag that we need to do special code generation
+					 * for this, i.e. generate a sequence of if-then-else
+					 */
+					sw.hasVars = 1;
+					if (sw.isFinal)
+						error("case variables not allowed in final switch statements");
+					goto L1;
+				}
+			}
+
+			if (exp.op != TOKstring && exp.op != TOKint64)
+			{
+				error("case must be a string or an integral constant, not %s", exp.toChars());
+				exp = new IntegerExp(0);
+			}
+
+			L1:
+			for (int i = 0; i < sw.cases.dim; i++)
+			{
+				CaseStatement cs = cast(CaseStatement)sw.cases.data[i];
+
+				//printf("comparing '%s' with '%s'\n", exp.toChars(), cs.exp.toChars());
+				if (cs.exp.equals(exp))
+				{	
+					error("duplicate case %s in switch statement", exp.toChars());
+					break;
+				}
+			}
+
+			sw.cases.push(cast(void*)this);
+
+			// Resolve any goto case's with no exp to this case statement
+			for (int i = 0; i < sw.gotoCases.dim; i++)
+			{
+				GotoCaseStatement gcs = cast(GotoCaseStatement)sw.gotoCases.data[i];
+
+				if (!gcs.exp)
+				{
+					gcs.cs = this;
+					sw.gotoCases.remove(i);	// remove from array
+				}
+			}
+
+			if (sc.sw.tf !is sc.tf)
+				error("switch and case are in different finally blocks");
+		}
+		else
+			error("case not in switch statement");
+		statement = statement.semantic(sc);
+		return this;
+	}
+	
+    int compare(Object obj)
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		return statement.blockExit();
+	}
+	
+    bool comeFrom()
+	{
+		return true;
+	}
+	
+    Expression interpret(InterState *istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		//printf("CaseStatement.inlineScan()\n");
+		exp = exp.inlineScan(iss);
+		if (statement)
+			statement = statement.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState *irs)
+	{
+		Blockx* blx = irs.blx;
+		block* bcase = blx.curblock;
+		if (!cblock)
+			cblock = block_calloc(blx);
+		block_next(blx,BCgoto,cblock);
+		block* bsw = irs.getSwitchBlock();
+		if (bsw.BC == BCswitch)
+			list_append(&bsw.Bsucc,cblock);	// second entry in pair
+		list_append(&bcase.Bsucc,cblock);
+		if (blx.tryblock != bsw.Btry)
+			error("case cannot be in different try block level from switch");
+		incUsage(irs, loc);
+		if (statement)
+			statement.toIR(irs);
+	}
+}
\ No newline at end of file