diff dmd2/statement.c @ 847:356e65836fb5

Merged DMD 2.021 frontend. Removed generated files from dmd/dmd2 dirs.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 13 Dec 2008 16:14:37 +0100
parents f08e0ff8d28c
children 03d7c4aac654
line wrap: on
line diff
--- a/dmd2/statement.c	Sat Dec 13 13:15:31 2008 +0100
+++ b/dmd2/statement.c	Sat Dec 13 16:14:37 2008 +0100
@@ -1116,7 +1116,9 @@
 	condition = condition->checkToBoolean();
     }
     if (increment)
-	increment = increment->semantic(sc);
+    {	increment = increment->semantic(sc);
+	increment = resolveProperties(sc, increment);
+    }
 
     sc->sbreak = this;
     sc->scontinue = this;
@@ -1261,8 +1263,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;
@@ -1391,15 +1392,6 @@
 	return s;
     }
 
-    for (i = 0; i < dim; i++)
-    {	Argument *arg = (Argument *)arguments->data[i];
-	if (!arg->type)
-	{
-	    error("cannot infer type for %s", arg->ident->toChars());
-	    return this;
-	}
-    }
-
     sym = new ScopeDsymbol();
     sym->parent = sc->scopesym;
     sc = sc->push(sym);
@@ -1410,6 +1402,9 @@
     {
 	case Tarray:
 	case Tsarray:
+	    if (!checkForArgTypes())
+		return this;
+
 	    if (dim < 1 || dim > 2)
 	    {
 		error("only one or two arguments for array foreach");
@@ -1423,7 +1418,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();
@@ -1441,7 +1436,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;
@@ -1506,6 +1501,9 @@
 	    break;
 
 	case Taarray:
+	    if (!checkForArgTypes())
+		return this;
+
 	    taa = (TypeAArray *)tab;
 	    if (dim < 1 || dim > 2)
 	    {
@@ -1520,6 +1518,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::Ftoe;
+		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;
@@ -1536,6 +1600,9 @@
         TypeDelegate* dgty2;
         TypeDelegate* fldeTy;
 
+	    if (!checkForArgTypes())
+		return this;
+
 	    tret = func->type->nextOf();
 
 	    // Need a variable to hold value from any return statements in body.
@@ -1555,7 +1622,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);
@@ -1815,6 +1882,19 @@
     return s;
 }
 
+bool ForeachStatement::checkForArgTypes()
+{
+    for (size_t i = 0; i < arguments->dim; i++)
+    {	Argument *arg = (Argument *)arguments->data[i];
+	if (!arg->type)
+	{
+	    error("cannot infer type for %s", arg->ident->toChars());
+	    return FALSE;
+	}
+    }
+    return TRUE;
+}
+
 int ForeachStatement::hasBreak()
 {
     return TRUE;
@@ -1888,6 +1968,8 @@
 
 /**************************** ForeachRangeStatement ***************************/
 
+#if DMDV2
+
 ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
 	Expression *lwr, Expression *upr, Statement *body)
     : Statement(loc)
@@ -2047,6 +2129,8 @@
     buf->writenl();
 }
 
+#endif
+
 /******************************** IfStatement ***************************/
 
 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
@@ -2339,6 +2423,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
@@ -2360,6 +2449,7 @@
 		mem.free(name);
 	    }
 	}
+#endif
     }
     else if (ident == Id::startaddress)
     {