diff dmd/statement.c @ 846:bc982f1ad106

Merged DMD 1.037 frontend
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 13 Dec 2008 13:15:31 +0100
parents 661384d6a936
children 330f999ade44
line wrap: on
line diff
--- a/dmd/statement.c	Sat Dec 13 06:48:00 2008 +0100
+++ b/dmd/statement.c	Sat Dec 13 13:15:31 2008 +0100
@@ -26,6 +26,7 @@
 #include "id.h"
 #include "hdrgen.h"
 #include "parse.h"
+#include "template.h"
 
 /******************************** Statement ***************************/
 
@@ -451,10 +452,7 @@
 			body = new CompoundStatement(0, a);
 			body = new ScopeStatement(0, body);
 
-			static int num;
-			char name[3 + sizeof(num) * 3 + 1];
-			sprintf(name, "__o%d", ++num);
-			Identifier *id = Lexer::idPool(name);
+			Identifier *id = Lexer::uniqueId("__o");
 
 			Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
 			handler = new CompoundStatement(0, sexception, handler);
@@ -1107,12 +1105,17 @@
 	// Use a default value
 	condition = new IntegerExp(loc, 1, Type::tboolean);
     sc->noctor++;
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->optimize(WANTvalue);
-    condition = condition->checkToBoolean();
+    if (condition)
+    {
+	condition = condition->semantic(sc);
+	condition = resolveProperties(sc, condition);
+	condition = condition->optimize(WANTvalue);
+	condition = condition->checkToBoolean();
+    }
     if (increment)
-	increment = increment->semantic(sc);
+    {	increment = increment->semantic(sc);
+	increment = resolveProperties(sc, increment);
+    }
 
     sc->sbreak = this;
     sc->scontinue = this;
@@ -1257,8 +1260,7 @@
     //printf("ForeachStatement::semantic() %p\n", this);
     ScopeDsymbol *sym;
     Statement *s = this;
-    int dim = arguments->dim;
-    int i;
+    size_t dim = arguments->dim;
     TypeAArray *taa = NULL;
 
     Type *tn = NULL;
@@ -1272,6 +1274,7 @@
 
     aggr = aggr->semantic(sc);
     aggr = resolveProperties(sc, aggr);
+    aggr = aggr->optimize(WANTvalue);
     if (!aggr->type)
     {
 	error("invalid foreach aggregate %s", aggr->toChars());
@@ -1387,7 +1390,7 @@
 	return s;
     }
 
-    for (i = 0; i < dim; i++)
+    for (size_t i = 0; i < dim; i++)
     {	Argument *arg = (Argument *)arguments->data[i];
 	if (!arg->type)
 	{
@@ -1419,7 +1422,7 @@
 	    if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
 	    {	Argument *arg;
 
-		i = (dim == 1) ? 0 : 1;	// index of value
+		int i = (dim == 1) ? 0 : 1;	// index of value
 		arg = (Argument *)arguments->data[i];
 		arg->type = arg->type->semantic(loc, sc);
 		tnv = arg->type->toBasetype();
@@ -1437,7 +1440,7 @@
 		}
 	    }
 
-	    for (i = 0; i < dim; i++)
+	    for (size_t i = 0; i < dim; i++)
 	    {	// Declare args
 		Argument *arg = (Argument *)arguments->data[i];
 		VarDeclaration *var;
@@ -1468,7 +1471,8 @@
 		if (aggr->op == TOKstring)
 		    aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
 		else
-		    error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
+		    error("foreach: %s is not an array of %s",
+			tab->toChars(), value->type->toChars());
 	    }
 
         if (key)
@@ -1505,6 +1509,72 @@
 
 	case Tclass:
 	case Tstruct:
+#if DMDV2
+	{   /* Look for range iteration, i.e. the properties
+	     * .empty, .next, .retreat, .head and .rear
+	     *    foreach (e; range) { ... }
+	     * translates to:
+	     *    for (auto __r = range; !__r.empty; __r.next)
+	     *    {   auto e = __r.head;
+	     *        ...
+	     *    }
+	     */
+	    if (dim != 1)	// only one argument allowed with ranges
+		goto Lapply;
+	    AggregateDeclaration *ad = (tab->ty == Tclass)
+			? (AggregateDeclaration *)((TypeClass  *)tab)->sym
+			: (AggregateDeclaration *)((TypeStruct *)tab)->sym;
+	    Identifier *idhead;
+	    Identifier *idnext;
+	    if (op == TOKforeach)
+	    {	idhead = Id::Fhead;
+		idnext = Id::Fnext;
+	    }
+	    else
+	    {	idhead = Id::Frear;
+		idnext = Id::Fretreat;
+	    }
+	    Dsymbol *shead = search_function(ad, idhead);
+	    if (!shead)
+		goto Lapply;
+
+	    /* Generate a temporary __r and initialize it with the aggregate.
+	     */
+	    Identifier *id = Identifier::generateId("__r");
+	    VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr));
+	    r->semantic(sc);
+	    Statement *init = new DeclarationStatement(loc, r);
+
+	    // !__r.empty
+	    Expression *e = new VarExp(loc, r);
+	    e = new DotIdExp(loc, e, Id::Fempty);
+	    Expression *condition = new NotExp(loc, e);
+
+	    // __r.next
+	    e = new VarExp(loc, r);
+	    Expression *increment = new DotIdExp(loc, e, idnext);
+
+	    /* Declaration statement for e:
+	     *    auto e = __r.idhead;
+	     */
+	    e = new VarExp(loc, r);
+	    Expression *einit = new DotIdExp(loc, e, idhead);
+	    einit = einit->semantic(sc);
+	    Argument *arg = (Argument *)arguments->data[0];
+	    VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
+	    ve->storage_class |= STCforeach;
+	    ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
+
+	    DeclarationExp *de = new DeclarationExp(loc, ve);
+
+	    Statement *body = new CompoundStatement(loc,
+		new DeclarationStatement(loc, de), this->body);
+
+	    s = new ForStatement(loc, init, condition, increment, body);
+	    s = s->semantic(sc);
+	    break;
+	}
+#endif
 	case Tdelegate:
 	Lapply:
 	{   FuncDeclaration *fdapply;
@@ -1540,7 +1610,7 @@
 	     *	int delegate(ref T arg) { body }
 	     */
 	    args = new Arguments();
-	    for (i = 0; i < dim; i++)
+	    for (size_t i = 0; i < dim; i++)
 	    {	Argument *arg = (Argument *)arguments->data[i];
 
 		arg->type = arg->type->semantic(loc, sc);
@@ -1551,10 +1621,8 @@
 		    // a reference.
 		    VarDeclaration *v;
 		    Initializer *ie;
-		    char applyArg[10 + sizeof(i)*3 + 1];
-
-		    sprintf(applyArg, "__applyArg%d", i);
-		    id = Lexer::idPool(applyArg);
+
+		    id = Lexer::uniqueId("__applyArg", i);
 
 		    ie = new ExpInitializer(0, new IdentifierExp(0, id));
 		    v = new VarDeclaration(0, arg->type, arg->ident, ie);
@@ -2145,6 +2213,11 @@
     }
     else if (ident == Id::lib)
     {
+#if 1
+	/* Should this be allowed?
+	 */
+	error("pragma(lib) not allowed as statement");
+#else
 	if (!args || args->dim != 1)
 	    error("string expected for library name");
 	else
@@ -2166,6 +2239,7 @@
 		mem.free(name);
 	    }
 	}
