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"
|
|
23 #elif linux
|
|
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
|