diff dmd/template.c @ 875:330f999ade44

Merged DMD 1.038
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 06 Jan 2009 16:33:51 +0100
parents eef8ac26c66c
children 27a379f288bf
line wrap: on
line diff
--- a/dmd/template.c	Tue Jan 06 15:54:48 2009 +0100
+++ b/dmd/template.c	Tue Jan 06 16:33:51 2009 +0100
@@ -201,8 +201,10 @@
 		goto Lnomatch;
 	}
     }
+    //printf("match\n");
     return 1;	// match
 Lnomatch:
+    //printf("nomatch\n");
     return 0;	// nomatch;
 }
 
@@ -320,7 +322,9 @@
 
     if (sc->func)
     {
+#if DMDV1
 	error("cannot declare template at function scope %s", sc->func->toChars());
+#endif
     }
 
     if (/*global.params.useArrayBounds &&*/ sc->module)
@@ -551,7 +555,9 @@
 
     if (!flag)
     {
-	// Any parameter left without a type gets the type of its corresponding arg
+	/* Any parameter left without a type gets the type of
+	 * its corresponding arg
+	 */
 	for (int i = 0; i < dedtypes_dim; i++)
 	{
 	    if (!dedtypes->data[i])
@@ -561,6 +567,25 @@
 	}
     }
 
+#if DMDV2
+    if (m && constraint && !(flag & 1))
+    {	/* Check to see if constraint is satisfied.
+	 */
+	Expression *e = constraint->syntaxCopy();
+	paramscope->flags |= SCOPEstaticif;
+	e = e->semantic(paramscope);
+	e = e->optimize(WANTvalue | WANTinterpret);
+        if (e->isBool(TRUE))
+            ;
+        else if (e->isBool(FALSE))
+            goto Lnomatch;
+        else
+        {
+            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
+        }
+    }
+#endif
+
 #if LOGM
     // Print out the results
     printf("--------------------------\n");
@@ -674,7 +699,9 @@
 /*************************************************
  * Match function arguments against a specific template function.
  * Input:
+ *	loc		instantiation location
  *	targsi		Expression/Type initial list of template arguments
+ *	ethis		'this' argument if !NULL
  *	fargs		arguments to function
  * Output:
  *	dedargs		Expression/Type deduced template arguments
@@ -682,7 +709,8 @@
  *	match level
  */
 
-MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
+MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
+	Expression *ethis, Expressions *fargs,
 	Objects *dedargs)
 {
     size_t i;
@@ -824,6 +852,27 @@
     }
 
 L2:
+#if DMDV2
+    // Match 'ethis' to any TemplateThisParameter's
+    if (ethis)
+    {
+	for (size_t i = 0; i < parameters->dim; i++)
+	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    TemplateThisParameter *ttp = tp->isTemplateThisParameter();
+	    if (ttp)
+	    {	MATCH m;
+
+		Type *t = new TypeIdentifier(0, ttp->ident);
+		m = ethis->type->deduceType(scope, t, parameters, &dedtypes);
+		if (!m)
+		    goto Lnomatch;
+		if (m < match)
+		    match = m;		// pick worst match
+	    }
+	}
+    }
+#endif
+
     // Loop through the function parameters
     for (i = 0; i < nfparams; i++)
     {
@@ -982,7 +1031,7 @@
 		}
 	    }
 	    else
-	    {	oded = tp->defaultArg(paramscope);
+	    {	oded = tp->defaultArg(loc, paramscope);
 		if (!oded)
 		    goto Lnomatch;
 	    }
@@ -991,6 +1040,25 @@
 	}
     }
 
