diff dmd/template.c @ 159:5acec6b2eef8 trunk

[svn r175] merged dmd 1.029
author ChristianK
date Thu, 01 May 2008 15:15:28 +0200
parents 0ab29b838084
children 297690b5d4a5
line wrap: on
line diff
--- a/dmd/template.c	Thu May 01 13:33:02 2008 +0200
+++ b/dmd/template.c	Thu May 01 15:15:28 2008 +0200
@@ -130,6 +130,7 @@
     Dsymbol *s2 = isDsymbol(o2);
     Tuple *v1 = isTuple(o1);
     Tuple *v2 = isTuple(o2);
+    //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
 
     /* A proper implementation of the various equals() overrides
      * should make it possible to just do o1->equals(o2), but
@@ -158,7 +159,7 @@
 	}
 
 	if (!t2 || !t1->equals(t2))
-	    goto L1;
+	    goto Lnomatch;
     }
     else if (e1)
     {
@@ -168,33 +169,39 @@
 	    printf("match %d\n", e1->equals(e2));
 	    e1->print();
 	    e2->print();
+	    e1->type->print();
+	    e2->type->print();
 	}
 #endif
-	if (!e2 || !e1->equals(e2))
-	    goto L1;
+	if (!e2)
+	    goto Lnomatch;
+	if (!e1->equals(e2))
+	    goto Lnomatch;
     }
     else if (s1)
     {
 	//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
 	if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
-	    goto L1;
+	{
+	    goto Lnomatch;
+	}
     }
     else if (v1)
     {
 	if (!v2)
-	    goto L1;
+	    goto Lnomatch;
 	if (v1->objects.dim != v2->objects.dim)
-	    goto L1;
+	    goto Lnomatch;
 	for (size_t i = 0; i < v1->objects.dim; i++)
 	{
 	    if (!match((Object *)v1->objects.data[i],
 		       (Object *)v2->objects.data[i],
 		       tempdecl, sc))
-		goto L1;
+		goto Lnomatch;
 	}
     }
     return 1;	// match
-L1:
+Lnomatch:
     return 0;	// nomatch;
 }
 
@@ -268,6 +275,7 @@
 #endif
     this->loc = loc;
     this->parameters = parameters;
+    this->origParameters = parameters;
     this->members = decldefs;
     this->overnext = NULL;
     this->overroot = NULL;
@@ -336,6 +344,17 @@
     Scope *paramscope = sc->push(paramsym);
     paramscope->parameterSpecialization = 1;
 
+    if (global.params.doDocComments)
+    {
+	origParameters = new TemplateParameters();
+	origParameters->setDim(parameters->dim);
+	for (int i = 0; i < parameters->dim; i++)
+	{
+	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    origParameters->data[i] = (void *)tp->syntaxCopy();
+	}
+    }
+
     for (int i = 0; i < parameters->dim; i++)
     {
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
@@ -348,6 +367,8 @@
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
 
 	tp->semantic(paramscope);
+	if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
+	    error("template tuple parameter must be last one");
     }
 
     paramscope->pop();
@@ -437,6 +458,7 @@
  * those deduced types in dedtypes[].
  * Input:
  *	flag	1: don't do semantic() because of dummy types
+ *		2: don't change types in matchArg()
  * Output:
  *	dedtypes	deduced arguments
  * Return match level.
@@ -447,8 +469,9 @@
 {   MATCH m;
     int dedtypes_dim = dedtypes->dim;
 
-#if LOG
-    printf("+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
+#define LOGM 0
+#if LOGM
+    printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
 #endif
 
 #if 0
@@ -466,7 +489,7 @@
     // If more arguments than parameters, no match
     if (ti->tiargs->dim > parameters_dim && !variadic)
     {
-#if LOG
+#if LOGM
 	printf(" no match: more arguments than parameters\n");
 #endif
 	return MATCHnomatch;
@@ -489,7 +512,7 @@
 	Declaration *sparam;
 
 	//printf("\targument [%d]\n", i);
-#if 0
+#if LOGM
 	//printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
 	TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
 	if (ttp)
@@ -528,7 +551,7 @@
 	}
     }
 
-#if 0
+#if LOGM
     // Print out the results
     printf("--------------------------\n");
     printf("template %s\n", toChars());
@@ -553,20 +576,20 @@
 	goto Lnomatch;
 #endif
 
-#if LOG
+#if LOGM
     printf(" match = %d\n", m);
 #endif
     goto Lret;
 
 Lnomatch:
-#if LOG
+#if LOGM
     printf(" no match\n");
 #endif
     m = MATCHnomatch;
 
 Lret:
     paramscope->pop();
-#if LOG
+#if LOGM
     printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
 #endif
     return m;
@@ -645,6 +668,8 @@
  *	fargs		arguments to function
  * Output:
  *	dedargs		Expression/Type deduced template arguments
+ * Returns:
+ *	match level
  */
 
 MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
