Warn about "assert X,Y"
[delight/core.git] / dmd2 / opover.c
blobbc3ae841b3dadb5e0a76895e2cca64db5e027c05
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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, September 2004
18 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
19 #undef integer_t
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <assert.h>
25 #include <complex.h>
27 #ifdef __APPLE__
28 #define integer_t dmd_integer_t
29 #endif
31 #if IN_GCC
32 #include "mem.h"
33 #elif linux
34 #include "../root/mem.h"
35 #elif _WIN32
36 #include "..\root\mem.h"
37 #endif
39 //#include "port.h"
40 #include "mtype.h"
41 #include "init.h"
42 #include "expression.h"
43 #include "id.h"
44 #include "declaration.h"
45 #include "aggregate.h"
46 #include "template.h"
48 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
49 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
50 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
52 /******************************** Expression **************************/
55 /***********************************
56 * Determine if operands of binary op can be reversed
57 * to fit operator overload.
60 int Expression::isCommutative()
62 return FALSE; // default is no reverse
65 /***********************************
66 * Get Identifier for operator overload.
69 Identifier *Expression::opId()
71 assert(0);
72 return NULL;
75 /***********************************
76 * Get Identifier for reverse operator overload,
77 * NULL if not supported for this operator.
80 Identifier *Expression::opId_r()
82 return NULL;
85 /************************* Operators *****************************/
87 Identifier *UAddExp::opId() { return Id::uadd; }
89 Identifier *NegExp::opId() { return Id::neg; }
91 Identifier *ComExp::opId() { return Id::com; }
93 Identifier *CastExp::opId() { return Id::cast; }
95 Identifier *InExp::opId() { return Id::opIn; }
96 Identifier *InExp::opId_r() { return Id::opIn_r; }
98 Identifier *PostExp::opId() { return (op == TOKplusplus)
99 ? Id::postinc
100 : Id::postdec; }
102 int AddExp::isCommutative() { return TRUE; }
103 Identifier *AddExp::opId() { return Id::add; }
104 Identifier *AddExp::opId_r() { return Id::add_r; }
106 Identifier *MinExp::opId() { return Id::sub; }
107 Identifier *MinExp::opId_r() { return Id::sub_r; }
109 int MulExp::isCommutative() { return TRUE; }
110 Identifier *MulExp::opId() { return Id::mul; }
111 Identifier *MulExp::opId_r() { return Id::mul_r; }
113 Identifier *DivExp::opId() { return Id::div; }
114 Identifier *DivExp::opId_r() { return Id::div_r; }
116 Identifier *ModExp::opId() { return Id::mod; }
117 Identifier *ModExp::opId_r() { return Id::mod_r; }
119 Identifier *ShlExp::opId() { return Id::shl; }
120 Identifier *ShlExp::opId_r() { return Id::shl_r; }
122 Identifier *ShrExp::opId() { return Id::shr; }
123 Identifier *ShrExp::opId_r() { return Id::shr_r; }
125 Identifier *UshrExp::opId() { return Id::ushr; }
126 Identifier *UshrExp::opId_r() { return Id::ushr_r; }
128 int AndExp::isCommutative() { return TRUE; }
129 Identifier *AndExp::opId() { return Id::iand; }
130 Identifier *AndExp::opId_r() { return Id::iand_r; }
132 int OrExp::isCommutative() { return TRUE; }
133 Identifier *OrExp::opId() { return Id::ior; }
134 Identifier *OrExp::opId_r() { return Id::ior_r; }
136 int XorExp::isCommutative() { return TRUE; }
137 Identifier *XorExp::opId() { return Id::ixor; }
138 Identifier *XorExp::opId_r() { return Id::ixor_r; }
140 Identifier *CatExp::opId() { return Id::cat; }
141 Identifier *CatExp::opId_r() { return Id::cat_r; }
143 Identifier * AssignExp::opId() { return Id::assign; }
144 Identifier * AddAssignExp::opId() { return Id::addass; }
145 Identifier * MinAssignExp::opId() { return Id::subass; }
146 Identifier * MulAssignExp::opId() { return Id::mulass; }
147 Identifier * DivAssignExp::opId() { return Id::divass; }
148 Identifier * ModAssignExp::opId() { return Id::modass; }
149 Identifier * AndAssignExp::opId() { return Id::andass; }
150 Identifier * OrAssignExp::opId() { return Id::orass; }
151 Identifier * XorAssignExp::opId() { return Id::xorass; }
152 Identifier * ShlAssignExp::opId() { return Id::shlass; }
153 Identifier * ShrAssignExp::opId() { return Id::shrass; }
154 Identifier *UshrAssignExp::opId() { return Id::ushrass; }
155 Identifier * CatAssignExp::opId() { return Id::catass; }
157 int EqualExp::isCommutative() { return TRUE; }
158 Identifier *EqualExp::opId() { return Id::eq; }
160 int CmpExp::isCommutative() { return TRUE; }
161 Identifier *CmpExp::opId() { return Id::cmp; }
163 Identifier *ArrayExp::opId() { return Id::index; }
164 Identifier *PtrExp::opId() { return Id::opStar; }
166 /************************************
167 * Operator overload.
168 * Check for operator overload, if so, replace
169 * with function call.
170 * Return NULL if not an operator overload.
173 Expression *UnaExp::op_overload(Scope *sc)
175 AggregateDeclaration *ad;
176 Dsymbol *fd;
177 Type *t1 = e1->type->toBasetype();
179 if (t1->ty == Tclass)
181 ad = ((TypeClass *)t1)->sym;
182 goto L1;
184 else if (t1->ty == Tstruct)
186 ad = ((TypeStruct *)t1)->sym;
189 fd = search_function(ad, opId());
190 if (fd)
192 if (op == TOKarray)
194 Expression *e;
195 ArrayExp *ae = (ArrayExp *)this;
197 e = new DotIdExp(loc, e1, fd->ident);
198 e = new CallExp(loc, e, ae->arguments);
199 e = e->semantic(sc);
200 return e;
202 else
204 // Rewrite +e1 as e1.add()
205 return build_overload(loc, sc, e1, NULL, fd->ident);
209 return NULL;
213 Expression *BinExp::op_overload(Scope *sc)
215 //printf("BinExp::op_overload() (%s)\n", toChars());
217 AggregateDeclaration *ad;
218 Type *t1 = e1->type->toBasetype();
219 Type *t2 = e2->type->toBasetype();
220 Identifier *id = opId();
221 Identifier *id_r = opId_r();
223 Match m;
224 Expressions args1;
225 Expressions args2;
226 int argsset = 0;
228 AggregateDeclaration *ad1;
229 if (t1->ty == Tclass)
230 ad1 = ((TypeClass *)t1)->sym;
231 else if (t1->ty == Tstruct)
232 ad1 = ((TypeStruct *)t1)->sym;
233 else
234 ad1 = NULL;
236 AggregateDeclaration *ad2;
237 if (t2->ty == Tclass)
238 ad2 = ((TypeClass *)t2)->sym;
239 else if (t2->ty == Tstruct)
240 ad2 = ((TypeStruct *)t2)->sym;
241 else
242 ad2 = NULL;
244 Dsymbol *s = NULL;
245 Dsymbol *s_r = NULL;
246 FuncDeclaration *fd = NULL;
247 TemplateDeclaration *td = NULL;
248 if (ad1 && id)
250 s = search_function(ad1, id);
252 if (ad2 && id_r)
254 s_r = search_function(ad2, id_r);
257 if (s || s_r)
259 /* Try:
260 * a.opfunc(b)
261 * b.opfunc_r(a)
262 * and see which is better.
264 Expression *e;
265 FuncDeclaration *lastf;
267 args1.setDim(1);
268 args1.data[0] = (void*) e1;
269 args2.setDim(1);
270 args2.data[0] = (void*) e2;
271 argsset = 1;
273 memset(&m, 0, sizeof(m));
274 m.last = MATCHnomatch;
276 if (s)
278 fd = s->isFuncDeclaration();
279 if (fd)
281 overloadResolveX(&m, fd, NULL, &args2);
283 else
284 { td = s->isTemplateDeclaration();
285 templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
289 lastf = m.lastf;
291 if (s_r)
293 fd = s_r->isFuncDeclaration();
294 if (fd)
296 overloadResolveX(&m, fd, NULL, &args1);
298 else
299 { td = s_r->isTemplateDeclaration();
300 templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
304 if (m.count > 1)
306 // Error, ambiguous
307 error("overloads %s and %s both match argument list for %s",
308 m.lastf->type->toChars(),
309 m.nextf->type->toChars(),
310 m.lastf->toChars());
312 else if (m.last == MATCHnomatch)
314 m.lastf = m.anyf;
317 if (op == TOKplusplus || op == TOKminusminus)
318 // Kludge because operator overloading regards e++ and e--
319 // as unary, but it's implemented as a binary.
320 // Rewrite (e1 ++ e2) as e1.postinc()
321 // Rewrite (e1 -- e2) as e1.postdec()
322 e = build_overload(loc, sc, e1, NULL, id);
323 else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
324 // Rewrite (e1 op e2) as e1.opfunc(e2)
325 e = build_overload(loc, sc, e1, e2, id);
326 else
327 // Rewrite (e1 op e2) as e2.opfunc_r(e1)
328 e = build_overload(loc, sc, e2, e1, id_r);
329 return e;
332 if (isCommutative())
334 s = NULL;
335 s_r = NULL;
336 if (ad1 && id_r)
338 s_r = search_function(ad1, id_r);
340 if (ad2 && id)
342 s = search_function(ad2, id);
345 if (s || s_r)
347 /* Try:
348 * a.opfunc_r(b)
349 * b.opfunc(a)
350 * and see which is better.
352 Expression *e;
353 FuncDeclaration *lastf;
355 if (!argsset)
356 { args1.setDim(1);
357 args1.data[0] = (void*) e1;
358 args2.setDim(1);
359 args2.data[0] = (void*) e2;
362 memset(&m, 0, sizeof(m));
363 m.last = MATCHnomatch;
365 if (s_r)
367 fd = s_r->isFuncDeclaration();
368 if (fd)
370 overloadResolveX(&m, fd, NULL, &args2);
372 else
373 { td = s_r->isTemplateDeclaration();
374 templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
377 lastf = m.lastf;
379 if (s)
381 fd = s->isFuncDeclaration();
382 if (fd)
384 overloadResolveX(&m, fd, NULL, &args1);
386 else
387 { td = s->isTemplateDeclaration();
388 templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
392 if (m.count > 1)
394 // Error, ambiguous
395 error("overloads %s and %s both match argument list for %s",
396 m.lastf->type->toChars(),
397 m.nextf->type->toChars(),
398 m.lastf->toChars());
400 else if (m.last == MATCHnomatch)
402 m.lastf = m.anyf;
405 if (lastf && m.lastf == lastf ||
406 id_r && m.last == MATCHnomatch)
407 // Rewrite (e1 op e2) as e1.opfunc_r(e2)
408 e = build_overload(loc, sc, e1, e2, id_r);
409 else
410 // Rewrite (e1 op e2) as e2.opfunc(e1)
411 e = build_overload(loc, sc, e2, e1, id);
413 // When reversing operands of comparison operators,
414 // need to reverse the sense of the op
415 switch (op)
417 case TOKlt: op = TOKgt; break;
418 case TOKgt: op = TOKlt; break;
419 case TOKle: op = TOKge; break;
420 case TOKge: op = TOKle; break;
422 // Floating point compares
423 case TOKule: op = TOKuge; break;
424 case TOKul: op = TOKug; break;
425 case TOKuge: op = TOKule; break;
426 case TOKug: op = TOKul; break;
428 // These are symmetric
429 case TOKunord:
430 case TOKlg:
431 case TOKleg:
432 case TOKue:
433 break;
436 return e;
440 return NULL;
443 /***********************************
444 * Utility to build a function call out of this reference and argument.
447 Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
449 Expression *e;
451 //printf("build_overload(id = '%s')\n", id->toChars());
452 //earg->print();
453 //earg->type->print();
454 e = new DotIdExp(loc, ethis, id);
456 if (earg)
457 e = new CallExp(loc, e, earg);
458 else
459 e = new CallExp(loc, e);
461 e = e->semantic(sc);
462 return e;
465 /***************************************
466 * Search for function funcid in aggregate ad.
469 Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
471 Dsymbol *s;
472 FuncDeclaration *fd;
473 TemplateDeclaration *td;
475 s = ad->search(0, funcid, 0);
476 if (s)
477 { Dsymbol *s2;
479 //printf("search_function: s = '%s'\n", s->kind());
480 s2 = s->toAlias();
481 //printf("search_function: s2 = '%s'\n", s2->kind());
482 fd = s2->isFuncDeclaration();
483 if (fd && fd->type->ty == Tfunction)
484 return fd;
486 td = s2->isTemplateDeclaration();
487 if (td)
488 return td;
490 return NULL;
494 /*****************************************
495 * Given array of arguments and an aggregate type,
496 * if any of the argument types are missing, attempt to infer
497 * them from the aggregate type.
500 void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr)
502 if (!arguments || !arguments->dim)
503 return;
505 /* Return if no arguments need types.
507 for (size_t u = 0; 1; u++)
508 { if (u == arguments->dim)
509 return;
510 Argument *arg = (Argument *)arguments->data[u];
511 if (!arg->type)
512 break;
515 AggregateDeclaration *ad;
516 FuncDeclaration *fd;
518 Argument *arg = (Argument *)arguments->data[0];
519 Type *taggr = aggr->type;
520 if (!taggr)
521 return;
522 Type *tab = taggr->toBasetype();
523 switch (tab->ty)
525 case Tarray:
526 case Tsarray:
527 case Ttuple:
528 if (arguments->dim == 2)
530 if (!arg->type)
531 arg->type = Type::tsize_t; // key type
532 arg = (Argument *)arguments->data[1];
534 if (!arg->type && tab->ty != Ttuple)
535 arg->type = tab->nextOf(); // value type
536 break;
538 case Taarray:
539 { TypeAArray *taa = (TypeAArray *)tab;
541 if (arguments->dim == 2)
543 if (!arg->type)
544 arg->type = taa->index; // key type
545 arg = (Argument *)arguments->data[1];
547 if (!arg->type)
548 arg->type = taa->next; // value type
549 break;
552 case Tclass:
553 ad = ((TypeClass *)tab)->sym;
554 goto Laggr;
556 case Tstruct:
557 ad = ((TypeStruct *)tab)->sym;
558 goto Laggr;
560 Laggr:
561 #if 0
562 if (arguments->dim == 1)
564 if (!arg->type)
566 /* Look for an opNext() overload
568 Dsymbol *s = search_function(ad, Id::next);
569 fd = s ? s->isFuncDeclaration() : NULL;
570 if (!fd)
571 goto Lapply;
572 arg->type = fd->type->next;
574 break;
576 #endif
577 Lapply:
578 { /* Look for an
579 * int opApply(int delegate(ref Type [, ...]) dg);
580 * overload
582 Dsymbol *s = search_function(ad,
583 (op == TOKforeach_reverse) ? Id::applyReverse
584 : Id::apply);
585 if (s)
587 fd = s->isFuncDeclaration();
588 if (fd)
589 inferApplyArgTypesX(fd, arguments);
591 break;
594 case Tdelegate:
596 if (0 && aggr->op == TOKdelegate)
597 { DelegateExp *de = (DelegateExp *)aggr;
599 fd = de->func->isFuncDeclaration();
600 if (fd)
601 inferApplyArgTypesX(fd, arguments);
603 else
605 inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
607 break;
610 default:
611 break; // ignore error, caught later
615 /********************************
616 * Recursive helper function,
617 * analogous to func.overloadResolveX().
620 int fp3(void *param, FuncDeclaration *f)
622 Arguments *arguments = (Arguments *)param;
623 TypeFunction *tf = (TypeFunction *)f->type;
624 if (inferApplyArgTypesY(tf, arguments) == 1)
625 return 0;
626 if (arguments->dim == 0)
627 return 1;
628 return 0;
631 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
633 overloadApply(fstart, &fp3, arguments);
636 #if 0
637 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
639 Declaration *d;
640 Declaration *next;
642 for (d = fstart; d; d = next)
644 FuncDeclaration *f;
645 FuncAliasDeclaration *fa;
646 AliasDeclaration *a;
648 fa = d->isFuncAliasDeclaration();
649 if (fa)
651 inferApplyArgTypesX(fa->funcalias, arguments);
652 next = fa->overnext;
654 else if ((f = d->isFuncDeclaration()) != NULL)
656 next = f->overnext;
658 TypeFunction *tf = (TypeFunction *)f->type;
659 if (inferApplyArgTypesY(tf, arguments) == 1)
660 continue;
661 if (arguments->dim == 0)
662 return;
664 else if ((a = d->isAliasDeclaration()) != NULL)
666 Dsymbol *s = a->toAlias();
667 next = s->isDeclaration();
668 if (next == a)
669 break;
670 if (next == fstart)
671 break;
673 else
674 { d->error("is aliased to a function");
675 break;
679 #endif
681 /******************************
682 * Infer arguments from type of function.
683 * Returns:
684 * 0 match for this function
685 * 1 no match for this function
688 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
689 { size_t nparams;
690 Argument *p;
692 if (Argument::dim(tf->parameters) != 1)
693 goto Lnomatch;
694 p = Argument::getNth(tf->parameters, 0);
695 if (p->type->ty != Tdelegate)
696 goto Lnomatch;
697 tf = (TypeFunction *)p->type->nextOf();
698 assert(tf->ty == Tfunction);
700 /* We now have tf, the type of the delegate. Match it against
701 * the arguments, filling in missing argument types.
703 nparams = Argument::dim(tf->parameters);
704 if (nparams == 0 || tf->varargs)
705 goto Lnomatch; // not enough parameters
706 if (arguments->dim != nparams)
707 goto Lnomatch; // not enough parameters
709 for (size_t u = 0; u < nparams; u++)
711 Argument *arg = (Argument *)arguments->data[u];
712 Argument *param = Argument::getNth(tf->parameters, u);
713 if (arg->type)
714 { if (!arg->type->equals(param->type))
716 /* Cannot resolve argument types. Indicate an
717 * error by setting the number of arguments to 0.
719 arguments->dim = 0;
720 goto Lmatch;
722 continue;
724 arg->type = param->type;
726 Lmatch:
727 return 0;
729 Lnomatch:
730 return 1;
733 /**************************************
736 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
738 FuncDeclaration *fd;
740 assert(td);
741 fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments);
742 if (!fd)
743 return;
744 m->anyf = fd;
745 if (m->last >= MATCHexact)
747 m->nextf = fd;
748 m->count++;
750 else
752 m->last = MATCHexact;
753 m->lastf = fd;
754 m->count = 1;