+#if DMDV2
+    if (constraint)
+    {	/* Check to see if constraint is satisfied.
+	 */
+	Expression *e = constraint->syntaxCopy();
+	paramscope->flags |= SCOPEstaticif;
+	e = e->semantic(paramscope);
+	e = e->optimize(WANTvalue | WANTinterpret);
+        if (e->isBool(TRUE))
+            ;
+        else if (e->isBool(FALSE))
+            goto Lnomatch;
+        else
+        {
+            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
+        }
+    }
+#endif
+
 #if 0
     for (i = 0; i < dedargs->dim; i++)
     {	Type *t = (Type *)dedargs->data[i];
@@ -1096,11 +1164,13 @@
  *	sc		instantiation scope
  *	loc		instantiation location
  *	targsi		initial list of template arguments
+ *	ethis		if !NULL, the 'this' pointer argument
  *	fargs		arguments to function
+ *	flags		1: do not issue error message on no match, just return NULL
  */
 
 FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
-	Objects *targsi, Expressions *fargs)
+	Objects *targsi, Expression *ethis, Expressions *fargs, int flags)
 {
     MATCH m_best = MATCHnomatch;
     TemplateDeclaration *td_ambig = NULL;
@@ -1142,7 +1212,7 @@
 	MATCH m;
 	Objects dedargs;
 
-	m = td->deduceFunctionTemplateMatch(targsi, fargs, &dedargs);
+	m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
 	//printf("deduceFunctionTemplateMatch = %d\n", m);
 	if (!m)			// if no match
 	    continue;
@@ -1207,14 +1277,26 @@
 
   Lerror:
     {
+	HdrGenState hgs;
+
+	OutBuffer bufa;
+	Objects *args = targsi;
+	if (args)
+	{   for (int i = 0; i < args->dim; i++)
+	    {
+		if (i)
+		    bufa.writeByte(',');
+		Object *oarg = (Object *)args->data[i];
+		ObjectToCBuffer(&bufa, &hgs, oarg);
+	    }
+	}
+
 	OutBuffer buf;
-	HdrGenState hgs;
-
 	argExpTypesToCBuffer(&buf, fargs, &hgs);
-	error(loc, "cannot deduce template function from argument types (%s)",
-		buf.toChars());
-	return NULL;
+	error(loc, "cannot deduce template function from argument types !(%s)(%s)",
+		bufa.toChars(), buf.toChars());
     }
+    return NULL;
 }
 
 void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -1237,6 +1319,13 @@
 	tp->toCBuffer(buf, hgs);
     }
     buf->writeByte(')');
+#if DMDV2
+    if (constraint)
+    {	buf->writestring(" if (");
+	constraint->toCBuffer(buf, hgs);
+	buf->writeByte(')');
+    }
+#endif
 
     if (hgs->hdrgen)
     {
@@ -1271,6 +1360,13 @@
 	tp->toCBuffer(&buf, &hgs);
     }
     buf.writeByte(')');
+#if DMDV2
+    if (constraint)
+    {	buf.writestring(" if (");
+	constraint->toCBuffer(&buf, &hgs);
+	buf.writeByte(')');
+    }
+#endif
     buf.writeByte(0);
     return (char *)buf.extractData();
 }
