Mercurial > projects > ldc
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