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 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()
76 /***********************************
77 * Get Identifier for reverse operator overload,
78 * NULL if not supported for this operator.
81 Identifier
*Expression::opId_r()
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
)
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 /************************************
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
;
178 Type
*t1
= e1
->type
->toBasetype();
180 if (t1
->ty
== Tclass
)
182 ad
= ((TypeClass
*)t1
)->sym
;
185 else if (t1
->ty
== Tstruct
)
187 ad
= ((TypeStruct
*)t1
)->sym
;
190 fd
= search_function(ad
, opId());
196 ArrayExp
*ae
= (ArrayExp
*)this;
198 e
= new DotIdExp(loc
, e1
, fd
->ident
);
199 e
= new CallExp(loc
, e
, ae
->arguments
);
205 // Rewrite +e1 as e1.add()
206 return build_overload(loc
, sc
, e1
, NULL
, fd
->ident
);
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();
229 AggregateDeclaration
*ad1
;
230 if (t1
->ty
== Tclass
)
231 ad1
= ((TypeClass
*)t1
)->sym
;
232 else if (t1
->ty
== Tstruct
)
233 ad1
= ((TypeStruct
*)t1
)->sym
;
237 AggregateDeclaration
*ad2
;
238 if (t2
->ty
== Tclass
)
239 ad2
= ((TypeClass
*)t2
)->sym
;
240 else if (t2
->ty
== Tstruct
)
241 ad2
= ((TypeStruct
*)t2
)->sym
;
247 FuncDeclaration
*fd
= NULL
;
248 TemplateDeclaration
*td
= NULL
;
251 s
= search_function(ad1
, id
);
255 s_r
= search_function(ad2
, id_r
);
263 * and see which is better.
266 FuncDeclaration
*lastf
;
269 args1
.data
[0] = (void*) e1
;
271 args2
.data
[0] = (void*) e2
;
274 memset(&m
, 0, sizeof(m
));
275 m
.last
= MATCHnomatch
;
279 fd
= s
->isFuncDeclaration();
282 overloadResolveX(&m
, fd
, &args2
);
285 { td
= s
->isTemplateDeclaration();
286 templateResolve(&m
, td
, sc
, loc
, NULL
, &args2
);
294 fd
= s_r
->isFuncDeclaration();
297 overloadResolveX(&m
, fd
, &args1
);
300 { td
= s_r
->isTemplateDeclaration();
301 templateResolve(&m
, td
, sc
, loc
, NULL
, &args1
);
308 error("overloads %s and %s both match argument list for %s",
309 m
.lastf
->type
->toChars(),
310 m
.nextf
->type
->toChars(),
313 else if (m
.last
== MATCHnomatch
)
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
);
328 // Rewrite (e1 op e2) as e2.opfunc_r(e1)
329 e
= build_overload(loc
, sc
, e2
, e1
, id_r
);
339 s_r
= search_function(ad1
, id_r
);
343 s
= search_function(ad2
, id
);
351 * and see which is better.
354 FuncDeclaration
*lastf
;
358 args1
.data
[0] = (void*) e1
;
360 args2
.data
[0] = (void*) e2
;
363 memset(&m
, 0, sizeof(m
));
364 m
.last
= MATCHnomatch
;
368 fd
= s_r
->isFuncDeclaration();
371 overloadResolveX(&m
, fd
, &args2
);
374 { td
= s_r
->isTemplateDeclaration();
375 templateResolve(&m
, td
, sc
, loc
, NULL
, &args2
);
382 fd
= s
->isFuncDeclaration();
385 overloadResolveX(&m
, fd
, &args1
);
388 { td
= s
->isTemplateDeclaration();
389 templateResolve(&m
, td
, sc
, loc
, NULL
, &args1
);
396 error("overloads %s and %s both match argument list for %s",
397 m
.lastf
->type
->toChars(),
398 m
.nextf
->type
->toChars(),
401 else if (m
.last
== MATCHnomatch
)
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
);
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
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
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
)
452 //printf("build_overload(id = '%s')\n", id->toChars());
454 //earg->type->print();
455 e
= new DotIdExp(loc
, ethis
, id
);
458 e
= new CallExp(loc
, e
, earg
);
460 e
= new CallExp(loc
, e
);
466 /***************************************
467 * Search for function funcid in aggregate ad.
470 Dsymbol
*search_function(AggregateDeclaration
*ad
, Identifier
*funcid
)
474 TemplateDeclaration
*td
;
476 s
= ad
->search(0, funcid
, 0);
480 //printf("search_function: s = '%s'\n", s->kind());
482 //printf("search_function: s2 = '%s'\n", s2->kind());
483 fd
= s2
->isFuncDeclaration();
484 if (fd
&& fd
->type
->ty
== Tfunction
)
487 td
= s2
->isTemplateDeclaration();
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
)
506 /* Return if no arguments need types.
508 for (size_t u
= 0; 1; u
++)
509 { if (u
== arguments
->dim
)
511 Argument
*arg
= (Argument
*)arguments
->data
[u
];
516 AggregateDeclaration
*ad
;
519 Argument
*arg
= (Argument
*)arguments
->data
[0];
520 Type
*taggr
= aggr
->type
;
523 Type
*tab
= taggr
->toBasetype();
529 if (arguments
->dim
== 2)
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
540 { TypeAArray
*taa
= (TypeAArray
*)tab
;
542 if (arguments
->dim
== 2)
545 arg
->type
= taa
->index
; // key type
546 arg
= (Argument
*)arguments
->data
[1];
549 arg
->type
= taa
->next
; // value type
554 ad
= ((TypeClass
*)tab
)->sym
;
558 ad
= ((TypeStruct
*)tab
)->sym
;
563 if (arguments
->dim
== 1)
567 /* Look for an opNext() overload
569 Dsymbol
*s
= search_function(ad
, Id::next
);
570 fd
= s
? s
->isFuncDeclaration() : NULL
;
573 arg
->type
= fd
->type
->next
;
580 * int opApply(int delegate(ref Type [, ...]) dg);
583 Dsymbol
*s
= search_function(ad
,
584 (op
== TOKforeach_reverse
) ? Id::applyReverse
588 fd
= s
->isFuncDeclaration();
590 inferApplyArgTypesX(fd
, arguments
);
597 if (0 && aggr
->op
== TOKdelegate
)
598 { DelegateExp
*de
= (DelegateExp
*)aggr
;
600 fd
= de
->func
->isFuncDeclaration();
602 inferApplyArgTypesX(fd
, arguments
);
606 inferApplyArgTypesY((TypeFunction
*)tab
->nextOf(), arguments
);
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)
627 if (arguments
->dim
== 0)
632 static void inferApplyArgTypesX(FuncDeclaration
*fstart
, Arguments
*arguments
)
634 overloadApply(fstart
, &fp3
, arguments
);
638 static void inferApplyArgTypesX(FuncDeclaration
*fstart
, Arguments
*arguments
)
643 for (d
= fstart
; d
; d
= next
)
646 FuncAliasDeclaration
*fa
;
649 fa
= d
->isFuncAliasDeclaration();
652 inferApplyArgTypesX(fa
->funcalias
, arguments
);
655 else if ((f
= d
->isFuncDeclaration()) != NULL
)
659 TypeFunction
*tf
= (TypeFunction
*)f
->type
;
660 if (inferApplyArgTypesY(tf
, arguments
) == 1)
662 if (arguments
->dim
== 0)
665 else if ((a
= d
->isAliasDeclaration()) != NULL
)
667 Dsymbol
*s
= a
->toAlias();
668 next
= s
->isDeclaration();
675 { d
->error("is aliased to a function");
682 /******************************
683 * Infer arguments from type of function.
685 * 0 match for this function
686 * 1 no match for this function
689 static int inferApplyArgTypesY(TypeFunction
*tf
, Arguments
*arguments
)
693 if (Argument::dim(tf
->parameters
) != 1)
695 p
= Argument::getNth(tf
->parameters
, 0);
696 if (p
->type
->ty
!= Tdelegate
)
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
);
715 { if (!arg
->type
->equals(param
->type
))
717 /* Cannot resolve argument types. Indicate an
718 * error by setting the number of arguments to 0.
725 arg
->type
= param
->type
;
734 /**************************************
737 static void templateResolve(Match
*m
, TemplateDeclaration
*td
, Scope
*sc
, Loc loc
, Objects
*targsi
, Expressions
*arguments
)
742 fd
= td
->deduceFunctionTemplate(sc
, loc
, targsi
, arguments
);
746 if (m
->last
>= MATCHexact
)
753 m
->last
= MATCHexact
;