Fixed some lexing problems with DOS line-endings
[delight/core.git] / dmd / opover.c
blob4056aa04796df4bab8c1b52f5b8b62d2887e971a
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 Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
49 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
50 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
51 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments);
53 /******************************** Expression **************************/
56 /***********************************
57 * Determine if operands of binary op can be reversed
58 * to fit operator overload.
61 int Expression::isCommutative()
63 return FALSE; // default is no reverse
66 /***********************************
67 * Get Identifier for operator overload.
70 Identifier *Expression::opId()
72 assert(0);
73 return NULL;
76 /***********************************
77 * Get Identifier for reverse operator overload,
78 * NULL if not supported for this operator.
81 Identifier *Expression::opId_r()
83 return NULL;
86 /************************* Operators *****************************/
88 Identifier *UAddExp::opId() { return Id::uadd; }
90 Identifier *NegExp::opId() { return Id::neg; }
92 Identifier *ComExp::opId() { return Id::com; }
94 Identifier *CastExp::opId() { return Id::cast; }
96 Identifier *InExp::opId() { return Id::opIn; }
97 Identifier *InExp::opId_r() { return Id::opIn_r; }
99 Identifier *PostExp::opId() { return (op == TOKplusplus)
100 ? Id::postinc
101 : Id::postdec; }
103 int AddExp::isCommutative() { return TRUE; }
104 Identifier *AddExp::opId() { return Id::add; }
105 Identifier *AddExp::opId_r() { return Id::add_r; }
107 Identifier *MinExp::opId() { return Id::sub; }
108 Identifier *MinExp::opId_r() { return Id::sub_r; }
110 int MulExp::isCommutative() { return TRUE; }
111 Identifier *MulExp::opId() { return Id::mul; }
112 Identifier *MulExp::opId_r() { return Id::mul_r; }
114 Identifier *DivExp::opId() { return Id::div; }
115 Identifier *DivExp::opId_r() { return Id::div_r; }
117 Identifier *ModExp::opId() { return Id::mod; }
118 Identifier *ModExp::opId_r() { return Id::mod_r; }
120 Identifier *ShlExp::opId() { return Id::shl; }
121 Identifier *ShlExp::opId_r() { return Id::shl_r; }
123 Identifier *ShrExp::opId() { return Id::shr; }
124 Identifier *ShrExp::opId_r() { return Id::shr_r; }
126 Identifier *UshrExp::opId() { return Id::ushr; }
127 Identifier *UshrExp::opId_r() { return Id::ushr_r; }
129 int AndExp::isCommutative() { return TRUE; }
130 Identifier *AndExp::opId() { return Id::iand; }
131 Identifier *AndExp::opId_r() { return Id::iand_r; }
133 int OrExp::isCommutative() { return TRUE; }
134 Identifier *OrExp::opId() { return Id::ior; }
135 Identifier *OrExp::opId_r() { return Id::ior_r; }
137 int XorExp::isCommutative() { return TRUE; }
138 Identifier *XorExp::opId() { return Id::ixor; }
139 Identifier *XorExp::opId_r() { return Id::ixor_r; }
141 Identifier *CatExp::opId() { return Id::cat; }
142 Identifier *CatExp::opId_r() { return Id::cat_r; }
144 Identifier * AssignExp::opId() { return Id::assign; }
145 Identifier * AddAssignExp::opId() { return Id::addass; }
146 Identifier * MinAssignExp::opId() { return Id::subass; }
147 Identifier * MulAssignExp::opId() { return Id::mulass; }
148 Identifier * DivAssignExp::opId() { return Id::divass; }
149 Identifier * ModAssignExp::opId() { return Id::modass; }
150 Identifier * AndAssignExp::opId() { return Id::andass; }
151 Identifier * OrAssignExp::opId() { return Id::orass; }
152 Identifier * XorAssignExp::opId() { return Id::xorass; }
153 Identifier * ShlAssignExp::opId() { return Id::shlass; }
154 Identifier * ShrAssignExp::opId() { return Id::shrass; }
155 Identifier *UshrAssignExp::opId() { return Id::ushrass; }
156 Identifier * CatAssignExp::opId() { return Id::catass; }
158 int EqualExp::isCommutative() { return TRUE; }
159 Identifier *EqualExp::opId() { return Id::eq; }
161 int CmpExp::isCommutative() { return TRUE; }
162 Identifier *CmpExp::opId() { return Id::cmp; }
164 Identifier *ArrayExp::opId() { return Id::index; }
167 /************************************
168 * Operator overload.
169 * Check for operator overload, if so, replace
170 * with function call.
171 * Return NULL if not an operator overload.
174 Expression *UnaExp::op_overload(Scope *sc)
176 AggregateDeclaration *ad;
177 Dsymbol *fd;
178 Type *t1 = e1->type->toBasetype();
180 if (t1->ty == Tclass)
182 ad = ((TypeClass *)t1)->sym;
183 goto L1;
185 else if (t1->ty == Tstruct)
187 ad = ((TypeStruct *)t1)->sym;
190 fd = search_function(ad, opId());
191 if (fd)
193 if (op == TOKarray)
195 Expression *e;
196 ArrayExp *ae = (ArrayExp *)this;
198 e = new DotIdExp(loc, e1, fd->ident);
199 e = new CallExp(loc, e, ae->arguments);
200 e = e->semantic(sc);
201 return e;
203 else
205 // Rewrite +e1 as e1.add()
206 return build_overload(loc, sc, e1, NULL, fd->ident);
210 return NULL;
214 Expression *BinExp::op_overload(Scope *sc)
216 //printf("BinExp::op_overload() (%s)\n", toChars());
218 AggregateDeclaration *ad;
219 Type *t1 = e1->type->toBasetype();
220 Type *t2 = e2->type->toBasetype();
221 Identifier *id = opId();
222 Identifier *id_r = opId_r();
224 Match m;
225 Expressions args1;
226 Expressions args2;
227 int argsset = 0;
229 AggregateDeclaration *ad1;
230 if (t1->ty == Tclass)
231 ad1 = ((TypeClass *)t1)->sym;
232 else if (t1->ty == Tstruct)
233 ad1 = ((TypeStruct *)t1)->sym;
234 else
235 ad1 = NULL;
237 AggregateDeclaration *ad2;
238 if (t2->ty == Tclass)
239 ad2 = ((TypeClass *)t2)->sym;
240 else if (t2->ty == Tstruct)
241 ad2 = ((TypeStruct *)t2)->sym;
242 else
243 ad2 = NULL;
245 Dsymbol *s = NULL;
246 Dsymbol *s_r = NULL;
247 FuncDeclaration *fd = NULL;
248 TemplateDeclaration *td = NULL;
249 if (ad1 && id)
251 s = search_function(ad1, id);
253 if (ad2 && id_r)
255 s_r = search_function(ad2, id_r);
258 if (s || s_r)
260 /* Try:
261 * a.opfunc(b)
262 * b.opfunc_r(a)
263 * and see which is better.
265 Expression *e;
266 FuncDeclaration *lastf;
268 args1.setDim(1);
269 args1.data[0] = (void*) e1;
270 args2.setDim(1);
271 args2.data[0] = (void*) e2;
272 argsset = 1;
274 memset(&m, 0, sizeof(m));
275 m.last = MATCHnomatch;
277 if (s)
279 fd = s->isFuncDeclaration();
280 if (fd)
282 overloadResolveX(&m, fd, &args2);
284 else
285 { td = s->isTemplateDeclaration();
286 templateResolve(&m, td, sc, loc, NULL, &args2);
290 lastf = m.lastf;
292 if (s_r)
294 fd = s_r->isFuncDeclaration();
295 if (fd)
297 overloadResolveX(&m, fd, &args1);
299 else
300 { td = s_r->isTemplateDeclaration();
301 templateResolve(&m, td, sc, loc, NULL, &args1);
305 if (m.count > 1)
307 // Error, ambiguous
308 error("overloads %s and %s both match argument list for %s",
309 m.lastf->type->toChars(),
310 m.nextf->type->toChars(),
311 m.lastf->toChars());
313 else if (m.last == MATCHnomatch)
315 m.lastf = m.anyf;
318 if (op == TOKplusplus || op == TOKminusminus)
319 // Kludge because operator overloading regards e++ and e--
320 // as unary, but it's implemented as a binary.
321 // Rewrite (e1 ++ e2) as e1.postinc()
322 // Rewrite (e1 -- e2) as e1.postdec()
323 e = build_overload(loc, sc, e1, NULL, id);
324 else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
325 // Rewrite (e1 op e2) as e1.opfunc(e2)
326 e = build_overload(loc, sc, e1, e2, id);
327 else
328 // Rewrite (e1 op e2) as e2.opfunc_r(e1)
329 e = build_overload(loc, sc, e2, e1, id_r);
330 return e;
333 if (isCommutative())
335 s = NULL;
336 s_r = NULL;
337 if (ad1 && id_r)
339 s_r = search_function(ad1, id_r);
341 if (ad2 && id)
343 s = search_function(ad2, id);
346 if (s || s_r)
348 /* Try:
349 * a.opfunc_r(b)
350 * b.opfunc(a)
351 * and see which is better.
353 Expression *e;
354 FuncDeclaration *lastf;
356 if (!argsset)
357 { args1.setDim(1);
358 args1.data[0] = (void*) e1;
359 args2.setDim(1);
360 args2.data[0] = (void*) e2;
363 memset(&m, 0, sizeof(m));
364 m.last = MATCHnomatch;
366 if (s_r)
368 fd = s_r->isFuncDeclaration();
369 if (fd)
371 overloadResolveX(&m, fd, &args2);
373 else
374 { td = s_r->isTemplateDeclaration();
375 templateResolve(&m, td, sc, loc, NULL, &args2);
378 lastf = m.lastf;
380 if (s)
382 fd = s->isFuncDeclaration();
383 if (fd)
385 overloadResolveX(&m, fd, &args1);
387 else
388 { td = s->isTemplateDeclaration();
389 templateResolve(&m, td, sc, loc, NULL, &args1);
393 if (m.count > 1)
395 // Error, ambiguous
396 error("overloads %s and %s both match argument list for %s",
397 m.lastf->type->toChars(),
398 m.nextf->type->toChars(),
399 m.lastf->toChars());
401 else if (m.last == MATCHnomatch)
403 m.lastf = m.anyf;
406 if (lastf && m.lastf == lastf ||
407 id_r && m.last == MATCHnomatch)
408 // Rewrite (e1 op e2) as e1.opfunc_r(e2)
409 e = build_overload(loc, sc, e1, e2, id_r);
410 else
411 // Rewrite (e1 op e2) as e2.opfunc(e1)
412 e = build_overload(loc, sc, e2, e1, id);
414 // When reversing operands of comparison operators,
415 // need to reverse the sense of the op
416 switch (op)
418 case TOKlt: op = TOKgt; break;
419 case TOKgt: op = TOKlt; break;
420 case TOKle: op = TOKge; break;
421 case TOKge: op = TOKle; break;
423 // Floating point compares
424 case TOKule: op = TOKuge; break;
425 case TOKul: op = TOKug; break;
426 case TOKuge: op = TOKule; break;
427 case TOKug: op = TOKul; break;
429 // These are symmetric
430 case TOKunord:
431 case TOKlg:
432 case TOKleg:
433 case TOKue:
434 break;
437 return e;
441 return NULL;
444 /***********************************
445 * Utility to build a function call out of this reference and argument.
448 static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
450 Expression *e;
452 //printf("build_overload(id = '%s')\n", id->toChars());
453 //earg->print();
454 //earg->type->print();
455 e = new DotIdExp(loc, ethis, id);
457 if (earg)
458 e = new CallExp(loc, e, earg);
459 else
460 e = new CallExp(loc, e);
462 e = e->semantic(sc);
463 return e;
466 /***************************************
467 * Search for function funcid in aggregate ad.
470 Dsymbol *search_function(AggregateDeclaration *ad, Identifier *funcid)
472 Dsymbol *s;
473 FuncDeclaration *fd;
474 TemplateDeclaration *td;
476 s = ad->search(0, funcid, 0);
477 if (s)
478 { Dsymbol *s2;
480 //printf("search_function: s = '%s'\n", s->kind());
481 s2 = s->toAlias();
482 //printf("search_function: s2 = '%s'\n", s2->kind());
483 fd = s2->isFuncDeclaration();
484 if (fd && fd->type->ty == Tfunction)
485 return fd;
487 td = s2->isTemplateDeclaration();
488 if (td)
489 return td;
491 return NULL;
495 /*****************************************
496 * Given array of arguments and an aggregate type,
497 * if any of the argument types are missing, attempt to infer
498 * them from the aggregate type.
501 void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr)
503 if (!arguments || !arguments->dim)
504 return;
506 /* Return if no arguments need types.
508 for (size_t u = 0; 1; u++)
509 { if (u == arguments->dim)
510 return;
511 Argument *arg = (Argument *)arguments->data[u];
512 if (!arg->type)
513 break;
516 AggregateDeclaration *ad;
517 FuncDeclaration *fd;
519 Argument *arg = (Argument *)arguments->data[0];
520 Type *taggr = aggr->type;
521 if (!taggr)
522 return;
523 Type *tab = taggr->toBasetype();
524 switch (tab->ty)
526 case Tarray:
527 case Tsarray:
528 case Ttuple:
529 if (arguments->dim == 2)
531 if (!arg->type)
532 arg->type = Type::tsize_t; // key type
533 arg = (Argument *)arguments->data[1];
535 if (!arg->type && tab->ty != Ttuple)
536 arg->type = tab->nextOf(); // value type
537 break;
539 case Taarray:
540 { TypeAArray *taa = (TypeAArray *)tab;
542 if (arguments->dim == 2)
544 if (!arg->type)
545 arg->type = taa->index; // key type
546 arg = (Argument *)arguments->data[1];
548 if (!arg->type)
549 arg->type = taa->next; // value type
550 break;
553 case Tclass:
554 ad = ((TypeClass *)tab)->sym;
555 goto Laggr;
557 case Tstruct:
558 ad = ((TypeStruct *)tab)->sym;
559 goto Laggr;
561 Laggr:
562 #if 0
563 if (arguments->dim == 1)
565 if (!arg->type)
567 /* Look for an opNext() overload
569 Dsymbol *s = search_function(ad, Id::next);
570 fd = s ? s->isFuncDeclaration() : NULL;
571 if (!fd)
572 goto Lapply;
573 arg->type = fd->type->next;
575 break;
577 #endif
578 Lapply:
579 { /* Look for an
580 * int opApply(int delegate(ref Type [, ...]) dg);
581 * overload
583 Dsymbol *s = search_function(ad,
584 (op == TOKforeach_reverse) ? Id::applyReverse
585 : Id::apply);
586 if (s)
588 fd = s->isFuncDeclaration();
589 if (fd)
590 inferApplyArgTypesX(fd, arguments);
592 break;
595 case Tdelegate:
597 if (0 && aggr->op == TOKdelegate)
598 { DelegateExp *de = (DelegateExp *)aggr;
600 fd = de->func->isFuncDeclaration();
601 if (fd)
602 inferApplyArgTypesX(fd, arguments);
604 else
606 inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
608 break;
611 default:
612 break; // ignore error, caught later
616 /********************************
617 * Recursive helper function,
618 * analogous to func.overloadResolveX().
621 int fp3(void *param, FuncDeclaration *f)
623 Arguments *arguments = (Arguments *)param;
624 TypeFunction *tf = (TypeFunction *)f->type;
625 if (inferApplyArgTypesY(tf, arguments) == 1)
626 return 0;
627 if (arguments->dim == 0)
628 return 1;
629 return 0;
632 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
634 overloadApply(fstart, &fp3, arguments);
637 #if 0
638 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments)
640 Declaration *d;
641 Declaration *next;
643 for (d = fstart; d; d = next)
645 FuncDeclaration *f;
646 FuncAliasDeclaration *fa;
647 AliasDeclaration *a;
649 fa = d->isFuncAliasDeclaration();
650 if (fa)
652 inferApplyArgTypesX(fa->funcalias, arguments);
653 next = fa->overnext;
655 else if ((f = d->isFuncDeclaration()) != NULL)
657 next = f->overnext;
659 TypeFunction *tf = (TypeFunction *)f->type;
660 if (inferApplyArgTypesY(tf, arguments) == 1)
661 continue;
662 if (arguments->dim == 0)
663 return;
665 else if ((a = d->isAliasDeclaration()) != NULL)
667 Dsymbol *s = a->toAlias();
668 next = s->isDeclaration();
669 if (next == a)
670 break;
671 if (next == fstart)
672 break;
674 else
675 { d->error("is aliased to a function");
676 break;
680 #endif
682 /******************************
683 * Infer arguments from type of function.
684 * Returns:
685 * 0 match for this function
686 * 1 no match for this function
689 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
690 { size_t nparams;
691 Argument *p;
693 if (Argument::dim(tf->parameters) != 1)
694 goto Lnomatch;
695 p = Argument::getNth(tf->parameters, 0);
696 if (p->type->ty != Tdelegate)
697 goto Lnomatch;
698 tf = (TypeFunction *)p->type->nextOf();
699 assert(tf->ty == Tfunction);
701 /* We now have tf, the type of the delegate. Match it against
702 * the arguments, filling in missing argument types.
704 nparams = Argument::dim(tf->parameters);
705 if (nparams == 0 || tf->varargs)
706 goto Lnomatch; // not enough parameters
707 if (arguments->dim != nparams)
708 goto Lnomatch; // not enough parameters
710 for (size_t u = 0; u < nparams; u++)
712 Argument *arg = (Argument *)arguments->data[u];
713 Argument *param = Argument::getNth(tf->parameters, u);
714 if (arg->type)
715 { if (!arg->type->equals(param->type))
717 /* Cannot resolve argument types. Indicate an
718 * error by setting the number of arguments to 0.
720 arguments->dim = 0;
721 goto Lmatch;
723 continue;
725 arg->type = param->type;
727 Lmatch:
728 return 0;
730 Lnomatch:
731 return 1;
734 /**************************************
737 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments)
739 FuncDeclaration *fd;
741 assert(td);
742 fd = td->deduceFunctionTemplate(sc, loc, targsi, arguments);
743 if (!fd)
744 return;
745 m->anyf = fd;
746 if (m->last >= MATCHexact)
748 m->nextf = fd;
749 m->count++;
751 else
753 m->last = MATCHexact;
754 m->lastf = fd;
755 m->count = 1;