Mercurial > projects > ldc
comparison 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 |
comparison
equal
deleted
inserted
replaced
158:287540c5f05e | 159:5acec6b2eef8 |
---|---|
128 Expression *e2 = isExpression(o2); | 128 Expression *e2 = isExpression(o2); |
129 Dsymbol *s1 = isDsymbol(o1); | 129 Dsymbol *s1 = isDsymbol(o1); |
130 Dsymbol *s2 = isDsymbol(o2); | 130 Dsymbol *s2 = isDsymbol(o2); |
131 Tuple *v1 = isTuple(o1); | 131 Tuple *v1 = isTuple(o1); |
132 Tuple *v2 = isTuple(o2); | 132 Tuple *v2 = isTuple(o2); |
133 //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); | |
133 | 134 |
134 /* A proper implementation of the various equals() overrides | 135 /* A proper implementation of the various equals() overrides |
135 * should make it possible to just do o1->equals(o2), but | 136 * should make it possible to just do o1->equals(o2), but |
136 * we'll do that another day. | 137 * we'll do that another day. |
137 */ | 138 */ |
156 } | 157 } |
157 } | 158 } |
158 } | 159 } |
159 | 160 |
160 if (!t2 || !t1->equals(t2)) | 161 if (!t2 || !t1->equals(t2)) |
161 goto L1; | 162 goto Lnomatch; |
162 } | 163 } |
163 else if (e1) | 164 else if (e1) |
164 { | 165 { |
165 #if 0 | 166 #if 0 |
166 if (e1 && e2) | 167 if (e1 && e2) |
167 { | 168 { |
168 printf("match %d\n", e1->equals(e2)); | 169 printf("match %d\n", e1->equals(e2)); |
169 e1->print(); | 170 e1->print(); |
170 e2->print(); | 171 e2->print(); |
171 } | 172 e1->type->print(); |
172 #endif | 173 e2->type->print(); |
173 if (!e2 || !e1->equals(e2)) | 174 } |
174 goto L1; | 175 #endif |
176 if (!e2) | |
177 goto Lnomatch; | |
178 if (!e1->equals(e2)) | |
179 goto Lnomatch; | |
175 } | 180 } |
176 else if (s1) | 181 else if (s1) |
177 { | 182 { |
178 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars()); | 183 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars()); |
179 if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) | 184 if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) |
180 goto L1; | 185 { |
186 goto Lnomatch; | |
187 } | |
181 } | 188 } |
182 else if (v1) | 189 else if (v1) |
183 { | 190 { |
184 if (!v2) | 191 if (!v2) |
185 goto L1; | 192 goto Lnomatch; |
186 if (v1->objects.dim != v2->objects.dim) | 193 if (v1->objects.dim != v2->objects.dim) |
187 goto L1; | 194 goto Lnomatch; |
188 for (size_t i = 0; i < v1->objects.dim; i++) | 195 for (size_t i = 0; i < v1->objects.dim; i++) |
189 { | 196 { |
190 if (!match((Object *)v1->objects.data[i], | 197 if (!match((Object *)v1->objects.data[i], |
191 (Object *)v2->objects.data[i], | 198 (Object *)v2->objects.data[i], |
192 tempdecl, sc)) | 199 tempdecl, sc)) |
193 goto L1; | 200 goto Lnomatch; |
194 } | 201 } |
195 } | 202 } |
196 return 1; // match | 203 return 1; // match |
197 L1: | 204 Lnomatch: |
198 return 0; // nomatch; | 205 return 0; // nomatch; |
199 } | 206 } |
200 | 207 |
201 /**************************************** | 208 /**************************************** |
202 */ | 209 */ |
266 } | 273 } |
267 } | 274 } |
268 #endif | 275 #endif |
269 this->loc = loc; | 276 this->loc = loc; |
270 this->parameters = parameters; | 277 this->parameters = parameters; |
278 this->origParameters = parameters; | |
271 this->members = decldefs; | 279 this->members = decldefs; |
272 this->overnext = NULL; | 280 this->overnext = NULL; |
273 this->overroot = NULL; | 281 this->overroot = NULL; |
274 this->scope = NULL; | 282 this->scope = NULL; |
275 this->onemember = NULL; | 283 this->onemember = NULL; |
334 ScopeDsymbol *paramsym = new ScopeDsymbol(); | 342 ScopeDsymbol *paramsym = new ScopeDsymbol(); |
335 paramsym->parent = sc->parent; | 343 paramsym->parent = sc->parent; |
336 Scope *paramscope = sc->push(paramsym); | 344 Scope *paramscope = sc->push(paramsym); |
337 paramscope->parameterSpecialization = 1; | 345 paramscope->parameterSpecialization = 1; |
338 | 346 |
347 if (global.params.doDocComments) | |
348 { | |
349 origParameters = new TemplateParameters(); | |
350 origParameters->setDim(parameters->dim); | |
351 for (int i = 0; i < parameters->dim; i++) | |
352 { | |
353 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
354 origParameters->data[i] = (void *)tp->syntaxCopy(); | |
355 } | |
356 } | |
357 | |
339 for (int i = 0; i < parameters->dim; i++) | 358 for (int i = 0; i < parameters->dim; i++) |
340 { | 359 { |
341 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 360 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
342 | 361 |
343 tp->declareParameter(paramscope); | 362 tp->declareParameter(paramscope); |
346 for (int i = 0; i < parameters->dim; i++) | 365 for (int i = 0; i < parameters->dim; i++) |
347 { | 366 { |
348 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 367 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
349 | 368 |
350 tp->semantic(paramscope); | 369 tp->semantic(paramscope); |
370 if (i + 1 != parameters->dim && tp->isTemplateTupleParameter()) | |
371 error("template tuple parameter must be last one"); | |
351 } | 372 } |
352 | 373 |
353 paramscope->pop(); | 374 paramscope->pop(); |
354 | 375 |
355 if (members) | 376 if (members) |
435 * Given that ti is an instance of this TemplateDeclaration, | 456 * Given that ti is an instance of this TemplateDeclaration, |
436 * deduce the types of the parameters to this, and store | 457 * deduce the types of the parameters to this, and store |
437 * those deduced types in dedtypes[]. | 458 * those deduced types in dedtypes[]. |
438 * Input: | 459 * Input: |
439 * flag 1: don't do semantic() because of dummy types | 460 * flag 1: don't do semantic() because of dummy types |
461 * 2: don't change types in matchArg() | |
440 * Output: | 462 * Output: |
441 * dedtypes deduced arguments | 463 * dedtypes deduced arguments |
442 * Return match level. | 464 * Return match level. |
443 */ | 465 */ |
444 | 466 |
445 MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, | 467 MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, |
446 Objects *dedtypes, int flag) | 468 Objects *dedtypes, int flag) |
447 { MATCH m; | 469 { MATCH m; |
448 int dedtypes_dim = dedtypes->dim; | 470 int dedtypes_dim = dedtypes->dim; |
449 | 471 |
450 #if LOG | 472 #define LOGM 0 |
451 printf("+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag); | 473 #if LOGM |
474 printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag); | |
452 #endif | 475 #endif |
453 | 476 |
454 #if 0 | 477 #if 0 |
455 printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim); | 478 printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim); |
456 if (ti->tiargs->dim) | 479 if (ti->tiargs->dim) |
464 int variadic = isVariadic() != NULL; | 487 int variadic = isVariadic() != NULL; |
465 | 488 |
466 // If more arguments than parameters, no match | 489 // If more arguments than parameters, no match |
467 if (ti->tiargs->dim > parameters_dim && !variadic) | 490 if (ti->tiargs->dim > parameters_dim && !variadic) |
468 { | 491 { |
469 #if LOG | 492 #if LOGM |
470 printf(" no match: more arguments than parameters\n"); | 493 printf(" no match: more arguments than parameters\n"); |
471 #endif | 494 #endif |
472 return MATCHnomatch; | 495 return MATCHnomatch; |
473 } | 496 } |
474 | 497 |
487 { MATCH m2; | 510 { MATCH m2; |
488 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 511 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
489 Declaration *sparam; | 512 Declaration *sparam; |
490 | 513 |
491 //printf("\targument [%d]\n", i); | 514 //printf("\targument [%d]\n", i); |
492 #if 0 | 515 #if LOGM |
493 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); | 516 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); |
494 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); | 517 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); |
495 if (ttp) | 518 if (ttp) |
496 printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); | 519 printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); |
497 #endif | 520 #endif |
526 dedtypes->data[i] = ti->tiargs->data[i]; | 549 dedtypes->data[i] = ti->tiargs->data[i]; |
527 } | 550 } |
528 } | 551 } |
529 } | 552 } |
530 | 553 |
531 #if 0 | 554 #if LOGM |
532 // Print out the results | 555 // Print out the results |
533 printf("--------------------------\n"); | 556 printf("--------------------------\n"); |
534 printf("template %s\n", toChars()); | 557 printf("template %s\n", toChars()); |
535 printf("instance %s\n", ti->toChars()); | 558 printf("instance %s\n", ti->toChars()); |
536 if (m) | 559 if (m) |
551 } | 574 } |
552 else | 575 else |
553 goto Lnomatch; | 576 goto Lnomatch; |
554 #endif | 577 #endif |
555 | 578 |
556 #if LOG | 579 #if LOGM |
557 printf(" match = %d\n", m); | 580 printf(" match = %d\n", m); |
558 #endif | 581 #endif |
559 goto Lret; | 582 goto Lret; |
560 | 583 |
561 Lnomatch: | 584 Lnomatch: |
562 #if LOG | 585 #if LOGM |
563 printf(" no match\n"); | 586 printf(" no match\n"); |
564 #endif | 587 #endif |
565 m = MATCHnomatch; | 588 m = MATCHnomatch; |
566 | 589 |
567 Lret: | 590 Lret: |
568 paramscope->pop(); | 591 paramscope->pop(); |
569 #if LOG | 592 #if LOGM |
570 printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); | 593 printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); |
571 #endif | 594 #endif |
572 return m; | 595 return m; |
573 } | 596 } |
574 | 597 |
643 * Input: | 666 * Input: |
644 * targsi Expression/Type initial list of template arguments | 667 * targsi Expression/Type initial list of template arguments |
645 * fargs arguments to function | 668 * fargs arguments to function |
646 * Output: | 669 * Output: |
647 * dedargs Expression/Type deduced template arguments | 670 * dedargs Expression/Type deduced template arguments |
671 * Returns: | |
672 * match level | |
648 */ | 673 */ |
649 | 674 |
650 MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, | 675 MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, |
651 Objects *dedargs) | 676 Objects *dedargs) |
652 { | 677 { |
653 size_t i; | 678 size_t i; |
654 size_t nfparams; | 679 size_t nfparams; |
655 size_t nfparams2; | |
656 size_t nfargs; | 680 size_t nfargs; |
657 size_t nargsi; | 681 size_t nargsi; // array size of targsi |
682 int fptupindex = -1; | |
683 int tuple_dim = 0; | |
658 MATCH match = MATCHexact; | 684 MATCH match = MATCHexact; |
659 FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); | 685 FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); |
660 TypeFunction *fdtype; | 686 TypeFunction *fdtype; // type of fd |
661 TemplateTupleParameter *tp; | 687 TemplateTupleParameter *tp; |
662 Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T | 688 Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T |
663 | 689 |
664 #if 0 | 690 #if 0 |
665 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); | 691 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); |
680 // Set up scope for parameters | 706 // Set up scope for parameters |
681 ScopeDsymbol *paramsym = new ScopeDsymbol(); | 707 ScopeDsymbol *paramsym = new ScopeDsymbol(); |
682 paramsym->parent = scope->parent; | 708 paramsym->parent = scope->parent; |
683 Scope *paramscope = scope->push(paramsym); | 709 Scope *paramscope = scope->push(paramsym); |
684 | 710 |
711 tp = isVariadic(); | |
712 | |
685 nargsi = 0; | 713 nargsi = 0; |
686 if (targsi) | 714 if (targsi) |
687 { // Set initial template arguments | 715 { // Set initial template arguments |
688 | 716 |
689 nargsi = targsi->dim; | 717 nargsi = targsi->dim; |
690 if (nargsi > parameters->dim) | 718 if (nargsi > parameters->dim) |
691 goto Lnomatch; | 719 { if (!tp) |
720 goto Lnomatch; | |
721 dedargs->setDim(nargsi); | |
722 dedargs->zero(); | |
723 } | |
692 | 724 |
693 memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data)); | 725 memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data)); |
694 | 726 |
695 for (i = 0; i < nargsi; i++) | 727 for (i = 0; i < nargsi; i++) |
696 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 728 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
697 MATCH m; | 729 MATCH m; |
698 Declaration *sparam; | 730 Declaration *sparam; |
699 | 731 |
700 m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); | 732 m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); |
733 //printf("\tdeduceType m = %d\n", m); | |
701 if (m == MATCHnomatch) | 734 if (m == MATCHnomatch) |
702 goto Lnomatch; | 735 goto Lnomatch; |
703 if (m < match) | 736 if (m < match) |
704 match = m; | 737 match = m; |
705 | 738 |
711 | 744 |
712 assert(fd->type->ty == Tfunction); | 745 assert(fd->type->ty == Tfunction); |
713 fdtype = (TypeFunction *)fd->type; | 746 fdtype = (TypeFunction *)fd->type; |
714 | 747 |
715 nfparams = Argument::dim(fdtype->parameters); // number of function parameters | 748 nfparams = Argument::dim(fdtype->parameters); // number of function parameters |
716 nfparams2 = nfparams; | |
717 nfargs = fargs->dim; // number of function arguments | 749 nfargs = fargs->dim; // number of function arguments |
718 | 750 |
719 /* Check for match of function arguments with variadic template | 751 /* Check for match of function arguments with variadic template |
720 * parameter, such as: | 752 * parameter, such as: |
721 * | 753 * |
722 * template Foo(T, A...) { void Foo(T t, A a); } | 754 * template Foo(T, A...) { void Foo(T t, A a); } |
723 * void main() { Foo(1,2,3); } | 755 * void main() { Foo(1,2,3); } |
724 */ | 756 */ |
725 tp = isVariadic(); | 757 tp = isVariadic(); |
726 if (tp) | 758 if (tp) // if variadic |
727 { | 759 { |
728 if (nfparams == 0) // if no function parameters | 760 if (nfparams == 0) // if no function parameters |
729 { | 761 { |
730 Tuple *t = new Tuple(); | 762 Tuple *t = new Tuple(); |
731 //printf("t = %p\n", t); | 763 //printf("t = %p\n", t); |
734 } | 766 } |
735 else if (nfargs < nfparams - 1) | 767 else if (nfargs < nfparams - 1) |
736 goto L1; | 768 goto L1; |
737 else | 769 else |
738 { | 770 { |
739 /* See if 'A' of the template parameter matches 'A' | 771 /* Figure out which of the function parameters matches |
740 * of the type of the last function parameter. | 772 * the tuple template parameter. Do this by matching |
773 * type identifiers. | |
774 * Set the index of this function parameter to fptupindex. | |
741 */ | 775 */ |
742 Argument *fparam = (Argument *)fdtype->parameters->data[nfparams - 1]; | 776 for (fptupindex = 0; fptupindex < nfparams; fptupindex++) |
743 if (fparam->type->ty != Tident) | 777 { |
744 goto L1; | 778 Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex]; |
745 TypeIdentifier *tid = (TypeIdentifier *)fparam->type; | 779 if (fparam->type->ty != Tident) |
746 if (!tp->ident->equals(tid->ident) || tid->idents.dim) | 780 continue; |
747 goto L1; | 781 TypeIdentifier *tid = (TypeIdentifier *)fparam->type; |
748 | 782 if (!tp->ident->equals(tid->ident) || tid->idents.dim) |
749 if (fdtype->varargs) // variadic function doesn't | 783 continue; |
750 goto Lnomatch; // go with variadic template | 784 |
751 | 785 if (fdtype->varargs) // variadic function doesn't |
752 /* The types of the function arguments [nfparams - 1 .. nfargs] | 786 goto Lnomatch; // go with variadic template |
753 * now form the tuple argument. | 787 |
754 */ | 788 /* The types of the function arguments |
755 Tuple *t = new Tuple(); | 789 * now form the tuple argument. |
756 dedargs->data[parameters->dim - 1] = (void *)t; | 790 */ |
757 | 791 Tuple *t = new Tuple(); |
758 int tuple_dim = nfargs - (nfparams - 1); | 792 dedargs->data[parameters->dim - 1] = (void *)t; |
759 t->objects.setDim(tuple_dim); | 793 |
760 for (i = 0; i < tuple_dim; i++) | 794 tuple_dim = nfargs - (nfparams - 1); |
761 { Expression *farg = (Expression *)fargs->data[nfparams - 1 + i]; | 795 t->objects.setDim(tuple_dim); |
762 t->objects.data[i] = (void *)farg->type; | 796 for (i = 0; i < tuple_dim; i++) |
763 } | 797 { Expression *farg = (Expression *)fargs->data[fptupindex + i]; |
764 nfparams2--; // don't consider the last parameter for type deduction | 798 t->objects.data[i] = (void *)farg->type; |
765 goto L2; | 799 } |
800 goto L2; | |
801 } | |
802 fptupindex = -1; | |
766 } | 803 } |
767 } | 804 } |
768 | 805 |
769 L1: | 806 L1: |
770 if (nfparams == nfargs) | 807 if (nfparams == nfargs) |
776 match = MATCHconvert; // match ... with a conversion | 813 match = MATCHconvert; // match ... with a conversion |
777 } | 814 } |
778 | 815 |
779 L2: | 816 L2: |
780 // Loop through the function parameters | 817 // Loop through the function parameters |
781 for (i = 0; i < nfparams2; i++) | 818 for (i = 0; i < nfparams; i++) |
782 { | 819 { |
820 /* Skip over function parameters which wound up | |
821 * as part of a template tuple parameter. | |
822 */ | |
823 if (i == fptupindex) | |
824 { if (fptupindex == nfparams - 1) | |
825 break; | |
826 i += tuple_dim - 1; | |
827 continue; | |
828 } | |
829 | |
783 Argument *fparam = Argument::getNth(fdtype->parameters, i); | 830 Argument *fparam = Argument::getNth(fdtype->parameters, i); |
784 Expression *farg; | |
785 MATCH m; | |
786 | 831 |
787 if (i >= nfargs) // if not enough arguments | 832 if (i >= nfargs) // if not enough arguments |
788 { | 833 { |
789 if (fparam->defaultArg) | 834 if (fparam->defaultArg) |
790 { /* Default arguments do not participate in template argument | 835 { /* Default arguments do not participate in template argument |
792 */ | 837 */ |
793 goto Lmatch; | 838 goto Lmatch; |
794 } | 839 } |
795 } | 840 } |
796 else | 841 else |
797 { farg = (Expression *)fargs->data[i]; | 842 { Expression *farg = (Expression *)fargs->data[i]; |
798 #if 0 | 843 #if 0 |
799 printf("\tfarg->type = %s\n", farg->type->toChars()); | 844 printf("\tfarg->type = %s\n", farg->type->toChars()); |
800 printf("\tfparam->type = %s\n", fparam->type->toChars()); | 845 printf("\tfparam->type = %s\n", fparam->type->toChars()); |
801 #endif | 846 #endif |
802 | 847 |
848 MATCH m; | |
803 m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes); | 849 m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes); |
804 //printf("\tdeduceType m = %d\n", m); | 850 //printf("\tdeduceType m = %d\n", m); |
805 | 851 |
806 /* If no match, see if there's a conversion to a delegate | 852 /* If no match, see if there's a conversion to a delegate |
807 */ | 853 */ |
850 /* Fill in any missing arguments with their defaults. | 896 /* Fill in any missing arguments with their defaults. |
851 */ | 897 */ |
852 for (i = nargsi; i < dedargs->dim; i++) | 898 for (i = nargsi; i < dedargs->dim; i++) |
853 { | 899 { |
854 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 900 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
901 //printf("tp[%d] = %s\n", i, tp->ident->toChars()); | |
902 /* For T:T*, the dedargs is the T*, dedtypes is the T | |
903 * But for function templates, we really need them to match | |
904 */ | |
855 Object *oarg = (Object *)dedargs->data[i]; | 905 Object *oarg = (Object *)dedargs->data[i]; |
856 Object *o = (Object *)dedtypes.data[i]; | 906 Object *oded = (Object *)dedtypes.data[i]; |
857 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, o); | 907 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded); |
858 if (!oarg) | 908 if (!oarg) |
859 { | 909 { |
860 if (o) | 910 if (oded) |
861 { | 911 { |
862 if (tp->specialization()) | 912 if (tp->specialization()) |
863 error("specialization not allowed for deduced parameter %s", tp->ident->toChars()); | 913 { /* The specialization can work as long as afterwards |
914 * the oded == oarg | |
915 */ | |
916 Declaration *sparam; | |
917 dedargs->data[i] = (void *)oded; | |
918 MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); | |
919 //printf("m2 = %d\n", m2); | |
920 if (!m2) | |
921 goto Lnomatch; | |
922 if (m2 < match) | |
923 match = m2; // pick worst match | |
924 if (dedtypes.data[i] != oded) | |
925 error("specialization not allowed for deduced parameter %s", tp->ident->toChars()); | |
926 } | |
864 } | 927 } |
865 else | 928 else |
866 { o = tp->defaultArg(paramscope); | 929 { oded = tp->defaultArg(paramscope); |
867 if (!o) | 930 if (!oded) |
868 goto Lnomatch; | 931 goto Lnomatch; |
869 #if 0 | 932 } |
870 Match m; | 933 declareParameter(paramscope, tp, oded); |
871 Declaration *sparam; | 934 dedargs->data[i] = (void *)oded; |
872 m = tp->matchArg(paramscope, dedargs, i, parameters, &sparam); | |
873 if (!m) | |
874 goto Lnomatch; | |
875 #endif | |
876 } | |
877 declareParameter(paramscope, tp, o); | |
878 dedargs->data[i] = (void *)o; | |
879 } | 935 } |
880 } | 936 } |
881 | 937 |
882 #if 0 | 938 #if 0 |
883 for (i = 0; i < dedargs->dim; i++) | 939 for (i = 0; i < dedargs->dim; i++) |
885 printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars()); | 941 printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars()); |
886 } | 942 } |
887 #endif | 943 #endif |
888 | 944 |
889 paramscope->pop(); | 945 paramscope->pop(); |
890 //printf("\tmatch\n"); | 946 //printf("\tmatch %d\n", match); |
891 return match; | 947 return match; |
892 | 948 |
893 Lnomatch: | 949 Lnomatch: |
894 paramscope->pop(); | 950 paramscope->pop(); |
895 //printf("\tnomatch\n"); | 951 //printf("\tnomatch\n"); |
1042 // Disambiguate by picking the most specialized TemplateDeclaration | 1098 // Disambiguate by picking the most specialized TemplateDeclaration |
1043 int c1 = td->leastAsSpecialized(td_best); | 1099 int c1 = td->leastAsSpecialized(td_best); |
1044 int c2 = td_best->leastAsSpecialized(td); | 1100 int c2 = td_best->leastAsSpecialized(td); |
1045 //printf("c1 = %d, c2 = %d\n", c1, c2); | 1101 //printf("c1 = %d, c2 = %d\n", c1, c2); |
1046 | 1102 |
1047 if (c1 && !c2) | 1103 if (c1 > c2) |
1048 goto Ltd; | 1104 goto Ltd; |
1049 else if (!c1 && c2) | 1105 else if (c1 < c2) |
1050 goto Ltd_best; | 1106 goto Ltd_best; |
1051 else | 1107 else |
1052 goto Lambig; | 1108 goto Lambig; |
1053 } | 1109 } |
1054 | 1110 |
1114 buf->writestring(ident->toChars()); | 1170 buf->writestring(ident->toChars()); |
1115 buf->writeByte('('); | 1171 buf->writeByte('('); |
1116 for (int i = 0; i < parameters->dim; i++) | 1172 for (int i = 0; i < parameters->dim; i++) |
1117 { | 1173 { |
1118 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 1174 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
1175 if (hgs->ddoc) | |
1176 tp = (TemplateParameter *)origParameters->data[i]; | |
1119 if (i) | 1177 if (i) |
1120 buf->writeByte(','); | 1178 buf->writeByte(','); |
1121 tp->toCBuffer(buf, hgs); | 1179 tp->toCBuffer(buf, hgs); |
1122 } | 1180 } |
1123 buf->writeByte(')'); | 1181 buf->writeByte(')'); |
1514 /* Handle case of: | 1572 /* Handle case of: |
1515 * template Foo(T : sa!(T), alias sa) | 1573 * template Foo(T : sa!(T), alias sa) |
1516 */ | 1574 */ |
1517 int i = templateIdentifierLookup(tp->tempinst->name, parameters); | 1575 int i = templateIdentifierLookup(tp->tempinst->name, parameters); |
1518 if (i == -1) | 1576 if (i == -1) |
1577 { /* Didn't find it as a parameter identifier. Try looking | |
1578 * it up and seeing if is an alias. See Bugzilla 1454 | |
1579 */ | |
1580 Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL); | |
1581 if (s) | |
1582 { | |
1583 s = s->toAlias(); | |
1584 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
1585 if (td && td == tempinst->tempdecl) | |
1586 goto L2; | |
1587 } | |
1519 goto Lnomatch; | 1588 goto Lnomatch; |
1589 } | |
1520 TemplateParameter *tpx = (TemplateParameter *)parameters->data[i]; | 1590 TemplateParameter *tpx = (TemplateParameter *)parameters->data[i]; |
1521 // This logic duplicates tpx->matchArg() | 1591 // This logic duplicates tpx->matchArg() |
1522 TemplateAliasParameter *ta = tpx->isTemplateAliasParameter(); | 1592 TemplateAliasParameter *ta = tpx->isTemplateAliasParameter(); |
1523 if (!ta) | 1593 if (!ta) |
1524 goto Lnomatch; | 1594 goto Lnomatch; |
1538 } | 1608 } |
1539 } | 1609 } |
1540 else if (tempinst->tempdecl != tp->tempinst->tempdecl) | 1610 else if (tempinst->tempdecl != tp->tempinst->tempdecl) |
1541 goto Lnomatch; | 1611 goto Lnomatch; |
1542 | 1612 |
1613 L2: | |
1543 if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) | 1614 if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) |
1544 goto Lnomatch; | 1615 goto Lnomatch; |
1545 | 1616 |
1546 for (int i = 0; i < tempinst->tiargs->dim; i++) | 1617 for (int i = 0; i < tempinst->tiargs->dim; i++) |
1547 { | 1618 { |
1548 //printf("test: [%d]\n", i); | 1619 //printf("\ttest: tempinst->tiargs[%d]\n", i); |
1620 int j; | |
1549 Object *o1 = (Object *)tempinst->tiargs->data[i]; | 1621 Object *o1 = (Object *)tempinst->tiargs->data[i]; |
1550 Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; | 1622 Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; |
1551 | 1623 |
1552 Type *t1 = isType(o1); | 1624 Type *t1 = isType(o1); |
1553 Type *t2 = isType(o2); | 1625 Type *t2 = isType(o2); |
1568 goto Lnomatch; | 1640 goto Lnomatch; |
1569 } | 1641 } |
1570 else if (e1 && e2) | 1642 else if (e1 && e2) |
1571 { | 1643 { |
1572 if (!e1->equals(e2)) | 1644 if (!e1->equals(e2)) |
1645 { if (e2->op == TOKvar) | |
1646 { | |
1647 /* | |
1648 * (T:Number!(e2), int e2) | |
1649 */ | |
1650 j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters); | |
1651 goto L1; | |
1652 } | |
1573 goto Lnomatch; | 1653 goto Lnomatch; |
1654 } | |
1574 } | 1655 } |
1575 else if (e1 && t2 && t2->ty == Tident) | 1656 else if (e1 && t2 && t2->ty == Tident) |
1576 { int i = templateParameterLookup(t2, parameters); | 1657 { |
1577 if (i == -1) | 1658 j = templateParameterLookup(t2, parameters); |
1659 L1: | |
1660 if (j == -1) | |
1578 goto Lnomatch; | 1661 goto Lnomatch; |
1579 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | 1662 TemplateParameter *tp = (TemplateParameter *)parameters->data[j]; |
1580 // BUG: use tp->matchArg() instead of the following | 1663 // BUG: use tp->matchArg() instead of the following |
1581 TemplateValueParameter *tv = tp->isTemplateValueParameter(); | 1664 TemplateValueParameter *tv = tp->isTemplateValueParameter(); |
1582 if (!tv) | 1665 if (!tv) |
1583 goto Lnomatch; | 1666 goto Lnomatch; |
1584 Expression *e = (Expression *)dedtypes->data[i]; | 1667 Expression *e = (Expression *)dedtypes->data[j]; |
1585 if (e) | 1668 if (e) |
1586 { | 1669 { |
1587 if (!e1->equals(e)) | 1670 if (!e1->equals(e)) |
1588 goto Lnomatch; | 1671 goto Lnomatch; |
1589 } | 1672 } |
1590 else | 1673 else |
1591 { Type *vt = tv->valType->semantic(0, sc); | 1674 { Type *vt = tv->valType->semantic(0, sc); |
1592 MATCH m = (MATCH)e1->implicitConvTo(vt); | 1675 MATCH m = (MATCH)e1->implicitConvTo(vt); |
1593 if (!m) | 1676 if (!m) |
1594 goto Lnomatch; | 1677 goto Lnomatch; |
1595 dedtypes->data[i] = e1; | 1678 dedtypes->data[j] = e1; |
1596 } | 1679 } |
1597 } | 1680 } |
1598 // BUG: Need to handle alias and tuple parameters | 1681 // BUG: Need to handle alias and tuple parameters |
1599 else | 1682 else |
1600 goto Lnomatch; | 1683 goto Lnomatch; |
2349 sparam->storage_class = STCconst; | 2432 sparam->storage_class = STCconst; |
2350 *psparam = sparam; | 2433 *psparam = sparam; |
2351 return m; | 2434 return m; |
2352 | 2435 |
2353 Lnomatch: | 2436 Lnomatch: |
2437 //printf("\tno match\n"); | |
2354 *psparam = NULL; | 2438 *psparam = NULL; |
2355 return MATCHnomatch; | 2439 return MATCHnomatch; |
2356 } | 2440 } |
2357 | 2441 |
2358 | 2442 |
2778 //printf("\t2: adding to module %s\n", m->toChars()); | 2862 //printf("\t2: adding to module %s\n", m->toChars()); |
2779 a = m->members; | 2863 a = m->members; |
2780 if (m->semanticdone >= 3) | 2864 if (m->semanticdone >= 3) |
2781 dosemantic3 = 1; | 2865 dosemantic3 = 1; |
2782 } | 2866 } |
2783 for (i = 0; 1; i++) | 2867 for (int i = 0; 1; i++) |
2784 { | 2868 { |
2785 if (i == a->dim) | 2869 if (i == a->dim) |
2786 { | 2870 { |
2787 a->push(this); | 2871 a->push(this); |
2788 break; | 2872 break; |
2951 Object *o = (Object *)tiargs->data[j]; | 3035 Object *o = (Object *)tiargs->data[j]; |
2952 Type *ta = isType(o); | 3036 Type *ta = isType(o); |
2953 Expression *ea = isExpression(o); | 3037 Expression *ea = isExpression(o); |
2954 Dsymbol *sa = isDsymbol(o); | 3038 Dsymbol *sa = isDsymbol(o); |
2955 | 3039 |
2956 //printf("1: tiargs->data[%d] = %p, %p, %p\n", j, o, isDsymbol(o), isTuple(o)); | 3040 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta); |
2957 if (ta) | 3041 if (ta) |
2958 { | 3042 { |
2959 //printf("type %s\n", ta->toChars()); | 3043 //printf("type %s\n", ta->toChars()); |
2960 // It might really be an Expression or an Alias | 3044 // It might really be an Expression or an Alias |
2961 ta->resolve(loc, sc, &ea, &ta, &sa); | 3045 ta->resolve(loc, sc, &ea, &ta, &sa); |
3194 // Disambiguate by picking the most specialized TemplateDeclaration | 3278 // Disambiguate by picking the most specialized TemplateDeclaration |
3195 int c1 = td->leastAsSpecialized(td_best); | 3279 int c1 = td->leastAsSpecialized(td_best); |
3196 int c2 = td_best->leastAsSpecialized(td); | 3280 int c2 = td_best->leastAsSpecialized(td); |
3197 //printf("c1 = %d, c2 = %d\n", c1, c2); | 3281 //printf("c1 = %d, c2 = %d\n", c1, c2); |
3198 | 3282 |
3199 if (c1 && !c2) | 3283 if (c1 > c2) |
3200 goto Ltd; | 3284 goto Ltd; |
3201 else if (!c1 && c2) | 3285 else if (c1 < c2) |
3202 goto Ltd_best; | 3286 goto Ltd_best; |
3203 else | 3287 else |
3204 goto Lambig; | 3288 goto Lambig; |
3205 } | 3289 } |
3206 | 3290 |
3303 (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && | 3387 (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && |
3304 !isTemplateMixin()) | 3388 !isTemplateMixin()) |
3305 { | 3389 { |
3306 // if module level template | 3390 // if module level template |
3307 if (tempdecl->toParent()->isModule()) | 3391 if (tempdecl->toParent()->isModule()) |
3308 { | 3392 { Dsymbol *dparent = d->toParent(); |
3309 if (isnested && isnested != d->toParent()) | 3393 if (!isnested) |
3310 error("inconsistent nesting levels %s and %s", isnested->toChars(), d->toParent()->toChars()); | 3394 isnested = dparent; |
3311 isnested = d->toParent(); | 3395 else if (isnested != dparent) |
3396 { | |
3397 /* Select the more deeply nested of the two. | |
3398 * Error if one is not nested inside the other. | |
3399 */ | |
3400 for (Dsymbol *p = isnested; p; p = p->parent) | |
3401 { | |
3402 if (p == dparent) | |
3403 goto L1; // isnested is most nested | |
3404 } | |
3405 for (Dsymbol *p = dparent; 1; p = p->parent) | |
3406 { | |
3407 if (p == isnested) | |
3408 { isnested = dparent; | |
3409 goto L1; // dparent is most nested | |
3410 } | |
3411 } | |
3412 error("is nested in both %s and %s", isnested->toChars(), dparent->toChars()); | |
3413 } | |
3414 L1: | |
3415 //printf("\tnested inside %s\n", isnested->toChars()); | |
3312 nested |= 1; | 3416 nested |= 1; |
3313 } | 3417 } |
3314 else | 3418 else |
3315 error("cannot use local '%s' as template parameter", d->toChars()); | 3419 error("cannot use local '%s' as template parameter", d->toChars()); |
3316 } | 3420 } |