+#endif
     }
     else
         error("unrecognized pragma(%s)", ident->toChars());
@@ -2454,8 +2528,7 @@
     //printf("CaseStatement::semantic() %s\n", toChars());
     exp = exp->semantic(sc);
     if (sw)
-    {	int i;
-
+    {
 	exp = exp->implicitCastTo(sc, sw->condition->type);
 	exp = exp->optimize(WANTvalue | WANTinterpret);
 	if (exp->op != TOKstring && exp->op != TOKint64)
@@ -2464,7 +2537,7 @@
 	    exp = new IntegerExp(0);
 	}
 
-	for (i = 0; i < sw->cases->dim; i++)
+	for (int i = 0; i < sw->cases->dim; i++)
 	{
 	    CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
 
@@ -2478,7 +2551,7 @@
 	sw->cases->push(this);
 
 	// Resolve any goto case's with no exp to this case statement
-	for (i = 0; i < sw->gotoCases.dim; i++)
+	for (size_t i = 0; i < sw->gotoCases.dim; i++)
 	{
 	    GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
 
@@ -2875,32 +2948,25 @@
 	    exp->op == TOKstring)
 	{
 	    sc->fes->cases.push(this);
+	    // Construct: return cases.dim+1;
 	    s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
 	}
 	else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
 	{
-	    Statement *s1;
-	    Statement *s2;
-
 	    s = new ReturnStatement(0, NULL);
 	    sc->fes->cases.push(s);
 
 	    // Construct: { exp; return cases.dim + 1; }
-	    s1 = new ExpStatement(loc, exp);
-	    s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	    Statement *s1 = new ExpStatement(loc, exp);
+	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
 	    s = new CompoundStatement(loc, s1, s2);
 	}
 	else
 	{
-	    VarExp *v;
-	    Statement *s1;
-	    Statement *s2;
-
 	    // Construct: return vresult;
 	    if (!fd->vresult)
-	    {	VarDeclaration *v;
-
-		v = new VarDeclaration(loc, tret, Id::result, NULL);
+	    {	// Declare vresult
+		VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
 		v->noauto = 1;
 		v->semantic(scx);
 		if (!scx->insert(v))
@@ -2909,16 +2975,14 @@
 		fd->vresult = v;
 	    }
 
-	    v = new VarExp(0, fd->vresult);
-	    s = new ReturnStatement(0, v);
+	    s = new ReturnStatement(0, new VarExp(0, fd->vresult));
 	    sc->fes->cases.push(s);
 
 	    // Construct: { vresult = exp; return cases.dim + 1; }
-	    v = new VarExp(0, fd->vresult);
-	    exp = new AssignExp(loc, v, exp);
+	    exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
 	    exp = exp->semantic(sc);
-	    s1 = new ExpStatement(loc, exp);
-	    s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
+	    Statement *s1 = new ExpStatement(loc, exp);
+	    Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
 	    s = new CompoundStatement(loc, s1, s2);
 	}
 	return s;
@@ -2959,9 +3023,10 @@
 
 	gs->label = fd->returnLabel;
 	if (exp)
-	{   Statement *s;
-
-	    s = new ExpStatement(0, exp);
+	{   /* Replace: return exp;
+	     * with:    exp; goto returnLabel;
+	     */
+	    Statement *s = new ExpStatement(0, exp);
 	    return new CompoundStatement(loc, s, gs);
 	}
 	return gs;
@@ -3739,10 +3804,7 @@
 	     *	sexception:    x = 1;
 	     *	sfinally: if (!x) statement;
 	     */
-	    static int num;
-	    char name[5 + sizeof(num) * 3 + 1];
-	    sprintf(name, "__osf%d", ++num);
-	    Identifier *id = Lexer::idPool(name);
+	    Identifier *id = Lexer::uniqueId("__os");
 
 	    ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
 	    VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);