comparison dmd2/opover.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 356e65836fb5
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
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 POSIX
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 void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
39 static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments);
40 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
41 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, 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 Identifier *PtrExp::opId() { return Id::opStar; }
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, NULL, &args2);
273 }
274 else
275 { td = s->isTemplateDeclaration();
276 templateResolve(&m, td, sc, loc, NULL, 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, NULL, &args1);
288 }
289 else
290 { td = s_r->isTemplateDeclaration();
291 templateResolve(&m, td, sc, loc, NULL, 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, NULL, &args2);
362 }
363 else
364 { td = s_r->isTemplateDeclaration();
365 templateResolve(&m, td, sc, loc, NULL, 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, NULL, &args1);
376 }
377 else
378 { td = s->isTemplateDeclaration();
379 templateResolve(&m, td, sc, loc, NULL, 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 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(ScopeDsymbol *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
508 Argument *arg = (Argument *)arguments->data[0];
509 Type *taggr = aggr->type;
510 if (!taggr)
511 return;
512 Type *tab = taggr->toBasetype();
513 switch (tab->ty)
514 {
515 case Tarray:
516 case Tsarray:
517 case Ttuple:
518 if (arguments->dim == 2)
519 {
520 if (!arg->type)
521 arg->type = Type::tsize_t; // key type
522 arg = (Argument *)arguments->data[1];
523 }
524 if (!arg->type && tab->ty != Ttuple)
525 arg->type = tab->nextOf(); // value type
526 break;
527
528 case Taarray:
529 { TypeAArray *taa = (TypeAArray *)tab;
530
531 if (arguments->dim == 2)
532 {
533 if (!arg->type)
534 arg->type = taa->index; // key type
535 arg = (Argument *)arguments->data[1];
536 }
537 if (!arg->type)
538 arg->type = taa->next; // value type
539 break;
540 }
541
542 case Tclass:
543 ad = ((TypeClass *)tab)->sym;
544 goto Laggr;
545
546 case Tstruct:
547 ad = ((TypeStruct *)tab)->sym;
548 goto Laggr;
549
550 Laggr:
551 #if 0
552 if (arguments->dim == 1)
553 {
554 if (!arg->type)
555 {
556 /* Look for an opNext() overload
557 */
558 Dsymbol *s = search_function(ad, Id::next);
559 fd = s ? s->isFuncDeclaration() : NULL;
560 if (!fd)
561 goto Lapply;
562 arg->type = fd->type->next;
563 }
564 break;
565 }
566 #endif
567 Lapply:
568 { /* Look for an
569 * int opApply(int delegate(ref Type [, ...]) dg);
570 * overload
571 */
572 Dsymbol *s = search_function(ad,
573 (op == TOKforeach_reverse) ? Id::applyReverse
574 : Id::apply);
575 if (s)
576 {
577 FuncDeclaration *fd = s->isFuncDeclaration();
578 if (fd)
579 { inferApplyArgTypesX(fd, arguments);
580 break;
581 }
582 #if 0
583 TemplateDeclaration *td = s->isTemplateDeclaration();
584 if (td)
585 { inferApplyArgTypesZ(td, arguments);
586 break;
587 }
588 #endif
589 }
590 break;
591 }
592
593 case Tdelegate:
594 {
595 if (0 && aggr->op == TOKdelegate)
596 { DelegateExp *de = (DelegateExp *)aggr;
597
598 FuncDeclaration *fd = de->func->isFuncDeclaration();
599 if (fd)
600 inferApplyArgTypesX(fd, arguments);
601 }
602 else
603 {
604 inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
605 }
606 break;
607 }
608
609 default:
610 break; // ignore error, caught later
611 }
612 }
613
614 /********************************
615 * Recursive helper function,
616 * analogous to func.overloadResolveX().
617 */
618
619 int fp3(void *param, FuncDeclaration *f)
620 {
621 Arguments *arguments = (Arguments *)param;
622 TypeFunction *tf = (TypeFunction *)f->type;
623 if (inferApplyArgTypesY(tf, arguments) == 1)
624 return 0;
625 if (arguments->dim == 0)
626 return 1;
627 return 0;
628 }
629
630 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
631 {
632 overloadApply(fstart, &fp3, arguments);
633 }
634
635 /******************************
636 * Infer arguments from type of function.
637 * Returns:
638 * 0 match for this function
639 * 1 no match for this function
640 */
641
642 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
643 { size_t nparams;
644 Argument *p;
645
646 if (Argument::dim(tf->parameters) != 1)
647 goto Lnomatch;
648 p = Argument::getNth(tf->parameters, 0);
649 if (p->type->ty != Tdelegate)
650 goto Lnomatch;
651 tf = (TypeFunction *)p->type->nextOf();
652 assert(tf->ty == Tfunction);
653
654 /* We now have tf, the type of the delegate. Match it against
655 * the arguments, filling in missing argument types.
656 */
657 nparams = Argument::dim(tf->parameters);
658 if (nparams == 0 || tf->varargs)
659 goto Lnomatch; // not enough parameters
660 if (arguments->dim != nparams)
661 goto Lnomatch; // not enough parameters
662
663 for (size_t u = 0; u < nparams; u++)
664 {
665 Argument *arg = (Argument *)arguments->data[u];
666 Argument *param = Argument::getNth(tf->parameters, u);
667 if (arg->type)
668 { if (!arg->type->equals(param->type))
669 {
670 /* Cannot resolve argument types. Indicate an
671 * error by setting the number of arguments to 0.
672 */
673 arguments->dim = 0;
674 goto Lmatch;
675 }
676 continue;
677 }
678 arg->type = param->type;
679 }
680 Lmatch:
681 return 0;
682
683 Lnomatch:
684 return 1;
685 }
686
687 /*******************************************
688 * Infer foreach arg types from a template function opApply which looks like:
689 * int opApply(alias int func(ref uint))() { ... }
690 */
691
692 #if 0
693 void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments)
694 {
695 for (TemplateDeclaration *td = tstart; td; td = td->overnext)
696 {
697 if (!td->scope)
698 {
699 error("forward reference to template %s", td->toChars());
700 return;
701 }
702 if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
703 {
704 error("is not a function template");
705 return;
706 }
707 if (!td->parameters || td->parameters->dim != 1)
708 continue;
709 TemplateParameter *tp = (TemplateParameter *)td->parameters->data[0];
710 TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
711 if (!tap || !tap->specType || tap->specType->ty != Tfunction)
712 continue;
713 TypeFunction *tf = (TypeFunction *)tap->specType;
714 if (inferApplyArgTypesY(tf, arguments) == 0) // found it
715 return;
716 }
717 }
718 #endif
719
720 /**************************************
721 */
722
723 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
724 {
725 FuncDeclaration *fd;
726
727 assert(td);
728 fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments);
729 if (!fd)
730 return;
731 m->anyf = fd;
732 if (m->last >= MATCHexact)
733 {
734 m->nextf = fd;
735 m->count++;
736 }
737 else
738 {
739 m->last = MATCHexact;
740 m->lastf = fd;
741 m->count = 1;
742 }
743 }
744