@@ -652,12 +677,13 @@
 {
     size_t i;
     size_t nfparams;
-    size_t nfparams2;
     size_t nfargs;
-    size_t nargsi;
+    size_t nargsi;		// array size of targsi
+    int fptupindex = -1;
+    int tuple_dim = 0;
     MATCH match = MATCHexact;
     FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
-    TypeFunction *fdtype;
+    TypeFunction *fdtype;		// type of fd
     TemplateTupleParameter *tp;
     Objects dedtypes;	// for T:T*, the dedargs is the T*, dedtypes is the T
 
@@ -682,13 +708,19 @@
     paramsym->parent = scope->parent;
     Scope *paramscope = scope->push(paramsym);
 
+    tp = isVariadic();
+
     nargsi = 0;
     if (targsi)
     {	// Set initial template arguments
 
 	nargsi = targsi->dim;
 	if (nargsi > parameters->dim)
-	    goto Lnomatch;
+	{   if (!tp)
+		goto Lnomatch;
+	    dedargs->setDim(nargsi);
+	    dedargs->zero();
+	}
 
 	memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
 
@@ -698,6 +730,7 @@
 	    Declaration *sparam;
 
 	    m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
+	    //printf("\tdeduceType m = %d\n", m);
 	    if (m == MATCHnomatch)
 		goto Lnomatch;
 	    if (m < match)
@@ -713,7 +746,6 @@
     fdtype = (TypeFunction *)fd->type;
 
     nfparams = Argument::dim(fdtype->parameters); // number of function parameters
-    nfparams2 = nfparams;
     nfargs = fargs->dim;		// number of function arguments
 
     /* Check for match of function arguments with variadic template
@@ -723,7 +755,7 @@
      * void main() { Foo(1,2,3); }
      */
     tp = isVariadic();
-    if (tp)
+    if (tp)				// if variadic
     {
 	if (nfparams == 0)		// if no function parameters
 	{
@@ -736,33 +768,38 @@
 	    goto L1;
 	else
 	{
-	    /* See if 'A' of the template parameter matches 'A'
-	     * of the type of the last function parameter.
+	    /* Figure out which of the function parameters matches
+	     * the tuple template parameter. Do this by matching
+	     * type identifiers.
+	     * Set the index of this function parameter to fptupindex.
 	     */
-	    Argument *fparam = (Argument *)fdtype->parameters->data[nfparams - 1];
-	    if (fparam->type->ty != Tident)
-		goto L1;
-	    TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
-	    if (!tp->ident->equals(tid->ident) || tid->idents.dim)
-		goto L1;
-
-	    if (fdtype->varargs)	// variadic function doesn't
-		goto Lnomatch;		// go with variadic template
-
-	    /* The types of the function arguments [nfparams - 1 .. nfargs]
-	     * now form the tuple argument.
-	     */
-	    Tuple *t = new Tuple();
-	    dedargs->data[parameters->dim - 1] = (void *)t;
-
-	    int tuple_dim = nfargs - (nfparams - 1);
-	    t->objects.setDim(tuple_dim);
-	    for (i = 0; i < tuple_dim; i++)
-	    {	Expression *farg = (Expression *)fargs->data[nfparams - 1 + i];
-		t->objects.data[i] = (void *)farg->type;
+	    for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
+	    {
+		Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex];
+		if (fparam->type->ty != Tident)
+		    continue;
+		TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
+		if (!tp->ident->equals(tid->ident) || tid->idents.dim)
+		    continue;
+
+		if (fdtype->varargs)	// variadic function doesn't
+		    goto Lnomatch;	// go with variadic template
+
+		/* The types of the function arguments
+		 * now form the tuple argument.
+		 */
+		Tuple *t = new Tuple();
+		dedargs->data[parameters->dim - 1] = (void *)t;
+
+		tuple_dim = nfargs - (nfparams - 1);
+		t->objects.setDim(tuple_dim);
+		for (i = 0; i < tuple_dim; i++)
+		{   Expression *farg = (Expression *)fargs->data[fptupindex + i];
+		    t->objects.data[i] = (void *)farg->type;
+		}
+		goto L2;
 	    }
-	    nfparams2--;	// don't consider the last parameter for type deduction
-	    goto L2;
+	    fptupindex = -1;
 	}
     }
 
@@ -778,11 +815,19 @@
 
 L2:
     // Loop through the function parameters
-    for (i = 0; i < nfparams2; i++)
+    for (i = 0; i < nfparams; i++)
     {
+	/* Skip over function parameters which wound up
+	 * as part of a template tuple parameter.
+	 */
+	if (i == fptupindex)
+	{   if (fptupindex == nfparams - 1)
+		break;
+	    i += tuple_dim - 1;
+	    continue;
+	}
+
 	Argument *fparam = Argument::getNth(fdtype->parameters, i);
-	Expression *farg;
-	MATCH m;
 
 	if (i >= nfargs)		// if not enough arguments
 	{
@@ -794,12 +839,13 @@
 	    }
 	}
 	else
-	{   farg = (Expression *)fargs->data[i];
+	{   Expression *farg = (Expression *)fargs->data[i];
 #if 0
 	    printf("\tfarg->type   = %s\n", farg->type->toChars());
 	    printf("\tfparam->type = %s\n", fparam->type->toChars());
 #endif
 
+	    MATCH m;
 	    m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
 	    //printf("\tdeduceType m = %d\n", m);
 
@@ -852,30 +898,40 @@
     for (i = nargsi; i < dedargs->dim; i++)
     {
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	//printf("tp[%d] = %s\n", i, tp->ident->toChars());
+	/* For T:T*, the dedargs is the T*, dedtypes is the T
+	 * But for function templates, we really need them to match
+	 */
 	Object *oarg = (Object *)dedargs->data[i];
-	Object *o = (Object *)dedtypes.data[i];
-	//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, o);
+	Object *oded = (Object *)dedtypes.data[i];
+	//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
 	if (!oarg)
 	{
-	    if (o)
+	    if (oded)
 	    {
 		if (tp->specialization())
-		    error("specialization not allowed for deduced parameter %s", tp->ident->toChars());
+		{   /* The specialization can work as long as afterwards
+		     * the oded == oarg
+		     */
+		    Declaration *sparam;
+		    dedargs->data[i] = (void *)oded;
+		    MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
+		    //printf("m2 = %d\n", m2);
+		    if (!m2)
+			goto Lnomatch;
+		    if (m2 < match)
+			match = m2;		// pick worst match
+		    if (dedtypes.data[i] != oded)
+			error("specialization not allowed for deduced parameter %s", tp->ident->toChars());
+		}
 	    }
 	    else
-	    {	o = tp->defaultArg(paramscope);
-		if (!o)
+	    {	oded = tp->defaultArg(paramscope);
+		if (!oded)
 		    goto Lnomatch;
-#if 0
-		Match m;
-		Declaration *sparam;
-		m = tp->matchArg(paramscope, dedargs, i, parameters, &sparam);
-		if (!m)
-		    goto Lnomatch;
-#endif
 	    }
-	    declareParameter(paramscope, tp, o);
-	    dedargs->data[i] = (void *)o;
+	    declareParameter(paramscope, tp, oded);
+	    dedargs->data[i] = (void *)oded;
 	}
     }
 
@@ -887,7 +943,7 @@
 #endif
 
     paramscope->pop();
-    //printf("\tmatch\n");
+    //printf("\tmatch %d\n", match);
     return match;
 
 Lnomatch:
@@ -1044,9 +1100,9 @@
 	int c2 = td_best->leastAsSpecialized(td);
 	//printf("c1 = %d, c2 = %d\n", c1, c2);
 
-	if (c1 && !c2)
+	if (c1 > c2)
 	    goto Ltd;
-	else if (!c1 && c2)
+	else if (c1 < c2)
 	    goto Ltd_best;
 	else
 	    goto Lambig;
@@ -1116,6 +1172,8 @@
     for (int i = 0; i < parameters->dim; i++)
     {
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	if (hgs->ddoc)
+	    tp = (TemplateParameter *)origParameters->data[i];
 	if (i)
 	    buf->writeByte(',');
 	tp->toCBuffer(buf, hgs);
@@ -1516,7 +1574,19 @@
 		 */
 		int i = templateIdentifierLookup(tp->tempinst->name, parameters);
 		if (i == -1)
+		{   /* Didn't find it as a parameter identifier. Try looking
+		     * it up and seeing if is an alias. See Bugzilla 1454
+		     */
+		    Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
+		    if (s)
+		    {
+			s = s->toAlias();
+			TemplateDeclaration *td = s->isTemplateDeclaration();
+			if (td && td == tempinst->tempdecl)
+			    goto L2;
+		    }
 		    goto Lnomatch;
+		}
 		TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
 		// This logic duplicates tpx->matchArg()
 		TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
@@ -1540,12 +1610,14 @@
 	else if (tempinst->tempdecl != tp->tempinst->tempdecl)
 	    goto Lnomatch;
 
+      L2:
 	if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
 	    goto Lnomatch;
 
 	for (int i = 0; i < tempinst->tiargs->dim; i++)
 	{
-	    //printf("test: [%d]\n", i);
+	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
+	    int j;
 	    Object *o1 = (Object *)tempinst->tiargs->data[i];
 	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
 
@@ -1570,18 +1642,29 @@
 	    else if (e1 && e2)
 	    {
 		if (!e1->equals(e2))
+		{   if (e2->op == TOKvar)
+		    {
+			/*
+			 * (T:Number!(e2), int e2)
+			 */
+			j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
+			goto L1;
+		    }
 		    goto Lnomatch;
+		}
 	    }
 	    else if (e1 && t2 && t2->ty == Tident)
-	    {	int i = templateParameterLookup(t2, parameters);
-		if (i == -1)
+	    {
+		j = templateParameterLookup(t2, parameters);
+	    L1:
+		if (j == -1)
 		    goto Lnomatch;
-		TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
 		// BUG: use tp->matchArg() instead of the following
 		TemplateValueParameter *tv = tp->isTemplateValueParameter();
 		if (!tv)
 		    goto Lnomatch;
-		Expression *e = (Expression *)dedtypes->data[i];
+		Expression *e = (Expression *)dedtypes->data[j];
 		if (e)
 		{
 		    if (!e1->equals(e))
@@ -1592,7 +1675,7 @@
 		    MATCH m = (MATCH)e1->implicitConvTo(vt);
 		    if (!m)
 			goto Lnomatch;
-		    dedtypes->data[i] = e1;
+		    dedtypes->data[j] = e1;
 		}
 	    }
 	    // BUG: Need to handle alias and tuple parameters
@@ -2351,6 +2434,7 @@
     return m;
 
 Lnomatch:
+    //printf("\tno match\n");
     *psparam = NULL;
     return MATCHnomatch;
 }
@@ -2780,7 +2864,7 @@
 	    if (m->semanticdone >= 3)
 		dosemantic3 = 1;
 	}
-	for (i = 0; 1; i++)
+	for (int i = 0; 1; i++)
 	{
 	    if (i == a->dim)
 	    {
@@ -2953,7 +3037,7 @@
 	Expression *ea = isExpression(o);
 	Dsymbol *sa = isDsymbol(o);
 
-	//printf("1: tiargs->data[%d] = %p, %p, %p\n", j, o, isDsymbol(o), isTuple(o));
+	//printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
 	if (ta)
 	{
 	    //printf("type %s\n", ta->toChars());
@@ -3196,9 +3280,9 @@
 	int c2 = td_best->leastAsSpecialized(td);
 	//printf("c1 = %d, c2 = %d\n", c1, c2);
 
-	if (c1 && !c2)
+	if (c1 > c2)
 	    goto Ltd;
-	else if (!c1 && c2)
+	else if (c1 < c2)
 	    goto Ltd_best;
 	else
 	    goto Lambig;
@@ -3305,10 +3389,30 @@
 	    {
 		// if module level template
 		if (tempdecl->toParent()->isModule())
-		{
-		    if (isnested && isnested != d->toParent())
-			error("inconsistent nesting levels %s and %s", isnested->toChars(), d->toParent()->toChars());
-		    isnested = d->toParent();
+		{   Dsymbol *dparent = d->toParent();
+		    if (!isnested)
+			isnested = dparent;
+		    else if (isnested != dparent)
+		    {
+			/* Select the more deeply nested of the two.
+			 * Error if one is not nested inside the other.
+			 */
+			for (Dsymbol *p = isnested; p; p = p->parent)
+			{
+			    if (p == dparent)
+				goto L1;	// isnested is most nested
+			}
+			for (Dsymbol *p = dparent; 1; p = p->parent)
+			{
+			    if (p == isnested)
+			    {	isnested = dparent;
+				goto L1;	// dparent is most nested
+			    }
+			}
+			error("is nested in both %s and %s", isnested->toChars(), dparent->toChars());
+		    }
+		  L1:
+		    //printf("\tnested inside %s\n", isnested->toChars());
 		    nested |= 1;
 		}
 		else