diff dmd/statement.c @ 719:7261ff0f95ff

Implemented first class delegates. closes #101
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Wed, 22 Oct 2008 21:50:08 +0200
parents 30b42a283c8e
children f08e0ff8d28c
line wrap: on
line diff
--- a/dmd/statement.c	Wed Oct 22 20:00:57 2008 +0200
+++ b/dmd/statement.c	Wed Oct 22 21:50:08 2008 +0200
@@ -1517,6 +1517,9 @@
 	    Expression *flde;
 	    Identifier *id;
 	    Type *tret;
+        TypeDelegate* dgty;
+        TypeDelegate* dgty2;
+        TypeDelegate* fldeTy;
 
 	    tret = func->type->nextOf();
 
@@ -1600,6 +1603,7 @@
 		 */
 		//LDC: Build arguments.
 		static FuncDeclaration *aaApply2_fd = NULL;
+        static TypeDelegate* aaApply2_dg;
 		if(!aaApply2_fd) {
 		    Arguments* args = new Arguments;
 		    args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
@@ -1607,25 +1611,28 @@
 		    Arguments* dgargs = new Arguments;
 		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
 		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
-		    args->push(new Argument(STCin, dgty, NULL, NULL));
+		    aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    args->push(new Argument(STCin, aaApply2_dg, NULL, NULL));
 		    aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2");
 		}
 		static FuncDeclaration *aaApply_fd = NULL;
+        static TypeDelegate* aaApply_dg;
 		if(!aaApply_fd) {
 		    Arguments* args = new Arguments;
 		    args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
 		    args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
 		    Arguments* dgargs = new Arguments;
 		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
-		    args->push(new Argument(STCin, dgty, NULL, NULL));
+		    aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    args->push(new Argument(STCin, aaApply_dg, NULL, NULL));
 		    aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply");
 		}
 		if (dim == 2) {
 		    fdapply = aaApply2_fd;
+            fldeTy = aaApply2_dg;
 		} else {
 		    fdapply = aaApply_fd;
+            fldeTy = aaApply_dg;
 		}
 		ec = new VarExp(0, fdapply);
 		Expressions *exps = new Expressions();
@@ -1633,7 +1640,15 @@
 		size_t keysize = taa->key->size();
 		keysize = (keysize + 3) & ~3;
 		exps->push(new IntegerExp(0, keysize, Type::tsize_t));
+
+        // LDC paint delegate argument to the type runtime expects
+        if (!fldeTy->equals(flde->type))
+        {
+            flde = new CastExp(loc, flde, flde->type);
+            flde->type = fldeTy;
+        }
 		exps->push(flde);
+
 		e = new CallExp(loc, ec, exps);
 		e->type = Type::tindex;	// don't run semantic() on e
 	    }
@@ -1674,13 +1689,13 @@
 		    Arguments* dgargs = new Arguments;
 		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
 		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
 		    args->push(new Argument(STCin, dgty, NULL, NULL));
 		    fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
 		} else {
 		    Arguments* dgargs = new Arguments;
 		    dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
-		    TypeDelegate* dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
+		    dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
 		    args->push(new Argument(STCin, dgty, NULL, NULL));
 		    fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
 		}
@@ -1690,7 +1705,15 @@
 		if (tab->ty == Tsarray)
 		   aggr = aggr->castTo(sc, tn->arrayOf());
         exps->push(aggr);
+
+        // LDC paint delegate argument to the type runtime expects
+        if (!dgty->equals(flde->type))
+        {
+            flde = new CastExp(loc, flde, flde->type);
+            flde->type = dgty;
+        }
 		exps->push(flde);
+
 		e = new CallExp(loc, ec, exps);
 		e->type = Type::tindex;	// don't run semantic() on e
 	    }