Mercurial > projects > ldc
annotate dmd/opover.c @ 847:356e65836fb5
Merged DMD 2.021 frontend.
Removed generated files from dmd/dmd2 dirs.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 13 Dec 2008 16:14:37 +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 |