@@ -1323,9 +1419,11 @@
 MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
 	Objects *dedtypes)
 {
-    //printf("Type::deduceType()\n");
-    //printf("\tthis   = %d, ", ty); print();
-    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#if 0
+    printf("Type::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
     if (!tparam)
 	goto Lnomatch;
 
@@ -2027,7 +2125,7 @@
 	oarg = (Object *)tiargs->data[i];
     else
     {	// Get default argument instead
-	oarg = defaultArg(sc);
+	oarg = defaultArg(loc, sc);
 	if (!oarg)
 	{   assert(i < dedtypes->dim);
 	    // It might have already been deduced
@@ -2141,7 +2239,7 @@
 }
 
 
-Object *TemplateTypeParameter::defaultArg(Scope *sc)
+Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
 {
     Type *t;
 
@@ -2271,7 +2369,7 @@
 	oarg = (Object *)tiargs->data[i];
     else
     {	// Get default argument instead
-	oarg = defaultArg(sc);
+	oarg = defaultArg(loc, sc);
 	if (!oarg)
 	{   assert(i < dedtypes->dim);
 	    // It might have already been deduced
@@ -2357,7 +2455,7 @@
 }
 
 
-Object *TemplateAliasParameter::defaultArg(Scope *sc)
+Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
 {
     Dsymbol *s = NULL;
 
@@ -2485,7 +2583,7 @@
 	oarg = (Object *)tiargs->data[i];
     else
     {	// Get default argument instead
-	oarg = defaultArg(sc);
+	oarg = defaultArg(loc, sc);
 	if (!oarg)
 	{   assert(i < dedtypes->dim);
 	    // It might have already been deduced
@@ -2602,7 +2700,7 @@
 }
 
 
-Object *TemplateValueParameter::defaultArg(Scope *sc)
+Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
 {
     Expression *e = defaultValue;
     if (e)
@@ -2748,7 +2846,7 @@
 }
 
 
-Object *TemplateTupleParameter::defaultArg(Scope *sc)
+Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc)
 {
     return NULL;
 }
@@ -2778,6 +2876,10 @@
     this->tinst = NULL;
 }
 
+/*****************
+ * This constructor is only called when we figured out which function
+ * template to instantiate.
+ */
 
 TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs)
     : ScopeDsymbol(NULL)
@@ -2830,7 +2932,6 @@
 Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
 {
     TemplateInstance *ti;
-    int i;
 
     if (s)
 	ti = (TemplateInstance *)s;
@@ -2896,7 +2997,9 @@
     }
     else
     {
-	// Run semantic on each argument, place results in tiargs[]
+	/* Run semantic on each argument, place results in tiargs[]
+	 * (if we havetempdecl, then tiargs is already evaluated)
+	 */
 	semanticTiargs(sc);
 
 	tempdecl = findTemplateDeclaration(sc);
@@ -2974,12 +3077,26 @@
 #if 1
     int dosemantic3 = 0;
     {	Array *a;
-	int i;
-
-	if (sc->scopesym && sc->scopesym->members && !sc->scopesym->isTemplateMixin())
+
+	Scope *scx = sc;
+#if 0
+	for (scx = sc; scx; scx = scx->enclosing)
+	    if (scx->scopesym)
+		break;
+#endif
+
+	//if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
+	if (scx && scx->scopesym &&
+	    scx->scopesym->members && !scx->scopesym->isTemplateMixin() &&
+	    /* The following test should really be if scx->module recursively
+	     * imports itself. Because if it does, see bugzilla 2500.
+	     */
+	    //scx->module == tempdecl->getModule()
+	    !scx->module->imports(scx->module)
+	   )
 	{
-	    //printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
-	    a = sc->scopesym->members;
+	    //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
+	    a = scx->scopesym->members;
 	}
 	else
 	{   Module *m = sc->module->importedFrom;
@@ -3395,19 +3512,15 @@
 	    return NULL;
 	}
 	m = td->matchWithInstance(this, &dedtypes, 0);
-	//printf("m = %d\n", m);
+	//printf("matchWithInstance = %d\n", m);
 	if (!m)			// no match at all
 	    continue;
 
-#if 1
 	if (m < m_best)
 	    goto Ltd_best;
 	if (m > m_best)
 	    goto Ltd;
-#else
-	if (!m_best)
-	    goto Ltd;
-#endif
+
 	{
 	// Disambiguate by picking the most specialized TemplateDeclaration
 	int c1 = td->leastAsSpecialized(td_best);
@@ -3656,6 +3769,7 @@
     buf.writeByte('Z');
     id = buf.toChars();
     buf.data = NULL;
+    //printf("\tgenIdent = %s\n", id);
     return new Identifier(id, TOKidentifier);
 }
 
@@ -3672,7 +3786,7 @@
     {
 	TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
 	//Object *o = (Object *)tiargs->data[i];
-	Object *o = (Object *)tdtypes.data[i];
+	Object *o = (Object *)tdtypes.data[i];		// initializer for tp
 
 	//printf("\ttdtypes[%d] = %p\n", i, o);
 	tempdecl->declareParameter(scope, tp, o);