2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
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...
28 #define integer_t dmd_integer_t
34 #include "../root/mem.h"
36 #include "..\root\mem.h"
42 #include "expression.h"
44 #include "declaration.h"
45 #include "aggregate.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()
75 /***********************************
76 * Get Identifier for reverse operator overload,
77 * NULL if not supported for this operator.
80 Identifier
*Expression::opId_r()
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
)
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 /************************************
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
;
177 Type
*t1
= e1
->type
->toBasetype();
179 if (t1
->ty
== Tclass
)
181 ad
= ((TypeClass
*)t1
)->sym
;
184 else if (t1
->ty
== Tstruct
)
186 ad
= ((TypeStruct
*)t1
)->sym
;
189 fd
= search_function(ad
, opId());
195 ArrayExp
*ae
= (ArrayExp
*)this;
197 e
= new DotIdExp(loc
, e1
, fd
->ident
);
198 e
= new CallExp(loc
, e
, ae
->arguments
);
204 // Rewrite +e1 as e1.add()
205 return build_overload(loc
, sc
, e1
, NULL
, fd
->ident
);
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();
228 AggregateDeclaration
*ad1
;
229 if (t1
->ty
== Tclass
)
230 ad1
= ((TypeClass
*)t1
)->sym
;
231 else if (t1
->ty
== Tstruct
)
232 ad1
= ((TypeStruct
*)t1
)->sym
;
236 AggregateDeclaration
*ad2
;
237 if (t2
->ty
== Tclass
)
238 ad2
= ((TypeClass
*)t2
)->sym
;
239 else if (t2
->ty
== Tstruct
)
240 ad2
= ((TypeStruct
*)t2
)->sym
;
246 FuncDeclaration
*fd
= NULL
;
247 TemplateDeclaration
*td
= NULL
;
250 s
= search_function(ad1
, id
);
254 s_r
= search_function(ad2
, id_r
);
262 * and see which is better.
265 FuncDeclaration
*lastf
;
268 args1
.data
[0] = (void*) e1
;
270 args2
.data
[0] = (void*) e2
;
273 memset(&m
, 0, sizeof(m
));
274 m
.last
= MATCHnomatch
;
278 fd
= s
->isFuncDeclaration();
281 overloadResolveX(&m
, fd
, NULL
, &args2
);
284 { td
= s
->isTemplateDeclaration();
285 templateResolve(&m
, td
, sc
, loc
, NULL
, NULL
, &args2
);
293 fd
= s_r
->isFuncDeclaration();
296 overloadResolveX(&m
, fd
, NULL
, &args1
);
299 { td
= s_r
->isTemplateDeclaration();
300 templateResolve(&m
, td
, sc
, loc
, NULL
, NULL
, &args1
);
307 error("overloads %s and %s both match argument list for %s",
308 m
.lastf
->type
->toChars(),
309 m
.nextf
->type
->toChars(),
312 else if (m
.last
== MATCHnomatch
)
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
);
327 // Rewrite (e1 op e2) as e2.opfunc_r(e1)
328 e
= build_overload(loc
, sc
, e2
, e1
, id_r
);
338 s_r
= search_function(ad1
, id_r
);
342 s
= search_function(ad2
, id
);
350 * and see which is better.
353 FuncDeclaration
*lastf
;
357 args1
.data
[0] = (void*) e1
;
359 args2
.data
[0] = (void*) e2
;
362 memset(&m
, 0, sizeof(m
));
363 m
.last
= MATCHnomatch
;
367 fd
= s_r
->isFuncDeclaration();
370 overloadResolveX(&m
, fd
, NULL
, &args2
);
373 { td
= s_r
->isTemplateDeclaration();
374 templateResolve(&m
, td
, sc
, loc
, NULL
, NULL
, &args2
);
381 fd
= s
->isFuncDeclaration();
384 overloadResolveX(&m
, fd
, NULL
, &args1
);
387 { td
= s
->isTemplateDeclaration();
388 templateResolve(&m
, td
, sc
, loc
, NULL
, NULL
, &args1
);
395 error("overloads %s and %s both match argument list for %s",
396 m
.lastf
->type
->toChars(),
397 m
.nextf
->type
->toChars(),
400 else if (m
.last
== MATCHnomatch
)
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
);
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
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
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
)
451 //printf("build_overload(id = '%s')\n", id->toChars());
453 //earg->type->print();
454 e
= new DotIdExp(loc
, ethis
, id
);
457 e
= new CallExp(loc
, e
, earg
);
459 e
= new CallExp(loc
, e
);
465 /***************************************
466 * Search for function funcid in aggregate ad.
469 Dsymbol
*search_function(ScopeDsymbol
*ad
, Identifier
*funcid
)
473 TemplateDeclaration
*td
;
475 s
= ad
->search(0, funcid
, 0);
479 //printf("search_function: s = '%s'\n", s->kind());
481 //printf("search_function: s2 = '%s'\n", s2->kind());
482 fd
= s2
->isFuncDeclaration();
483 if (fd
&& fd
->type
->ty
== Tfunction
)
486 td
= s2
->isTemplateDeclaration();
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
)
505 /* Return if no arguments need types.
507 for (size_t u
= 0; 1; u
++)
508 { if (u
== arguments
->dim
)
510 Argument
*arg
= (Argument
*)arguments
->data
[u
];
515 AggregateDeclaration
*ad
;
518 Argument
*arg
= (Argument
*)arguments
->data
[0];
519 Type
*taggr
= aggr
->type
;
522 Type
*tab
= taggr
->toBasetype();
528 if (arguments
->dim
== 2)
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
539 { TypeAArray
*taa
= (TypeAArray
*)tab
;
541 if (arguments
->dim
== 2)
544 arg
->type
= taa
->index
; // key type
545 arg
= (Argument
*)arguments
->data
[1];
548 arg
->type
= taa
->next
; // value type
553 ad
= ((TypeClass
*)tab
)->sym
;
557 ad
= ((TypeStruct
*)tab
)->sym
;
562 if (arguments
->dim
== 1)
566 /* Look for an opNext() overload
568 Dsymbol
*s
= search_function(ad
, Id::next
);
569 fd
= s
? s
->isFuncDeclaration() : NULL
;
572 arg
->type
= fd
->type
->next
;
579 * int opApply(int delegate(ref Type [, ...]) dg);
582 Dsymbol
*s
= search_function(ad
,
583 (op
== TOKforeach_reverse
) ? Id::applyReverse
587 fd
= s
->isFuncDeclaration();
589 inferApplyArgTypesX(fd
, arguments
);
596 if (0 && aggr
->op
== TOKdelegate
)
597 { DelegateExp
*de
= (DelegateExp
*)aggr
;
599 fd
= de
->func
->isFuncDeclaration();
601 inferApplyArgTypesX(fd
, arguments
);
605 inferApplyArgTypesY((TypeFunction
*)tab
->nextOf(), arguments
);
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)
626 if (arguments
->dim
== 0)
631 static void inferApplyArgTypesX(FuncDeclaration
*fstart
, Arguments
*arguments
)
633 overloadApply(fstart
, &fp3
, arguments
);
637 static void inferApplyArgTypesX(FuncDeclaration
*fstart
, Arguments
*arguments
)
642 for (d
= fstart
; d
; d
= next
)
645 FuncAliasDeclaration
*fa
;
648 fa
= d
->isFuncAliasDeclaration();
651 inferApplyArgTypesX(fa
->funcalias
, arguments
);
654 else if ((f
= d
->isFuncDeclaration()) != NULL
)
658 TypeFunction
*tf
= (TypeFunction
*)f
->type
;
659 if (inferApplyArgTypesY(tf
, arguments
) == 1)
661 if (arguments
->dim
== 0)
664 else if ((a
= d
->isAliasDeclaration()) != NULL
)
666 Dsymbol
*s
= a
->toAlias();
667 next
= s
->isDeclaration();
674 { d
->error("is aliased to a function");
681 /******************************
682 * Infer arguments from type of function.
684 * 0 match for this function
685 * 1 no match for this function
688 static int inferApplyArgTypesY(TypeFunction
*tf
, Arguments
*arguments
)
692 if (Argument::dim(tf
->parameters
) != 1)
694 p
= Argument::getNth(tf
->parameters
, 0);
695 if (p
->type
->ty
!= Tdelegate
)
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
);
714 { if (!arg
->type
->equals(param
->type
))
716 /* Cannot resolve argument types. Indicate an
717 * error by setting the number of arguments to 0.
724 arg
->type
= param
->type
;
733 /**************************************
736 static void templateResolve(Match
*m
, TemplateDeclaration
*td
, Scope
*sc
, Loc loc
, Objects
*targsi
, Expression
*ethis
, Expressions
*arguments
)
741 fd
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, ethis
, arguments
);
745 if (m
->last
>= MATCHexact
)
752 m
->last
= MATCHexact
;