Mercurial > projects > ldc
annotate dmd/opover.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | cbd6c8073a32 |
children | 330f999ade44 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <ctype.h> | |
14 #include <assert.h> | |
15 #include <complex> | |
16 | |
17 #ifdef __APPLE__ | |
18 #define integer_t dmd_integer_t | |
19 #endif | |
20 | |
21 #if IN_GCC || IN_LLVM | |
22 #include "mem.h" | |
571
cbd6c8073a32
Changed all '#if linux || __APPLE__' to '#if POSIX' so we can support other platforms too, thanx for the suggestion anders.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
535
diff
changeset
|
23 #elif POSIX |
1 | 24 #include "../root/mem.h" |
25 #elif _WIN32 | |
26 #include "..\root\mem.h" | |
27 #endif | |
28 | |
29 //#include "port.h" | |
30 #include "mtype.h" | |
31 #include "init.h" | |
32 #include "expression.h" | |
33 #include "id.h" | |
34 #include "declaration.h" | |
35 #include "aggregate.h" | |
36 #include "template.h" | |
37 | |
38 static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id); | |
39 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments); | |
40 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments); | |
41 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments); | |
42 | |
43 /******************************** Expression **************************/ | |
44 | |
45 | |
46 /*********************************** | |
47 * Determine if operands of binary op can be reversed | |
48 * to fit operator overload. | |
49 */ | |
50 | |
51 int Expression::isCommutative() | |
52 { | |
53 return FALSE; // default is no reverse | |
54 } | |
55 | |
56 /*********************************** | |
57 * Get Identifier for operator overload. | |
58 */ | |
59 | |
60 Identifier *Expression::opId() | |
61 { | |
62 assert(0); | |
63 return NULL; | |
64 } | |
65 | |
66 /*********************************** | |
67 * Get Identifier for reverse operator overload, | |
68 * NULL if not supported for this operator. | |
69 */ | |
70 | |
71 Identifier *Expression::opId_r() | |
72 { | |
73 return NULL; | |
74 } | |
75 | |
76 /************************* Operators *****************************/ | |
77 | |
78 Identifier *UAddExp::opId() { return Id::uadd; } | |
79 | |
80 Identifier *NegExp::opId() { return Id::neg; } | |
81 | |
82 Identifier *ComExp::opId() { return Id::com; } | |
83 | |
84 Identifier *CastExp::opId() { return Id::cast; } | |
85 | |
86 Identifier *InExp::opId() { return Id::opIn; } | |
87 Identifier *InExp::opId_r() { return Id::opIn_r; } | |
88 | |
89 Identifier *PostExp::opId() { return (op == TOKplusplus) | |
90 ? Id::postinc | |
91 : Id::postdec; } | |
92 | |
93 int AddExp::isCommutative() { return TRUE; } | |
94 Identifier *AddExp::opId() { return Id::add; } | |
95 Identifier *AddExp::opId_r() { return Id::add_r; } | |
96 | |
97 Identifier *MinExp::opId() { return Id::sub; } | |
98 Identifier *MinExp::opId_r() { return Id::sub_r; } | |
99 | |
100 int MulExp::isCommutative() { return TRUE; } | |
101 Identifier *MulExp::opId() { return Id::mul; } | |
102 Identifier *MulExp::opId_r() { return Id::mul_r; } | |
103 | |
104 Identifier *DivExp::opId() { return Id::div; } | |
105 Identifier *DivExp::opId_r() { return Id::div_r; } | |
106 | |
107 Identifier *ModExp::opId() { return Id::mod; } | |
108 Identifier *ModExp::opId_r() { return Id::mod_r; } | |
109 | |
110 Identifier *ShlExp::opId() { return Id::shl; } | |
111 Identifier *ShlExp::opId_r() { return Id::shl_r; } | |
112 | |
113 Identifier *ShrExp::opId() { return Id::shr; } | |
114 Identifier *ShrExp::opId_r() { return Id::shr_r; } | |
115 | |
116 Identifier *UshrExp::opId() { return Id::ushr; } | |
117 Identifier *UshrExp::opId_r() { return Id::ushr_r; } | |
118 | |
119 int AndExp::isCommutative() { return TRUE; } | |
120 Identifier *AndExp::opId() { return Id::iand; } | |
121 Identifier *AndExp::opId_r() { return Id::iand_r; } | |
122 | |
123 int OrExp::isCommutative() { return TRUE; } | |
124 Identifier *OrExp::opId() { return Id::ior; } | |
125 Identifier *OrExp::opId_r() { return Id::ior_r; } | |
126 | |
127 int XorExp::isCommutative() { return TRUE; } | |
128 Identifier *XorExp::opId() { return Id::ixor; } | |
129 Identifier *XorExp::opId_r() { return Id::ixor_r; } | |
130 | |
131 Identifier *CatExp::opId() { return Id::cat; } | |
132 Identifier *CatExp::opId_r() { return Id::cat_r; } | |
133 | |
134 Identifier * AssignExp::opId() { return Id::assign; } | |
135 Identifier * AddAssignExp::opId() { return Id::addass; } | |
136 Identifier * MinAssignExp::opId() { return Id::subass; } | |
137 Identifier * MulAssignExp::opId() { return Id::mulass; } | |
138 Identifier * DivAssignExp::opId() { return Id::divass; } | |
139 Identifier * ModAssignExp::opId() { return Id::modass; } | |
140 Identifier * AndAssignExp::opId() { return Id::andass; } | |
141 Identifier * OrAssignExp::opId() { return Id::orass; } | |
142 Identifier * XorAssignExp::opId() { return Id::xorass; } | |
143 Identifier * ShlAssignExp::opId() { return Id::shlass; } | |
144 Identifier * ShrAssignExp::opId() { return Id::shrass; } | |
145 Identifier *UshrAssignExp::opId() { return Id::ushrass; } | |
146 Identifier * CatAssignExp::opId() { return Id::catass; } | |
147 | |
148 int EqualExp::isCommutative() { return TRUE; } | |
149 Identifier *EqualExp::opId() { return Id::eq; } | |
150 | |
151 int CmpExp::isCommutative() { return TRUE; } | |
152 Identifier *CmpExp::opId() { return Id::cmp; } | |
153 | |
154 Identifier *ArrayExp::opId() { return Id::index; } | |
155 | |
156 | |
157 /************************************ | |
158 * Operator overload. | |
159 * Check for operator overload, if so, replace | |
160 * with function call. | |
161 * Return NULL if not an operator overload. | |
162 */ | |
163 | |
164 Expression *UnaExp::op_overload(Scope *sc) | |
165 { | |
166 AggregateDeclaration *ad; | |
167 Dsymbol *fd; | |
168 Type *t1 = e1->type->toBasetype(); | |
169 | |
170 if (t1->ty == Tclass) | |
171 { | |
172 ad = ((TypeClass *)t1)->sym; | |
173 goto L1; | |
174 } | |
175 else if (t1->ty == Tstruct) | |
176 { | |
177 ad = ((TypeStruct *)t1)->sym; | |
178 | |
179 L1: | |
180 fd = search_function(ad, opId()); | |
181 if (fd) | |
182 { | |
183 if (op == TOKarray) | |
184 { | |
185 Expression *e; | |
186 ArrayExp *ae = (ArrayExp *)this; | |
187 | |
188 e = new DotIdExp(loc, e1, fd->ident); | |
189 e = new CallExp(loc, e, ae->arguments); | |
190 e = e->semantic(sc); | |
191 return e; | |
192 } | |
193 else | |
194 { | |
195 // Rewrite +e1 as e1.add() | |
196 return build_overload(loc, sc, e1, NULL, fd->ident); | |
197 } | |
198 } | |
199 } | |
200 return NULL; | |
201 } | |
202 | |
203 | |
204 Expression *BinExp::op_overload(Scope *sc) | |
205 { | |
206 //printf("BinExp::op_overload() (%s)\n", toChars()); | |
207 | |
208 AggregateDeclaration *ad; | |
209 Type *t1 = e1->type->toBasetype(); | |
210 Type *t2 = e2->type->toBasetype(); | |
211 Identifier *id = opId(); | |
212 Identifier *id_r = opId_r(); | |
213 | |
214 Match m; | |
215 Expressions args1; | |
216 Expressions args2; | |
217 int argsset = 0; | |
218 | |
219 AggregateDeclaration *ad1; | |
220 if (t1->ty == Tclass) | |
221 ad1 = ((TypeClass *)t1)->sym; | |
222 else if (t1->ty == Tstruct) | |
223 ad1 = ((TypeStruct *)t1)->sym; | |
224 else | |
225 ad1 = NULL; | |
226 | |
227 AggregateDeclaration *ad2; | |
228 if (t2->ty == Tclass) | |
229 ad2 = ((TypeClass *)t2)->sym; | |
230 else if (t2->ty == Tstruct) | |
231 ad2 = ((TypeStruct *)t2)->sym; | |
232 else | |
233 ad2 = NULL; | |
234 | |
235 Dsymbol *s = NULL; | |
236 Dsymbol *s_r = NULL; | |
237 FuncDeclaration *fd = NULL; | |
238 TemplateDeclaration *td = NULL; | |
239 if (ad1 && id) | |
240 { | |
241 s = search_function(ad1, id); | |
242 } | |
243 if (ad2 && id_r) | |
244 { | |
245 s_r = search_function(ad2, id_r); | |
246 } | |
247 | |
248 if (s || s_r) | |
249 { | |
250 /* Try: | |
251 * a.opfunc(b) | |
252 * b.opfunc_r(a) | |
253 * and see which is better. | |
254 */ | |
255 Expression *e; | |
256 FuncDeclaration *lastf; | |
257 | |
258 args1.setDim(1); | |
259 args1.data[0] = (void*) e1; | |
260 args2.setDim(1); | |
261 args2.data[0] = (void*) e2; | |
262 argsset = 1; | |
263 | |
264 memset(&m, 0, sizeof(m)); | |
265 m.last = MATCHnomatch; | |
266 | |
267 if (s) | |
268 { | |
269 fd = s->isFuncDeclaration(); | |
270 if (fd) | |
271 { | |
272 overloadResolveX(&m, fd, &args2); | |
273 } | |
274 else | |
275 { td = s->isTemplateDeclaration(); | |
276 templateResolve(&m, td, sc, loc, NULL, &args2); | |
277 } | |
278 } | |
279 | |
280 lastf = m.lastf; | |
281 | |
282 if (s_r) | |
283 { | |
284 fd = s_r->isFuncDeclaration(); | |
285 if (fd) | |
286 { | |
287 overloadResolveX(&m, fd, &args1); | |
288 } | |
289 else | |
290 { td = s_r->isTemplateDeclaration(); | |
291 templateResolve(&m, td, sc, loc, NULL, &args1); | |
292 } | |
293 } | |
294 | |
295 if (m.count > 1) | |
296 { | |
297 // Error, ambiguous | |
298 error("overloads %s and %s both match argument list for %s", | |
299 m.lastf->type->toChars(), | |
300 m.nextf->type->toChars(), | |
301 m.lastf->toChars()); | |
302 } | |
303 else if (m.last == MATCHnomatch) | |
304 { | |
305 m.lastf = m.anyf; | |
306 } | |
307 | |
308 if (op == TOKplusplus || op == TOKminusminus) | |
309 // Kludge because operator overloading regards e++ and e-- | |
310 // as unary, but it's implemented as a binary. | |
311 // Rewrite (e1 ++ e2) as e1.postinc() | |
312 // Rewrite (e1 -- e2) as e1.postdec() | |
313 e = build_overload(loc, sc, e1, NULL, id); | |
314 else if (lastf && m.lastf == lastf || m.last == MATCHnomatch) | |
315 // Rewrite (e1 op e2) as e1.opfunc(e2) | |
316 e = build_overload(loc, sc, e1, e2, id); | |
317 else | |
318 // Rewrite (e1 op e2) as e2.opfunc_r(e1) | |
319 e = build_overload(loc, sc, e2, e1, id_r); | |
320 return e; | |
321 } | |
322 | |
323 if (isCommutative()) | |
324 { | |
325 s = NULL; | |
326 s_r = NULL; | |
327 if (ad1 && id_r) | |
328 { | |
329 s_r = search_function(ad1, id_r); | |
330 } | |
331 if (ad2 && id) | |
332 { | |
333 s = search_function(ad2, id); | |
334 } | |
335 | |
336 if (s || s_r) | |
337 { | |
338 /* Try: | |
339 * a.opfunc_r(b) | |
340 * b.opfunc(a) | |
341 * and see which is better. | |
342 */ | |
343 Expression *e; | |
344 FuncDeclaration *lastf; | |
345 | |
346 if (!argsset) | |
347 { args1.setDim(1); | |
348 args1.data[0] = (void*) e1; | |
349 args2.setDim(1); | |
350 args2.data[0] = (void*) e2; | |
351 } | |
352 | |
353 memset(&m, 0, sizeof(m)); | |
354 m.last = MATCHnomatch; | |
355 | |
356 if (s_r) | |
357 { | |
358 fd = s_r->isFuncDeclaration(); | |
359 if (fd) | |
360 { | |
361 overloadResolveX(&m, fd, &args2); | |
362 } | |
363 else | |
364 { td = s_r->isTemplateDeclaration(); | |
365 templateResolve(&m, td, sc, loc, NULL, &args2); | |
366 } | |
367 } | |
368 lastf = m.lastf; | |
369 | |
370 if (s) | |
371 { | |
372 fd = s->isFuncDeclaration(); | |
373 if (fd) | |
374 { | |
375 overloadResolveX(&m, fd, &args1); | |
376 } | |
377 else | |
378 { td = s->isTemplateDeclaration(); | |
379 templateResolve(&m, td, sc, loc, NULL, &args1); | |
380 } | |
381 } | |
382 | |
383 if (m.count > 1) | |
384 { | |
385 // Error, ambiguous | |
386 error("overloads %s and %s both match argument list for %s", | |
387 m.lastf->type->toChars(), | |
388 m.nextf->type->toChars(), | |
389 m.lastf->toChars()); | |
390 } | |
391 else if (m.last == MATCHnomatch) | |
392 { | |
393 m.lastf = m.anyf; | |
394 } | |
395 | |
396 if (lastf && m.lastf == lastf || | |
397 id_r && m.last == MATCHnomatch) | |
398 // Rewrite (e1 op e2) as e1.opfunc_r(e2) | |
399 e = build_overload(loc, sc, e1, e2, id_r); | |
400 else | |
401 // Rewrite (e1 op e2) as e2.opfunc(e1) | |
402 e = build_overload(loc, sc, e2, e1, id); | |
403 | |
404 // When reversing operands of comparison operators, | |
405 // need to reverse the sense of the op | |
406 switch (op) | |
407 { | |
408 case TOKlt: op = TOKgt; break; | |
409 case TOKgt: op = TOKlt; break; | |
410 case TOKle: op = TOKge; break; | |
411 case TOKge: op = TOKle; break; | |
412 | |
413 // Floating point compares | |
414 case TOKule: op = TOKuge; break; | |
415 case TOKul: op = TOKug; break; | |
416 case TOKuge: op = TOKule; break; | |
417 case TOKug: op = TOKul; break; | |
418 | |
419 // These are symmetric | |
420 case TOKunord: | |
421 case TOKlg: | |
422 case TOKleg: | |
423 case TOKue: | |
424 break; | |
425 } | |
426 | |
427 return e; | |
428 } | |
429 } | |
430 | |
431 return NULL; | |
432 } | |
433 | |
434 /*********************************** | |
435 * Utility to build a function call out of this reference and argument. | |
436 */ | |
437 | |
438 static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id) | |
439 { | |
440 Expression *e; | |
441 | |
442 //printf("build_overload(id = '%s')\n", id->toChars()); | |
443 //earg->print(); | |
444 //earg->type->print(); | |
445 e = new DotIdExp(loc, ethis, id); | |
446 | |
447 if (earg) | |
448 e = new CallExp(loc, e, earg); | |
449 else | |
450 e = new CallExp(loc, e); | |
451 | |
452 e = e->semantic(sc); | |
453 return e; | |
454 } | |
455 | |
456 /*************************************** | |
457 * Search for function funcid in aggregate ad. | |
458 */ | |
459 | |
460 Dsymbol *search_function(AggregateDeclaration *ad, Identifier *funcid) | |
461 { | |
462 Dsymbol *s; | |
463 FuncDeclaration *fd; | |
464 TemplateDeclaration *td; | |
465 | |
466 s = ad->search(0, funcid, 0); | |
467 if (s) | |
468 { Dsymbol *s2; | |
469 | |
470 //printf("search_function: s = '%s'\n", s->kind()); | |
471 s2 = s->toAlias(); | |
472 //printf("search_function: s2 = '%s'\n", s2->kind()); | |
473 fd = s2->isFuncDeclaration(); | |
474 if (fd && fd->type->ty == Tfunction) | |
475 return fd; | |
476 | |
477 td = s2->isTemplateDeclaration(); | |
478 if (td) | |
479 return td; | |
480 } | |
481 return NULL; | |
482 } | |
483 | |
484 | |
485 /***************************************** | |
486 * Given array of arguments and an aggregate type, | |
487 * if any of the argument types are missing, attempt to infer | |
488 * them from the aggregate type. | |
489 */ | |
490 | |
491 void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr) | |
492 { | |
493 if (!arguments || !arguments->dim) | |
494 return; | |
495 | |
496 /* Return if no arguments need types. | |
497 */ | |
498 for (size_t u = 0; 1; u++) | |
499 { if (u == arguments->dim) | |
500 return; | |
501 Argument *arg = (Argument *)arguments->data[u]; | |
502 if (!arg->type) | |
503 break; | |
504 } | |
505 | |
506 AggregateDeclaration *ad; | |
507 FuncDeclaration *fd; | |
508 | |
509 Argument *arg = (Argument *)arguments->data[0]; | |
510 Type *taggr = aggr->type; | |
511 if (!taggr) | |
512 return; | |
513 Type *tab = taggr->toBasetype(); | |
514 switch (tab->ty) | |
515 { | |
516 case Tarray: | |
517 case Tsarray: | |
518 case Ttuple: | |
519 if (arguments->dim == 2) | |
520 { | |
521 if (!arg->type) | |
522 arg->type = Type::tsize_t; // key type | |
523 arg = (Argument *)arguments->data[1]; | |
524 } | |
525 if (!arg->type && tab->ty != Ttuple) | |
526 arg->type = tab->nextOf(); // value type | |
527 break; | |
528 | |
529 case Taarray: | |
530 { TypeAArray *taa = (TypeAArray *)tab; | |
531 | |
532 if (arguments->dim == 2) | |
533 { | |
534 if (!arg->type) | |
535 arg->type = taa->index; // key type | |
536 arg = (Argument *)arguments->data[1]; | |
537 } | |
538 if (!arg->type) | |
539 arg->type = taa->next; // value type | |
540 break; | |
541 } | |
542 | |
543 case Tclass: | |
544 ad = ((TypeClass *)tab)->sym; | |
545 goto Laggr; | |
546 | |
547 case Tstruct: | |
548 ad = ((TypeStruct *)tab)->sym; | |
549 goto Laggr; | |
550 | |
551 Laggr: | |
552 #if 0 | |
553 if (arguments->dim == 1) | |
554 { | |
555 if (!arg->type) | |
556 { | |
557 /* Look for an opNext() overload | |
558 */ | |
559 Dsymbol *s = search_function(ad, Id::next); | |
560 fd = s ? s->isFuncDeclaration() : NULL; | |
561 if (!fd) | |
562 goto Lapply; | |
563 arg->type = fd->type->next; | |
564 } | |
565 break; | |
566 } | |
567 #endif | |
568 Lapply: | |
569 { /* Look for an | |
570 * int opApply(int delegate(ref Type [, ...]) dg); | |
571 * overload | |
572 */ | |
573 Dsymbol *s = search_function(ad, | |
574 (op == TOKforeach_reverse) ? Id::applyReverse | |
575 : Id::apply); | |
576 if (s) | |
577 { | |
578 fd = s->isFuncDeclaration(); | |
579 if (fd) | |
580 inferApplyArgTypesX(fd, arguments); | |
581 } | |
582 break; | |
583 } | |
584 | |
585 case Tdelegate: | |
586 { | |
587 if (0 && aggr->op == TOKdelegate) | |
588 { DelegateExp *de = (DelegateExp *)aggr; | |
589 | |
590 fd = de->func->isFuncDeclaration(); | |
591 if (fd) | |
592 inferApplyArgTypesX(fd, arguments); | |
593 } | |
594 else | |
595 { | |
596 inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments); | |
597 } | |
598 break; | |
599 } | |
600 | |
601 default: | |
602 break; // ignore error, caught later | |
603 } | |
604 } | |
605 | |
606 /******************************** | |
607 * Recursive helper function, | |
608 * analogous to func.overloadResolveX(). | |
609 */ | |
610 | |
611 int fp3(void *param, FuncDeclaration *f) | |
612 { | |
613 Arguments *arguments = (Arguments *)param; | |
614 TypeFunction *tf = (TypeFunction *)f->type; | |
615 if (inferApplyArgTypesY(tf, arguments) == 1) | |
616 return 0; | |
617 if (arguments->dim == 0) | |
618 return 1; | |
619 return 0; | |
620 } | |
621 | |
622 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments) | |
623 { | |
624 overloadApply(fstart, &fp3, arguments); | |
625 } | |
626 | |
627 #if 0 | |
628 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments) | |
629 { | |
630 Declaration *d; | |
631 Declaration *next; | |
632 | |
633 for (d = fstart; d; d = next) | |
634 { | |
635 FuncDeclaration *f; | |
636 FuncAliasDeclaration *fa; | |
637 AliasDeclaration *a; | |
638 | |
639 fa = d->isFuncAliasDeclaration(); | |
640 if (fa) | |
641 { | |
642 inferApplyArgTypesX(fa->funcalias, arguments); | |
643 next = fa->overnext; | |
644 } | |
645 else if ((f = d->isFuncDeclaration()) != NULL) | |
646 { | |
647 next = f->overnext; | |
648 | |
649 TypeFunction *tf = (TypeFunction *)f->type; | |
650 if (inferApplyArgTypesY(tf, arguments) == 1) | |
651 continue; | |
652 if (arguments->dim == 0) | |
653 return; | |
654 } | |
655 else if ((a = d->isAliasDeclaration()) != NULL) | |
656 { | |
657 Dsymbol *s = a->toAlias(); | |
658 next = s->isDeclaration(); | |
659 if (next == a) | |
660 break; | |
661 if (next == fstart) | |
662 break; | |
663 } | |
664 else | |
665 { d->error("is aliased to a function"); | |
666 break; | |
667 } | |
668 } | |
669 } | |
670 #endif | |
671 | |
672 /****************************** | |
673 * Infer arguments from type of function. | |
674 * Returns: | |
675 * 0 match for this function | |
676 * 1 no match for this function | |
677 */ | |
678 | |
679 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments) | |
680 { size_t nparams; | |
681 Argument *p; | |
682 | |
683 if (Argument::dim(tf->parameters) != 1) | |
684 goto Lnomatch; | |
685 p = Argument::getNth(tf->parameters, 0); | |
686 if (p->type->ty != Tdelegate) | |
687 goto Lnomatch; | |
688 tf = (TypeFunction *)p->type->nextOf(); | |
689 assert(tf->ty == Tfunction); | |
690 | |
691 /* We now have tf, the type of the delegate. Match it against | |
692 * the arguments, filling in missing argument types. | |
693 */ | |
694 nparams = Argument::dim(tf->parameters); | |
695 if (nparams == 0 || tf->varargs) | |
696 goto Lnomatch; // not enough parameters | |
697 if (arguments->dim != nparams) | |
698 goto Lnomatch; // not enough parameters | |
699 | |
700 for (size_t u = 0; u < nparams; u++) | |
701 { | |
702 Argument *arg = (Argument *)arguments->data[u]; | |
703 Argument *param = Argument::getNth(tf->parameters, u); | |
704 if (arg->type) | |
705 { if (!arg->type->equals(param->type)) | |
706 { | |
707 /* Cannot resolve argument types. Indicate an | |
708 * error by setting the number of arguments to 0. | |
709 */ | |
710 arguments->dim = 0; | |
711 goto Lmatch; | |
712 } | |
713 continue; | |
714 } | |
715 arg->type = param->type; | |
716 } | |
717 Lmatch: | |
718 return 0; | |
719 | |
720 Lnomatch: | |
721 return 1; | |
722 } | |
723 | |
724 /************************************** | |
725 */ | |
726 | |
727 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments) | |
728 { | |
729 FuncDeclaration *fd; | |
730 | |
731 assert(td); | |
130 | 732 fd = td->deduceFunctionTemplate(sc, loc, targsi, arguments); |
1 | 733 if (!fd) |
734 return; | |
735 m->anyf = fd; | |
736 if (m->last >= MATCHexact) | |
737 { | |
738 m->nextf = fd; | |
739 m->count++; | |
740 } | |
741 else | |
742 { | |
743 m->last = MATCHexact; | |
744 m->lastf = fd; | |
745 m->count = 1; | |
746 } | |
747 } | |
748 |