Mercurial > projects > ldc
annotate dmd/template.c @ 1138:4c8bb03e4fbc
Update DtoConstFP() to be correct after LLVM r67562, which changed the way the
APFloat constructor expects its i80 APInts to be formatted. (They're now
actually consistent with the x87 format)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 24 Mar 2009 15:24:59 +0100 |
parents | b30fe7e1dbb9 |
children | 1860414bf3b7 |
rev | line source |
---|---|
336 | 1 |
2 // Compiler implementation of the D programming language | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3 // Copyright (c) 1999-2009 by Digital Mars |
336 | 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 // Handle template implementation | |
12 | |
13 #include <stdio.h> | |
14 #include <assert.h> | |
15 | |
16 #if !IN_LLVM | |
17 #if _WIN32 | |
18 #include <windows.h> | |
19 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); | |
20 #endif | |
21 #endif | |
22 | |
23 #include "root.h" | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
24 #include "rmem.h" |
336 | 25 #include "stringtable.h" |
26 #include "mars.h" | |
27 #include "identifier.h" | |
28 #include "mtype.h" | |
29 #include "template.h" | |
30 #include "init.h" | |
31 #include "expression.h" | |
32 #include "scope.h" | |
33 #include "module.h" | |
34 #include "aggregate.h" | |
35 #include "declaration.h" | |
36 #include "dsymbol.h" | |
37 #include "hdrgen.h" | |
38 | |
39 #define LOG 0 | |
40 | |
41 /******************************************** | |
42 * These functions substitute for dynamic_cast. dynamic_cast does not work | |
43 * on earlier versions of gcc. | |
44 */ | |
45 | |
46 Expression *isExpression(Object *o) | |
47 { | |
48 //return dynamic_cast<Expression *>(o); | |
49 if (!o || o->dyncast() != DYNCAST_EXPRESSION) | |
50 return NULL; | |
51 return (Expression *)o; | |
52 } | |
53 | |
54 Dsymbol *isDsymbol(Object *o) | |
55 { | |
56 //return dynamic_cast<Dsymbol *>(o); | |
57 if (!o || o->dyncast() != DYNCAST_DSYMBOL) | |
58 return NULL; | |
59 return (Dsymbol *)o; | |
60 } | |
61 | |
62 Type *isType(Object *o) | |
63 { | |
64 //return dynamic_cast<Type *>(o); | |
65 if (!o || o->dyncast() != DYNCAST_TYPE) | |
66 return NULL; | |
67 return (Type *)o; | |
68 } | |
69 | |
70 Tuple *isTuple(Object *o) | |
71 { | |
72 //return dynamic_cast<Tuple *>(o); | |
73 if (!o || o->dyncast() != DYNCAST_TUPLE) | |
74 return NULL; | |
75 return (Tuple *)o; | |
76 } | |
77 | |
78 | |
79 /*********************** | |
80 * Try to get arg as a type. | |
81 */ | |
82 | |
83 Type *getType(Object *o) | |
84 { | |
85 Type *t = isType(o); | |
86 if (!t) | |
87 { Expression *e = isExpression(o); | |
88 if (e) | |
89 t = e->type; | |
90 } | |
91 return t; | |
92 } | |
93 | |
94 Dsymbol *getDsymbol(Object *oarg) | |
95 { | |
96 Dsymbol *sa; | |
97 Expression *ea = isExpression(oarg); | |
98 if (ea) | |
99 { // Try to convert Expression to symbol | |
100 if (ea->op == TOKvar) | |
101 sa = ((VarExp *)ea)->var; | |
102 else if (ea->op == TOKfunction) | |
103 sa = ((FuncExp *)ea)->fd; | |
104 else | |
105 sa = NULL; | |
106 } | |
107 else | |
108 { // Try to convert Type to symbol | |
109 Type *ta = isType(oarg); | |
110 if (ta) | |
111 sa = ta->toDsymbol(NULL); | |
112 else | |
113 sa = isDsymbol(oarg); // if already a symbol | |
114 } | |
115 return sa; | |
116 } | |
117 | |
118 /****************************** | |
119 * If o1 matches o2, return 1. | |
120 * Else, return 0. | |
121 */ | |
122 | |
123 int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) | |
124 { | |
125 Type *t1 = isType(o1); | |
126 Type *t2 = isType(o2); | |
127 Expression *e1 = isExpression(o1); | |
128 Expression *e2 = isExpression(o2); | |
129 Dsymbol *s1 = isDsymbol(o1); | |
130 Dsymbol *s2 = isDsymbol(o2); | |
131 Tuple *v1 = isTuple(o1); | |
132 Tuple *v2 = isTuple(o2); | |
133 | |
134 //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2); | |
135 | |
136 /* A proper implementation of the various equals() overrides | |
137 * should make it possible to just do o1->equals(o2), but | |
138 * we'll do that another day. | |
139 */ | |
140 | |
141 if (t1) | |
142 { | |
143 /* if t1 is an instance of ti, then give error | |
144 * about recursive expansions. | |
145 */ | |
146 Dsymbol *s = t1->toDsymbol(sc); | |
147 if (s && s->parent) | |
148 { TemplateInstance *ti1 = s->parent->isTemplateInstance(); | |
149 if (ti1 && ti1->tempdecl == tempdecl) | |
150 { | |
151 for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing) | |
152 { | |
153 if (sc1->scopesym == ti1) | |
154 { | |
155 error("recursive template expansion for template argument %s", t1->toChars()); | |
156 return 1; // fake a match | |
157 } | |
158 } | |
159 } | |
160 } | |
161 | |
162 if (!t2 || !t1->equals(t2)) | |
163 goto Lnomatch; | |
164 } | |
165 else if (e1) | |
166 { | |
167 #if 0 | |
168 if (e1 && e2) | |
169 { | |
170 printf("match %d\n", e1->equals(e2)); | |
171 e1->print(); | |
172 e2->print(); | |
173 e1->type->print(); | |
174 e2->type->print(); | |
175 } | |
176 #endif | |
177 if (!e2) | |
178 goto Lnomatch; | |
179 if (!e1->equals(e2)) | |
180 goto Lnomatch; | |
181 } | |
182 else if (s1) | |
183 { | |
184 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars()); | |
185 if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) | |
186 { | |
187 goto Lnomatch; | |
188 } | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
189 #if V2 |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
190 VarDeclaration *v1 = s1->isVarDeclaration(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
191 VarDeclaration *v2 = s2->isVarDeclaration(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
192 if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
193 { ExpInitializer *ei1 = v1->init->isExpInitializer(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
194 ExpInitializer *ei2 = v2->init->isExpInitializer(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
195 if (ei1 && ei2 && !ei1->exp->equals(ei2->exp)) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
196 goto Lnomatch; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
197 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
198 #endif |
336 | 199 } |
200 else if (v1) | |
201 { | |
202 if (!v2) | |
203 goto Lnomatch; | |
204 if (v1->objects.dim != v2->objects.dim) | |
205 goto Lnomatch; | |
206 for (size_t i = 0; i < v1->objects.dim; i++) | |
207 { | |
208 if (!match((Object *)v1->objects.data[i], | |
209 (Object *)v2->objects.data[i], | |
210 tempdecl, sc)) | |
211 goto Lnomatch; | |
212 } | |
213 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
214 //printf("match\n"); |
336 | 215 return 1; // match |
216 Lnomatch: | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
217 //printf("nomatch\n"); |
336 | 218 return 0; // nomatch; |
219 } | |
220 | |
221 /**************************************** | |
222 */ | |
223 | |
224 void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg) | |
225 { | |
226 //printf("ObjectToCBuffer()\n"); | |
227 Type *t = isType(oarg); | |
228 Expression *e = isExpression(oarg); | |
229 Dsymbol *s = isDsymbol(oarg); | |
230 Tuple *v = isTuple(oarg); | |
231 if (t) | |
232 { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty); | |
233 t->toCBuffer(buf, NULL, hgs); | |
234 } | |
235 else if (e) | |
236 e->toCBuffer(buf, hgs); | |
237 else if (s) | |
238 { | |
239 char *p = s->ident ? s->ident->toChars() : s->toChars(); | |
240 buf->writestring(p); | |
241 } | |
242 else if (v) | |
243 { | |
244 Objects *args = &v->objects; | |
245 for (size_t i = 0; i < args->dim; i++) | |
246 { | |
247 if (i) | |
248 buf->writeByte(','); | |
249 Object *o = (Object *)args->data[i]; | |
250 ObjectToCBuffer(buf, hgs, o); | |
251 } | |
252 } | |
253 else if (!oarg) | |
254 { | |
255 buf->writestring("NULL"); | |
256 } | |
257 else | |
258 { | |
259 #ifdef DEBUG | |
260 printf("bad Object = %p\n", oarg); | |
261 #endif | |
262 assert(0); | |
263 } | |
264 } | |
265 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
266 #if V2 |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
267 Object *objectSyntaxCopy(Object *o) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
268 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
269 if (!o) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
270 return NULL; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
271 Type *t = isType(o); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
272 if (t) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
273 return t->syntaxCopy(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
274 Expression *e = isExpression(o); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
275 if (e) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
276 return e->syntaxCopy(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
277 return o; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
278 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
279 #endif |
336 | 280 |
281 | |
282 /* ======================== TemplateDeclaration ============================= */ | |
283 | |
284 TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs) | |
285 : ScopeDsymbol(id) | |
286 { | |
287 #if LOG | |
288 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars()); | |
289 #endif | |
290 #if 0 | |
291 if (parameters) | |
292 for (int i = 0; i < parameters->dim; i++) | |
293 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
294 //printf("\tparameter[%d] = %p\n", i, tp); | |
295 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); | |
296 | |
297 if (ttp) | |
298 { | |
299 printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); | |
300 } | |
301 } | |
302 #endif | |
303 this->loc = loc; | |
304 this->parameters = parameters; | |
305 this->origParameters = parameters; | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
306 #if V2 |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
307 this->constraint = constraint; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
308 #endif |
336 | 309 this->members = decldefs; |
310 this->overnext = NULL; | |
311 this->overroot = NULL; | |
312 this->scope = NULL; | |
313 this->onemember = NULL; | |
314 } | |
315 | |
316 Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) | |
317 { | |
318 //printf("TemplateDeclaration::syntaxCopy()\n"); | |
319 TemplateDeclaration *td; | |
320 TemplateParameters *p; | |
321 Array *d; | |
322 | |
323 p = NULL; | |
324 if (parameters) | |
325 { | |
326 p = new TemplateParameters(); | |
327 p->setDim(parameters->dim); | |
328 for (int i = 0; i < p->dim; i++) | |
329 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
330 p->data[i] = (void *)tp->syntaxCopy(); | |
331 } | |
332 } | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
333 #if V2 |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
334 Expression *e = NULL; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
335 if (constraint) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
336 e = constraint->syntaxCopy(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
337 #endif |
336 | 338 d = Dsymbol::arraySyntaxCopy(members); |
339 td = new TemplateDeclaration(loc, ident, p, d); | |
527
cecfee2d01a8
Added support for overloaded intrinsics.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
340 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
561
diff
changeset
|
341 // LDC |
527
cecfee2d01a8
Added support for overloaded intrinsics.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
342 td->intrinsicName = intrinsicName; |
cecfee2d01a8
Added support for overloaded intrinsics.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
343 |
336 | 344 return td; |
345 } | |
346 | |
347 void TemplateDeclaration::semantic(Scope *sc) | |
348 { | |
349 #if LOG | |
350 printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars()); | |
351 #endif | |
352 if (scope) | |
353 return; // semantic() already run | |
354 | |
355 if (sc->func) | |
356 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
357 #if DMDV1 |
336 | 358 error("cannot declare template at function scope %s", sc->func->toChars()); |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
359 #endif |
336 | 360 } |
361 | |
362 if (/*global.params.useArrayBounds &&*/ sc->module) | |
363 { | |
364 // Generate this function as it may be used | |
365 // when template is instantiated in other modules | |
366 sc->module->toModuleArray(); | |
367 } | |
368 | |
369 if (/*global.params.useAssert &&*/ sc->module) | |
370 { | |
371 // Generate this function as it may be used | |
372 // when template is instantiated in other modules | |
373 sc->module->toModuleAssert(); | |
374 } | |
375 | |
376 /* Remember Scope for later instantiations, but make | |
377 * a copy since attributes can change. | |
378 */ | |
379 this->scope = new Scope(*sc); | |
380 this->scope->setNoFree(); | |
381 | |
382 // Set up scope for parameters | |
383 ScopeDsymbol *paramsym = new ScopeDsymbol(); | |
384 paramsym->parent = sc->parent; | |
385 Scope *paramscope = sc->push(paramsym); | |
386 paramscope->parameterSpecialization = 1; | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
387 paramscope->stc = 0; |
336 | 388 |
389 if (global.params.doDocComments) | |
390 { | |
391 origParameters = new TemplateParameters(); | |
392 origParameters->setDim(parameters->dim); | |
393 for (int i = 0; i < parameters->dim; i++) | |
394 { | |
395 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
396 origParameters->data[i] = (void *)tp->syntaxCopy(); | |
397 } | |
398 } | |
399 | |
400 for (int i = 0; i < parameters->dim; i++) | |
401 { | |
402 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
403 | |
404 tp->declareParameter(paramscope); | |
405 } | |
406 | |
407 for (int i = 0; i < parameters->dim; i++) | |
408 { | |
409 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
410 | |
411 tp->semantic(paramscope); | |
412 if (i + 1 != parameters->dim && tp->isTemplateTupleParameter()) | |
413 error("template tuple parameter must be last one"); | |
414 } | |
415 | |
416 paramscope->pop(); | |
417 | |
418 if (members) | |
419 { | |
420 Dsymbol *s; | |
421 if (Dsymbol::oneMembers(members, &s)) | |
422 { | |
423 if (s && s->ident && s->ident->equals(ident)) | |
424 { | |
425 onemember = s; | |
426 s->parent = this; | |
427 } | |
428 } | |
429 } | |
430 | |
431 /* BUG: should check: | |
432 * o no virtual functions or non-static data members of classes | |
433 */ | |
434 } | |
435 | |
436 const char *TemplateDeclaration::kind() | |
437 { | |
438 return (onemember && onemember->isAggregateDeclaration()) | |
439 ? onemember->kind() | |
440 : (char *)"template"; | |
441 } | |
442 | |
443 /********************************** | |
444 * Overload existing TemplateDeclaration 'this' with the new one 's'. | |
445 * Return !=0 if successful; i.e. no conflict. | |
446 */ | |
447 | |
448 int TemplateDeclaration::overloadInsert(Dsymbol *s) | |
449 { | |
450 TemplateDeclaration **pf; | |
451 TemplateDeclaration *f; | |
452 | |
453 #if LOG | |
454 printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars()); | |
455 #endif | |
456 f = s->isTemplateDeclaration(); | |
457 if (!f) | |
458 return FALSE; | |
459 TemplateDeclaration *pthis = this; | |
460 for (pf = &pthis; *pf; pf = &(*pf)->overnext) | |
461 { | |
462 #if 0 | |
463 // Conflict if TemplateParameter's match | |
464 // Will get caught anyway later with TemplateInstance, but | |
465 // should check it now. | |
466 TemplateDeclaration *f2 = *pf; | |
467 | |
468 if (f->parameters->dim != f2->parameters->dim) | |
469 goto Lcontinue; | |
470 | |
471 for (int i = 0; i < f->parameters->dim; i++) | |
472 { TemplateParameter *p1 = (TemplateParameter *)f->parameters->data[i]; | |
473 TemplateParameter *p2 = (TemplateParameter *)f2->parameters->data[i]; | |
474 | |
475 if (!p1->overloadMatch(p2)) | |
476 goto Lcontinue; | |
477 } | |
478 | |
479 #if LOG | |
480 printf("\tfalse: conflict\n"); | |
481 #endif | |
482 return FALSE; | |
483 | |
484 Lcontinue: | |
485 ; | |
486 #endif | |
487 } | |
488 | |
489 f->overroot = this; | |
490 *pf = f; | |
491 #if LOG | |
492 printf("\ttrue: no conflict\n"); | |
493 #endif | |
494 return TRUE; | |
495 } | |
496 | |
497 /*************************************** | |
498 * Given that ti is an instance of this TemplateDeclaration, | |
499 * deduce the types of the parameters to this, and store | |
500 * those deduced types in dedtypes[]. | |
501 * Input: | |
502 * flag 1: don't do semantic() because of dummy types | |
503 * 2: don't change types in matchArg() | |
504 * Output: | |
505 * dedtypes deduced arguments | |
506 * Return match level. | |
507 */ | |
508 | |
509 MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, | |
510 Objects *dedtypes, int flag) | |
511 { MATCH m; | |
512 int dedtypes_dim = dedtypes->dim; | |
513 | |
514 #define LOGM 0 | |
515 #if LOGM | |
516 printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag); | |
517 #endif | |
518 | |
519 #if 0 | |
520 printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim); | |
521 if (ti->tiargs->dim) | |
522 printf("ti->tiargs->dim = %d, [0] = %p\n", | |
523 ti->tiargs->dim, | |
524 ti->tiargs->data[0]); | |
525 #endif | |
526 dedtypes->zero(); | |
527 | |
528 int parameters_dim = parameters->dim; | |
529 int variadic = isVariadic() != NULL; | |
530 | |
531 // If more arguments than parameters, no match | |
532 if (ti->tiargs->dim > parameters_dim && !variadic) | |
533 { | |
534 #if LOGM | |
535 printf(" no match: more arguments than parameters\n"); | |
536 #endif | |
537 return MATCHnomatch; | |
538 } | |
539 | |
540 assert(dedtypes_dim == parameters_dim); | |
541 assert(dedtypes_dim >= ti->tiargs->dim || variadic); | |
542 | |
543 // Set up scope for parameters | |
544 assert((size_t)scope > 0x10000); | |
545 ScopeDsymbol *paramsym = new ScopeDsymbol(); | |
546 paramsym->parent = scope->parent; | |
547 Scope *paramscope = scope->push(paramsym); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
548 paramscope->stc = 0; |
336 | 549 |
550 // Attempt type deduction | |
551 m = MATCHexact; | |
552 for (int i = 0; i < dedtypes_dim; i++) | |
553 { MATCH m2; | |
554 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
555 Declaration *sparam; | |
556 | |
557 //printf("\targument [%d]\n", i); | |
558 #if LOGM | |
559 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); | |
560 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); | |
561 if (ttp) | |
562 printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); | |
563 #endif | |
564 | |
565 #if DMDV1 | |
566 m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam); | |
567 #else | |
568 m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0); | |
569 | |
570 #endif | |
571 //printf("\tm2 = %d\n", m2); | |
572 | |
573 if (m2 == MATCHnomatch) | |
574 { | |
575 #if 0 | |
576 printf("\tmatchArg() for parameter %i failed\n", i); | |
577 #endif | |
578 goto Lnomatch; | |
579 } | |
580 | |
581 if (m2 < m) | |
582 m = m2; | |
583 | |
584 if (!flag) | |
585 sparam->semantic(paramscope); | |
586 if (!paramscope->insert(sparam)) | |
587 goto Lnomatch; | |
588 } | |
589 | |
590 if (!flag) | |
591 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
592 /* Any parameter left without a type gets the type of |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
593 * its corresponding arg |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
594 */ |
336 | 595 for (int i = 0; i < dedtypes_dim; i++) |
596 { | |
597 if (!dedtypes->data[i]) | |
598 { assert(i < ti->tiargs->dim); | |
599 dedtypes->data[i] = ti->tiargs->data[i]; | |
600 } | |
601 } | |
602 } | |
603 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
604 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
605 if (m && constraint && !(flag & 1)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
606 { /* Check to see if constraint is satisfied. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
607 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
608 Expression *e = constraint->syntaxCopy(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
609 paramscope->flags |= SCOPEstaticif; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
610 e = e->semantic(paramscope); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
611 e = e->optimize(WANTvalue | WANTinterpret); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
612 if (e->isBool(TRUE)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
613 ; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
614 else if (e->isBool(FALSE)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
615 goto Lnomatch; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
616 else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
617 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
618 e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
619 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
620 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
621 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
622 |
336 | 623 #if LOGM |
624 // Print out the results | |
625 printf("--------------------------\n"); | |
626 printf("template %s\n", toChars()); | |
627 printf("instance %s\n", ti->toChars()); | |
628 if (m) | |
629 { | |
630 for (int i = 0; i < dedtypes_dim; i++) | |
631 { | |
632 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
633 Object *oarg; | |
634 | |
635 printf(" [%d]", i); | |
636 | |
637 if (i < ti->tiargs->dim) | |
638 oarg = (Object *)ti->tiargs->data[i]; | |
639 else | |
640 oarg = NULL; | |
641 tp->print(oarg, (Object *)dedtypes->data[i]); | |
642 } | |
643 } | |
644 else | |
645 goto Lnomatch; | |
646 #endif | |
647 | |
648 #if LOGM | |
649 printf(" match = %d\n", m); | |
650 #endif | |
651 goto Lret; | |
652 | |
653 Lnomatch: | |
654 #if LOGM | |
655 printf(" no match\n"); | |
656 #endif | |
657 m = MATCHnomatch; | |
658 | |
659 Lret: | |
660 paramscope->pop(); | |
661 #if LOGM | |
662 printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); | |
663 #endif | |
664 return m; | |
665 } | |
666 | |
667 /******************************************** | |
668 * Determine partial specialization order of 'this' vs td2. | |
669 * Returns: | |
670 * 1 this is at least as specialized as td2 | |
671 * 0 td2 is more specialized than this | |
672 */ | |
673 | |
674 int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) | |
675 { | |
676 /* This works by taking the template parameters to this template | |
677 * declaration and feeding them to td2 as if it were a template | |
678 * instance. | |
679 * If it works, then this template is at least as specialized | |
680 * as td2. | |
681 */ | |
682 | |
683 TemplateInstance ti(0, ident); // create dummy template instance | |
684 Objects dedtypes; | |
685 | |
686 #define LOG_LEASTAS 0 | |
687 | |
688 #if LOG_LEASTAS | |
689 printf("%s.leastAsSpecialized(%s)\n", toChars(), td2->toChars()); | |
690 #endif | |
691 | |
692 // Set type arguments to dummy template instance to be types | |
693 // generated from the parameters to this template declaration | |
694 ti.tiargs = new Objects(); | |
695 ti.tiargs->setDim(parameters->dim); | |
696 for (int i = 0; i < ti.tiargs->dim; i++) | |
697 { | |
698 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
699 | |
700 void *p = tp->dummyArg(); | |
701 if (p) | |
702 ti.tiargs->data[i] = p; | |
703 else | |
704 ti.tiargs->setDim(i); | |
705 } | |
706 | |
707 // Temporary Array to hold deduced types | |
708 //dedtypes.setDim(parameters->dim); | |
709 dedtypes.setDim(td2->parameters->dim); | |
710 | |
711 // Attempt a type deduction | |
712 if (td2->matchWithInstance(&ti, &dedtypes, 1)) | |
713 { | |
714 /* A non-variadic template is more specialized than a | |
715 * variadic one. | |
716 */ | |
717 if (isVariadic() && !td2->isVariadic()) | |
718 goto L1; | |
719 | |
720 #if LOG_LEASTAS | |
721 printf(" matches, so is least as specialized\n"); | |
722 #endif | |
723 return 1; | |
724 } | |
725 L1: | |
726 #if LOG_LEASTAS | |
727 printf(" doesn't match, so is not as specialized\n"); | |
728 #endif | |
729 return 0; | |
730 } | |
731 | |
732 | |
733 /************************************************* | |
734 * Match function arguments against a specific template function. | |
735 * Input: | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
736 * loc instantiation location |
336 | 737 * targsi Expression/Type initial list of template arguments |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
738 * ethis 'this' argument if !NULL |
336 | 739 * fargs arguments to function |
740 * Output: | |
741 * dedargs Expression/Type deduced template arguments | |
742 * Returns: | |
743 * match level | |
744 */ | |
745 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
746 MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi, |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
747 Expression *ethis, Expressions *fargs, |
336 | 748 Objects *dedargs) |
749 { | |
750 size_t i; | |
751 size_t nfparams; | |
752 size_t nfargs; | |
753 size_t nargsi; // array size of targsi | |
754 int fptupindex = -1; | |
755 int tuple_dim = 0; | |
756 MATCH match = MATCHexact; | |
757 FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); | |
758 TypeFunction *fdtype; // type of fd | |
759 TemplateTupleParameter *tp; | |
760 Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T | |
761 | |
762 #if 0 | |
763 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); | |
764 for (i = 0; i < fargs->dim; i++) | |
765 { Expression *e = (Expression *)fargs->data[i]; | |
766 printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars()); | |
767 } | |
768 #endif | |
769 | |
770 assert((size_t)scope > 0x10000); | |
771 | |
772 dedargs->setDim(parameters->dim); | |
773 dedargs->zero(); | |
774 | |
775 dedtypes.setDim(parameters->dim); | |
776 dedtypes.zero(); | |
777 | |
778 // Set up scope for parameters | |
779 ScopeDsymbol *paramsym = new ScopeDsymbol(); | |
780 paramsym->parent = scope->parent; | |
781 Scope *paramscope = scope->push(paramsym); | |
782 | |
783 tp = isVariadic(); | |
784 | |
785 nargsi = 0; | |
786 if (targsi) | |
787 { // Set initial template arguments | |
788 | |
789 nargsi = targsi->dim; | |
790 if (nargsi > parameters->dim) | |
791 { if (!tp) | |
792 goto Lnomatch; | |
793 dedargs->setDim(nargsi); | |
794 dedargs->zero(); | |
795 } | |
796 | |
797 memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data)); | |
798 | |
799 for (i = 0; i < nargsi; i++) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
800 { assert(i < parameters->dim); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
801 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
336 | 802 MATCH m; |
803 Declaration *sparam; | |
804 | |
805 m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); | |
806 //printf("\tdeduceType m = %d\n", m); | |
807 if (m == MATCHnomatch) | |
808 goto Lnomatch; | |
809 if (m < match) | |
810 match = m; | |
811 | |
812 sparam->semantic(paramscope); | |
813 if (!paramscope->insert(sparam)) | |
814 goto Lnomatch; | |
815 } | |
816 } | |
817 | |
818 assert(fd->type->ty == Tfunction); | |
819 fdtype = (TypeFunction *)fd->type; | |
820 | |
821 nfparams = Argument::dim(fdtype->parameters); // number of function parameters | |
822 nfargs = fargs->dim; // number of function arguments | |
823 | |
824 /* Check for match of function arguments with variadic template | |
825 * parameter, such as: | |
826 * | |
827 * template Foo(T, A...) { void Foo(T t, A a); } | |
828 * void main() { Foo(1,2,3); } | |
829 */ | |
830 tp = isVariadic(); | |
831 if (tp) // if variadic | |
832 { | |
833 if (nfparams == 0) // if no function parameters | |
834 { | |
835 Tuple *t = new Tuple(); | |
836 //printf("t = %p\n", t); | |
837 dedargs->data[parameters->dim - 1] = (void *)t; | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
838 declareParameter(paramscope, tp, t); |
336 | 839 goto L2; |
840 } | |
841 else if (nfargs < nfparams - 1) | |
842 goto L1; | |
843 else | |
844 { | |
845 /* Figure out which of the function parameters matches | |
846 * the tuple template parameter. Do this by matching | |
847 * type identifiers. | |
848 * Set the index of this function parameter to fptupindex. | |
849 */ | |
850 for (fptupindex = 0; fptupindex < nfparams; fptupindex++) | |
851 { | |
852 Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex]; | |
853 if (fparam->type->ty != Tident) | |
854 continue; | |
855 TypeIdentifier *tid = (TypeIdentifier *)fparam->type; | |
856 if (!tp->ident->equals(tid->ident) || tid->idents.dim) | |
857 continue; | |
858 | |
859 if (fdtype->varargs) // variadic function doesn't | |
860 goto Lnomatch; // go with variadic template | |
861 | |
862 /* The types of the function arguments | |
863 * now form the tuple argument. | |
864 */ | |
865 Tuple *t = new Tuple(); | |
866 dedargs->data[parameters->dim - 1] = (void *)t; | |
867 | |
868 tuple_dim = nfargs - (nfparams - 1); | |
869 t->objects.setDim(tuple_dim); | |
870 for (i = 0; i < tuple_dim; i++) | |
871 { Expression *farg = (Expression *)fargs->data[fptupindex + i]; | |
872 t->objects.data[i] = (void *)farg->type; | |
873 } | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
874 declareParameter(paramscope, tp, t); |
336 | 875 goto L2; |
876 } | |
877 fptupindex = -1; | |
878 } | |
879 } | |
880 | |
881 L1: | |
882 if (nfparams == nfargs) | |
883 ; | |
884 else if (nfargs > nfparams) | |
885 { | |
886 if (fdtype->varargs == 0) | |
887 goto Lnomatch; // too many args, no match | |
888 match = MATCHconvert; // match ... with a conversion | |
889 } | |
890 | |
891 L2: | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
892 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
893 // Match 'ethis' to any TemplateThisParameter's |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
894 if (ethis) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
895 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
896 for (size_t i = 0; i < parameters->dim; i++) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
897 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
898 TemplateThisParameter *ttp = tp->isTemplateThisParameter(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
899 if (ttp) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
900 { MATCH m; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
901 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
902 Type *t = new TypeIdentifier(0, ttp->ident); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
903 m = ethis->type->deduceType(scope, t, parameters, &dedtypes); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
904 if (!m) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
905 goto Lnomatch; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
906 if (m < match) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
907 match = m; // pick worst match |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
908 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
909 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
910 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
911 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
912 |
336 | 913 // Loop through the function parameters |
914 for (i = 0; i < nfparams; i++) | |
915 { | |
916 /* Skip over function parameters which wound up | |
917 * as part of a template tuple parameter. | |
918 */ | |
919 if (i == fptupindex) | |
920 { if (fptupindex == nfparams - 1) | |
921 break; | |
922 i += tuple_dim - 1; | |
923 continue; | |
924 } | |
925 | |
926 Argument *fparam = Argument::getNth(fdtype->parameters, i); | |
927 | |
928 if (i >= nfargs) // if not enough arguments | |
929 { | |
930 if (fparam->defaultArg) | |
931 { /* Default arguments do not participate in template argument | |
932 * deduction. | |
933 */ | |
934 goto Lmatch; | |
935 } | |
936 } | |
937 else | |
938 { Expression *farg = (Expression *)fargs->data[i]; | |
939 #if 0 | |
940 printf("\tfarg->type = %s\n", farg->type->toChars()); | |
941 printf("\tfparam->type = %s\n", fparam->type->toChars()); | |
942 #endif | |
943 | |
944 MATCH m; | |
945 m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes); | |
946 //printf("\tdeduceType m = %d\n", m); | |
947 | |
948 /* If no match, see if there's a conversion to a delegate | |
949 */ | |
950 if (!m && fparam->type->toBasetype()->ty == Tdelegate) | |
951 { | |
952 TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype(); | |
953 TypeFunction *tf = (TypeFunction *)td->next; | |
954 | |
955 if (!tf->varargs && Argument::dim(tf->parameters) == 0) | |
956 { | |
957 m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes); | |
958 if (!m && tf->next->toBasetype()->ty == Tvoid) | |
959 m = MATCHconvert; | |
960 } | |
961 //printf("\tm2 = %d\n", m); | |
962 } | |
963 | |
964 if (m) | |
965 { if (m < match) | |
966 match = m; // pick worst match | |
967 continue; | |
968 } | |
969 } | |
970 | |
971 /* The following code for variadic arguments closely | |
972 * matches TypeFunction::callMatch() | |
973 */ | |
974 if (!(fdtype->varargs == 2 && i + 1 == nfparams)) | |
975 goto Lnomatch; | |
976 | |
977 /* Check for match with function parameter T... | |
978 */ | |
979 Type *tb = fparam->type->toBasetype(); | |
980 switch (tb->ty) | |
981 { | |
982 // Perhaps we can do better with this, see TypeFunction::callMatch() | |
983 case Tsarray: | |
984 { TypeSArray *tsa = (TypeSArray *)tb; | |
985 integer_t sz = tsa->dim->toInteger(); | |
986 if (sz != nfargs - i) | |
987 goto Lnomatch; | |
988 } | |
989 case Tarray: | |
990 { TypeArray *ta = (TypeArray *)tb; | |
991 for (; i < nfargs; i++) | |
992 { | |
993 Expression *arg = (Expression *)fargs->data[i]; | |
994 assert(arg); | |
995 MATCH m; | |
996 /* If lazy array of delegates, | |
997 * convert arg(s) to delegate(s) | |
998 */ | |
999 Type *tret = fparam->isLazyArray(); | |
1000 if (tret) | |
1001 { | |
1002 if (ta->next->equals(arg->type)) | |
1003 { m = MATCHexact; | |
1004 } | |
1005 else | |
1006 { | |
1007 m = arg->implicitConvTo(tret); | |
1008 if (m == MATCHnomatch) | |
1009 { | |
1010 if (tret->toBasetype()->ty == Tvoid) | |
1011 m = MATCHconvert; | |
1012 } | |
1013 } | |
1014 } | |
1015 else | |
1016 { | |
1017 m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes); | |
1018 //m = arg->implicitConvTo(ta->next); | |
1019 } | |
1020 if (m == MATCHnomatch) | |
1021 goto Lnomatch; | |
1022 if (m < match) | |
1023 match = m; | |
1024 } | |
1025 goto Lmatch; | |
1026 } | |
1027 case Tclass: | |
1028 case Tident: | |
1029 goto Lmatch; | |
1030 | |
1031 default: | |
1032 goto Lnomatch; | |
1033 } | |
1034 } | |
1035 | |
1036 Lmatch: | |
1037 | |
1038 /* Fill in any missing arguments with their defaults. | |
1039 */ | |
1040 for (i = nargsi; i < dedargs->dim; i++) | |
1041 { | |
1042 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1043 //printf("tp[%d] = %s\n", i, tp->ident->toChars()); | |
1044 /* For T:T*, the dedargs is the T*, dedtypes is the T | |
1045 * But for function templates, we really need them to match | |
1046 */ | |
1047 Object *oarg = (Object *)dedargs->data[i]; | |
1048 Object *oded = (Object *)dedtypes.data[i]; | |
1049 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded); | |
1050 if (!oarg) | |
1051 { | |
1052 if (oded) | |
1053 { | |
1054 if (tp->specialization()) | |
1055 { /* The specialization can work as long as afterwards | |
1056 * the oded == oarg | |
1057 */ | |
1058 Declaration *sparam; | |
1059 dedargs->data[i] = (void *)oded; | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1060 MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam, 0); |
336 | 1061 //printf("m2 = %d\n", m2); |
1062 if (!m2) | |
1063 goto Lnomatch; | |
1064 if (m2 < match) | |
1065 match = m2; // pick worst match | |
1066 if (dedtypes.data[i] != oded) | |
1067 error("specialization not allowed for deduced parameter %s", tp->ident->toChars()); | |
1068 } | |
1069 } | |
1070 else | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1071 { oded = tp->defaultArg(loc, paramscope); |
336 | 1072 if (!oded) |
1073 goto Lnomatch; | |
1074 } | |
1075 declareParameter(paramscope, tp, oded); | |
1076 dedargs->data[i] = (void *)oded; | |
1077 } | |
1078 } | |
1079 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1080 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1081 if (constraint) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1082 { /* Check to see if constraint is satisfied. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1083 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1084 Expression *e = constraint->syntaxCopy(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1085 paramscope->flags |= SCOPEstaticif; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1086 e = e->semantic(paramscope); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1087 e = e->optimize(WANTvalue | WANTinterpret); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1088 if (e->isBool(TRUE)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1089 ; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1090 else if (e->isBool(FALSE)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1091 goto Lnomatch; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1092 else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1093 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1094 e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1095 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1096 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1097 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1098 |
336 | 1099 #if 0 |
1100 for (i = 0; i < dedargs->dim; i++) | |
1101 { Type *t = (Type *)dedargs->data[i]; | |
1102 printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars()); | |
1103 } | |
1104 #endif | |
1105 | |
1106 paramscope->pop(); | |
1107 //printf("\tmatch %d\n", match); | |
1108 return match; | |
1109 | |
1110 Lnomatch: | |
1111 paramscope->pop(); | |
1112 //printf("\tnomatch\n"); | |
1113 return MATCHnomatch; | |
1114 } | |
1115 | |
1116 /************************************************** | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1117 * Declare template parameter tp with value o, and install it in the scope sc. |
336 | 1118 */ |
1119 | |
1120 void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Object *o) | |
1121 { | |
1122 //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o); | |
1123 | |
1124 Type *targ = isType(o); | |
1125 Expression *ea = isExpression(o); | |
1126 Dsymbol *sa = isDsymbol(o); | |
1127 Tuple *va = isTuple(o); | |
1128 | |
1129 Dsymbol *s; | |
1130 | |
1131 if (targ) | |
1132 { | |
1133 //printf("type %s\n", targ->toChars()); | |
1134 s = new AliasDeclaration(0, tp->ident, targ); | |
1135 } | |
1136 else if (sa) | |
1137 { | |
1138 //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars()); | |
1139 s = new AliasDeclaration(0, tp->ident, sa); | |
1140 } | |
1141 else if (ea) | |
1142 { | |
1143 // tdtypes.data[i] always matches ea here | |
1144 Initializer *init = new ExpInitializer(loc, ea); | |
1145 TemplateValueParameter *tvp = tp->isTemplateValueParameter(); | |
1146 assert(tvp); | |
1147 | |
1148 VarDeclaration *v = new VarDeclaration(loc, tvp->valType, tp->ident, init); | |
1149 v->storage_class = STCconst; | |
1150 s = v; | |
1151 } | |
1152 else if (va) | |
1153 { | |
1154 //printf("\ttuple\n"); | |
1155 s = new TupleDeclaration(loc, tp->ident, &va->objects); | |
1156 } | |
1157 else | |
1158 { | |
1159 #ifdef DEBUG | |
1160 o->print(); | |
1161 #endif | |
1162 assert(0); | |
1163 } | |
1164 if (!sc->insert(s)) | |
1165 error("declaration %s is already defined", tp->ident->toChars()); | |
1166 s->semantic(sc); | |
1167 } | |
1168 | |
1169 /************************************** | |
1170 * Determine if TemplateDeclaration is variadic. | |
1171 */ | |
1172 | |
1173 TemplateTupleParameter *isVariadic(TemplateParameters *parameters) | |
1174 { size_t dim = parameters->dim; | |
1175 TemplateTupleParameter *tp = NULL; | |
1176 | |
1177 if (dim) | |
1178 tp = ((TemplateParameter *)parameters->data[dim - 1])->isTemplateTupleParameter(); | |
1179 return tp; | |
1180 } | |
1181 | |
1182 TemplateTupleParameter *TemplateDeclaration::isVariadic() | |
1183 { | |
1184 return ::isVariadic(parameters); | |
1185 } | |
1186 | |
1187 /*********************************** | |
1188 * We can overload templates. | |
1189 */ | |
1190 | |
1191 int TemplateDeclaration::isOverloadable() | |
1192 { | |
1193 return 1; | |
1194 } | |
1195 | |
1196 /************************************************* | |
1197 * Given function arguments, figure out which template function | |
1198 * to expand, and return that function. | |
1199 * If no match, give error message and return NULL. | |
1200 * Input: | |
1201 * sc instantiation scope | |
1202 * loc instantiation location | |
1203 * targsi initial list of template arguments | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1204 * ethis if !NULL, the 'this' pointer argument |
336 | 1205 * fargs arguments to function |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1206 * flags 1: do not issue error message on no match, just return NULL |
336 | 1207 */ |
1208 | |
1209 FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1210 Objects *targsi, Expression *ethis, Expressions *fargs, int flags) |
336 | 1211 { |
1212 MATCH m_best = MATCHnomatch; | |
1213 TemplateDeclaration *td_ambig = NULL; | |
1214 TemplateDeclaration *td_best = NULL; | |
1215 Objects *tdargs = new Objects(); | |
1216 TemplateInstance *ti; | |
1217 FuncDeclaration *fd; | |
1218 | |
1219 #if 0 | |
1220 printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars()); | |
1221 printf(" targsi:\n"); | |
1222 if (targsi) | |
1223 { for (int i = 0; i < targsi->dim; i++) | |
1224 { Object *arg = (Object *)targsi->data[i]; | |
1225 printf("\t%s\n", arg->toChars()); | |
1226 } | |
1227 } | |
1228 printf(" fargs:\n"); | |
1229 for (int i = 0; i < fargs->dim; i++) | |
1230 { Expression *arg = (Expression *)fargs->data[i]; | |
1231 printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); | |
1232 //printf("\tty = %d\n", arg->type->ty); | |
1233 } | |
1234 #endif | |
1235 | |
1236 for (TemplateDeclaration *td = this; td; td = td->overnext) | |
1237 { | |
1238 if (!td->scope) | |
1239 { | |
1240 error("forward reference to template %s", td->toChars()); | |
1241 goto Lerror; | |
1242 } | |
1243 if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration()) | |
1244 { | |
1245 error("is not a function template"); | |
1246 goto Lerror; | |
1247 } | |
1248 | |
1249 MATCH m; | |
1250 Objects dedargs; | |
1251 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1252 m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs); |
336 | 1253 //printf("deduceFunctionTemplateMatch = %d\n", m); |
1254 if (!m) // if no match | |
1255 continue; | |
1256 | |
1257 if (m < m_best) | |
1258 goto Ltd_best; | |
1259 if (m > m_best) | |
1260 goto Ltd; | |
1261 | |
1262 { | |
1263 // Disambiguate by picking the most specialized TemplateDeclaration | |
1264 int c1 = td->leastAsSpecialized(td_best); | |
1265 int c2 = td_best->leastAsSpecialized(td); | |
1266 //printf("c1 = %d, c2 = %d\n", c1, c2); | |
1267 | |
1268 if (c1 > c2) | |
1269 goto Ltd; | |
1270 else if (c1 < c2) | |
1271 goto Ltd_best; | |
1272 else | |
1273 goto Lambig; | |
1274 } | |
1275 | |
1276 Lambig: // td_best and td are ambiguous | |
1277 td_ambig = td; | |
1278 continue; | |
1279 | |
1280 Ltd_best: // td_best is the best match so far | |
1281 td_ambig = NULL; | |
1282 continue; | |
1283 | |
1284 Ltd: // td is the new best match | |
1285 td_ambig = NULL; | |
1286 assert((size_t)td->scope > 0x10000); | |
1287 td_best = td; | |
1288 m_best = m; | |
1289 tdargs->setDim(dedargs.dim); | |
1290 memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *)); | |
1291 continue; | |
1292 } | |
1293 if (!td_best) | |
1294 { | |
1295 error(loc, "does not match any template declaration"); | |
1296 goto Lerror; | |
1297 } | |
1298 if (td_ambig) | |
1299 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1300 error(loc, "matches more than one function template declaration:\n %s\nand:\n %s", |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1301 td_best->toChars(), td_ambig->toChars()); |
336 | 1302 } |
1303 | |
1304 /* The best match is td_best with arguments tdargs. | |
1305 * Now instantiate the template. | |
1306 */ | |
1307 assert((size_t)td_best->scope > 0x10000); | |
1308 ti = new TemplateInstance(loc, td_best, tdargs); | |
1309 ti->semantic(sc); | |
1310 fd = ti->toAlias()->isFuncDeclaration(); | |
1311 if (!fd) | |
1312 goto Lerror; | |
1313 return fd; | |
1314 | |
1315 Lerror: | |
1316 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1317 HdrGenState hgs; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1318 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1319 OutBuffer bufa; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1320 Objects *args = targsi; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1321 if (args) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1322 { for (int i = 0; i < args->dim; i++) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1323 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1324 if (i) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1325 bufa.writeByte(','); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1326 Object *oarg = (Object *)args->data[i]; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1327 ObjectToCBuffer(&bufa, &hgs, oarg); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1328 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1329 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1330 |
336 | 1331 OutBuffer buf; |
1332 argExpTypesToCBuffer(&buf, fargs, &hgs); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1333 error(loc, "cannot deduce template function from argument types !(%s)(%s)", |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1334 bufa.toChars(), buf.toChars()); |
336 | 1335 } |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1336 return NULL; |
336 | 1337 } |
1338 | |
1339 void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1340 { | |
1341 #if 0 // Should handle template functions | |
1342 if (onemember && onemember->isFuncDeclaration()) | |
1343 buf->writestring("foo "); | |
1344 #endif | |
1345 buf->writestring(kind()); | |
1346 buf->writeByte(' '); | |
1347 buf->writestring(ident->toChars()); | |
1348 buf->writeByte('('); | |
1349 for (int i = 0; i < parameters->dim; i++) | |
1350 { | |
1351 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1352 if (hgs->ddoc) | |
1353 tp = (TemplateParameter *)origParameters->data[i]; | |
1354 if (i) | |
1355 buf->writeByte(','); | |
1356 tp->toCBuffer(buf, hgs); | |
1357 } | |
1358 buf->writeByte(')'); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1359 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1360 if (constraint) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1361 { buf->writestring(" if ("); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1362 constraint->toCBuffer(buf, hgs); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1363 buf->writeByte(')'); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1364 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1365 #endif |
336 | 1366 |
1367 if (hgs->hdrgen) | |
1368 { | |
1369 hgs->tpltMember++; | |
1370 buf->writenl(); | |
1371 buf->writebyte('{'); | |
1372 buf->writenl(); | |
1373 for (int i = 0; i < members->dim; i++) | |
1374 { | |
1375 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1376 s->toCBuffer(buf, hgs); | |
1377 } | |
1378 buf->writebyte('}'); | |
1379 buf->writenl(); | |
1380 hgs->tpltMember--; | |
1381 } | |
1382 } | |
1383 | |
1384 | |
1385 char *TemplateDeclaration::toChars() | |
1386 { OutBuffer buf; | |
1387 HdrGenState hgs; | |
1388 | |
1389 memset(&hgs, 0, sizeof(hgs)); | |
1390 buf.writestring(ident->toChars()); | |
1391 buf.writeByte('('); | |
1392 for (int i = 0; i < parameters->dim; i++) | |
1393 { | |
1394 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1395 if (i) | |
1396 buf.writeByte(','); | |
1397 tp->toCBuffer(&buf, &hgs); | |
1398 } | |
1399 buf.writeByte(')'); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1400 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1401 if (constraint) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1402 { buf.writestring(" if ("); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1403 constraint->toCBuffer(&buf, &hgs); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1404 buf.writeByte(')'); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1405 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1406 #endif |
336 | 1407 buf.writeByte(0); |
1408 return (char *)buf.extractData(); | |
1409 } | |
1410 | |
1411 /* ======================== Type ============================================ */ | |
1412 | |
1413 /**** | |
1414 * Given an identifier, figure out which TemplateParameter it is. | |
1415 * Return -1 if not found. | |
1416 */ | |
1417 | |
1418 int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters) | |
1419 { | |
1420 for (size_t i = 0; i < parameters->dim; i++) | |
1421 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1422 | |
1423 if (tp->ident->equals(id)) | |
1424 return i; | |
1425 } | |
1426 return -1; | |
1427 } | |
1428 | |
1429 int templateParameterLookup(Type *tparam, TemplateParameters *parameters) | |
1430 { | |
1431 assert(tparam->ty == Tident); | |
1432 TypeIdentifier *tident = (TypeIdentifier *)tparam; | |
1433 //printf("\ttident = '%s'\n", tident->toChars()); | |
1434 if (tident->idents.dim == 0) | |
1435 { | |
1436 return templateIdentifierLookup(tident->ident, parameters); | |
1437 } | |
1438 return -1; | |
1439 } | |
1440 | |
1441 /* These form the heart of template argument deduction. | |
1442 * Given 'this' being the type argument to the template instance, | |
1443 * it is matched against the template declaration parameter specialization | |
1444 * 'tparam' to determine the type to be used for the parameter. | |
1445 * Example: | |
1446 * template Foo(T:T*) // template declaration | |
1447 * Foo!(int*) // template instantiation | |
1448 * Input: | |
1449 * this = int* | |
1450 * tparam = T | |
1451 * parameters = [ T:T* ] // Array of TemplateParameter's | |
1452 * Output: | |
1453 * dedtypes = [ int ] // Array of Expression/Type's | |
1454 */ | |
1455 | |
1456 MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, | |
1457 Objects *dedtypes) | |
1458 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1459 #if 0 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1460 printf("Type::deduceType()\n"); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1461 printf("\tthis = %d, ", ty); print(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1462 printf("\ttparam = %d, ", tparam->ty); tparam->print(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
1463 #endif |
336 | 1464 if (!tparam) |
1465 goto Lnomatch; | |
1466 | |
1467 if (this == tparam) | |
1468 goto Lexact; | |
1469 | |
1470 if (tparam->ty == Tident) | |
1471 { | |
1472 // Determine which parameter tparam is | |
1473 int i = templateParameterLookup(tparam, parameters); | |
1474 if (i == -1) | |
1475 { | |
1476 if (!sc) | |
1477 goto Lnomatch; | |
1478 | |
1479 /* Need a loc to go with the semantic routine. | |
1480 */ | |
1481 Loc loc; | |
1482 if (parameters->dim) | |
1483 { | |
1484 TemplateParameter *tp = (TemplateParameter *)parameters->data[0]; | |
1485 loc = tp->loc; | |
1486 } | |
1487 | |
1488 /* BUG: what if tparam is a template instance, that | |
1489 * has as an argument another Tident? | |
1490 */ | |
1491 tparam = tparam->semantic(loc, sc); | |
1492 assert(tparam->ty != Tident); | |
1493 return deduceType(sc, tparam, parameters, dedtypes); | |
1494 } | |
1495 | |
1496 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1497 | |
1498 // Found the corresponding parameter tp | |
1499 if (!tp->isTemplateTypeParameter()) | |
1500 goto Lnomatch; | |
1501 Type *at = (Type *)dedtypes->data[i]; | |
1502 if (!at) | |
1503 { | |
1504 dedtypes->data[i] = (void *)this; | |
1505 goto Lexact; | |
1506 } | |
1507 if (equals(at)) | |
1508 goto Lexact; | |
1509 else if (ty == Tclass && at->ty == Tclass) | |
1510 { | |
1511 return (MATCH) implicitConvTo(at); | |
1512 } | |
1513 else if (ty == Tsarray && at->ty == Tarray && | |
1514 nextOf()->equals(at->nextOf())) | |
1515 { | |
1516 goto Lexact; | |
1517 } | |
1518 else | |
1519 goto Lnomatch; | |
1520 } | |
1521 | |
1522 if (ty != tparam->ty) | |
1523 return implicitConvTo(tparam); | |
1524 // goto Lnomatch; | |
1525 | |
1526 if (nextOf()) | |
1527 return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes); | |
1528 | |
1529 Lexact: | |
1530 return MATCHexact; | |
1531 | |
1532 Lnomatch: | |
1533 return MATCHnomatch; | |
1534 } | |
1535 | |
1536 MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, | |
1537 Objects *dedtypes) | |
1538 { | |
1539 #if 0 | |
1540 printf("TypeSArray::deduceType()\n"); | |
1541 printf("\tthis = %d, ", ty); print(); | |
1542 printf("\ttparam = %d, ", tparam->ty); tparam->print(); | |
1543 #endif | |
1544 | |
1545 // Extra check that array dimensions must match | |
1546 if (tparam) | |
1547 { | |
1548 if (tparam->ty == Tsarray) | |
1549 { | |
1550 TypeSArray *tp = (TypeSArray *)tparam; | |
1551 | |
1552 if (tp->dim->op == TOKvar && | |
1553 ((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter) | |
1554 { int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters); | |
1555 // This code matches code in TypeInstance::deduceType() | |
1556 if (i == -1) | |
1557 goto Lnomatch; | |
1558 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1559 TemplateValueParameter *tvp = tp->isTemplateValueParameter(); | |
1560 if (!tvp) | |
1561 goto Lnomatch; | |
1562 Expression *e = (Expression *)dedtypes->data[i]; | |
1563 if (e) | |
1564 { | |
1565 if (!dim->equals(e)) | |
1566 goto Lnomatch; | |
1567 } | |
1568 else | |
1569 { Type *vt = tvp->valType->semantic(0, sc); | |
1570 MATCH m = (MATCH)dim->implicitConvTo(vt); | |
1571 if (!m) | |
1572 goto Lnomatch; | |
1573 dedtypes->data[i] = dim; | |
1574 } | |
1575 } | |
1576 else if (dim->toInteger() != tp->dim->toInteger()) | |
1577 return MATCHnomatch; | |
1578 } | |
1579 else if (tparam->ty == Taarray) | |
1580 { | |
1581 TypeAArray *tp = (TypeAArray *)tparam; | |
1582 if (tp->index->ty == Tident) | |
1583 { TypeIdentifier *tident = (TypeIdentifier *)tp->index; | |
1584 | |
1585 if (tident->idents.dim == 0) | |
1586 { Identifier *id = tident->ident; | |
1587 | |
1588 for (size_t i = 0; i < parameters->dim; i++) | |
1589 { | |
1590 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
1591 | |
1592 if (tp->ident->equals(id)) | |
1593 { // Found the corresponding template parameter | |
1594 TemplateValueParameter *tvp = tp->isTemplateValueParameter(); | |
1595 if (!tvp || !tvp->valType->isintegral()) | |
1596 goto Lnomatch; | |
1597 | |
1598 if (dedtypes->data[i]) | |
1599 { | |
1600 if (!dim->equals((Object *)dedtypes->data[i])) | |
1601 goto Lnomatch; | |
1602 } | |
1603 else | |
1604 { dedtypes->data[i] = (void *)dim; | |
1605 } | |
1606 return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); | |
1607 } | |
1608 } | |
1609 } | |
1610 } | |
1611 } | |
1612 else if (tparam->ty == Tarray) | |
1613 { MATCH m; | |
1614 | |
1615 m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); | |
1616 if (m == MATCHexact) | |
1617 m = MATCHconvert; | |
1618 return m; | |
1619 } | |
1620 } | |
1621 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1622 | |
1623 Lnomatch: | |
1624 return MATCHnomatch; | |
1625 } | |
1626 | |
1627 MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
1628 { | |
1629 #if 0 | |
1630 printf("TypeAArray::deduceType()\n"); | |
1631 printf("\tthis = %d, ", ty); print(); | |
1632 printf("\ttparam = %d, ", tparam->ty); tparam->print(); | |
1633 #endif | |
1634 | |
1635 // Extra check that index type must match | |
1636 if (tparam && tparam->ty == Taarray) | |
1637 { | |
1638 TypeAArray *tp = (TypeAArray *)tparam; | |
1639 if (!index->deduceType(sc, tp->index, parameters, dedtypes)) | |
1640 { | |
1641 return MATCHnomatch; | |
1642 } | |
1643 } | |
1644 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1645 } | |
1646 | |
1647 MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
1648 { | |
1649 //printf("TypeFunction::deduceType()\n"); | |
1650 //printf("\tthis = %d, ", ty); print(); | |
1651 //printf("\ttparam = %d, ", tparam->ty); tparam->print(); | |
1652 | |
1653 // Extra check that function characteristics must match | |
1654 if (tparam && tparam->ty == Tfunction) | |
1655 { | |
1656 TypeFunction *tp = (TypeFunction *)tparam; | |
1657 if (varargs != tp->varargs || | |
1658 linkage != tp->linkage) | |
1659 return MATCHnomatch; | |
1660 | |
1661 size_t nfargs = Argument::dim(this->parameters); | |
1662 size_t nfparams = Argument::dim(tp->parameters); | |
1663 | |
1664 /* See if tuple match | |
1665 */ | |
1666 if (nfparams > 0 && nfargs >= nfparams - 1) | |
1667 { | |
1668 /* See if 'A' of the template parameter matches 'A' | |
1669 * of the type of the last function parameter. | |
1670 */ | |
1671 Argument *fparam = (Argument *)tp->parameters->data[nfparams - 1]; | |
1672 if (fparam->type->ty != Tident) | |
1673 goto L1; | |
1674 TypeIdentifier *tid = (TypeIdentifier *)fparam->type; | |
1675 if (tid->idents.dim) | |
1676 goto L1; | |
1677 | |
1678 /* Look through parameters to find tuple matching tid->ident | |
1679 */ | |
1680 size_t tupi = 0; | |
1681 for (; 1; tupi++) | |
1682 { if (tupi == parameters->dim) | |
1683 goto L1; | |
1684 TemplateParameter *t = (TemplateParameter *)parameters->data[tupi]; | |
1685 TemplateTupleParameter *tup = t->isTemplateTupleParameter(); | |
1686 if (tup && tup->ident->equals(tid->ident)) | |
1687 break; | |
1688 } | |
1689 | |
1690 /* The types of the function arguments [nfparams - 1 .. nfargs] | |
1691 * now form the tuple argument. | |
1692 */ | |
1693 int tuple_dim = nfargs - (nfparams - 1); | |
1694 | |
1695 /* See if existing tuple, and whether it matches or not | |
1696 */ | |
1697 Object *o = (Object *)dedtypes->data[tupi]; | |
1698 if (o) | |
1699 { // Existing deduced argument must be a tuple, and must match | |
1700 Tuple *t = isTuple(o); | |
1701 if (!t || t->objects.dim != tuple_dim) | |
1702 return MATCHnomatch; | |
1703 for (size_t i = 0; i < tuple_dim; i++) | |
1704 { Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i); | |
1705 if (!arg->type->equals((Object *)t->objects.data[i])) | |
1706 return MATCHnomatch; | |
1707 } | |
1708 } | |
1709 else | |
1710 { // Create new tuple | |
1711 Tuple *t = new Tuple(); | |
1712 t->objects.setDim(tuple_dim); | |
1713 for (size_t i = 0; i < tuple_dim; i++) | |
1714 { Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i); | |
1715 t->objects.data[i] = (void *)arg->type; | |
1716 } | |
1717 dedtypes->data[tupi] = (void *)t; | |
1718 } | |
1719 nfparams--; // don't consider the last parameter for type deduction | |
1720 goto L2; | |
1721 } | |
1722 | |
1723 L1: | |
1724 if (nfargs != nfparams) | |
1725 return MATCHnomatch; | |
1726 L2: | |
1727 for (size_t i = 0; i < nfparams; i++) | |
1728 { | |
1729 Argument *a = Argument::getNth(this->parameters, i); | |
1730 Argument *ap = Argument::getNth(tp->parameters, i); | |
1731 if (a->storageClass != ap->storageClass || | |
1732 !a->type->deduceType(sc, ap->type, parameters, dedtypes)) | |
1733 return MATCHnomatch; | |
1734 } | |
1735 } | |
1736 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1737 } | |
1738 | |
1739 MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
1740 { | |
1741 // Extra check | |
1742 if (tparam && tparam->ty == Tident) | |
1743 { | |
1744 TypeIdentifier *tp = (TypeIdentifier *)tparam; | |
1745 | |
1746 for (int i = 0; i < idents.dim; i++) | |
1747 { | |
1748 Identifier *id1 = (Identifier *)idents.data[i]; | |
1749 Identifier *id2 = (Identifier *)tp->idents.data[i]; | |
1750 | |
1751 if (!id1->equals(id2)) | |
1752 return MATCHnomatch; | |
1753 } | |
1754 } | |
1755 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1756 } | |
1757 | |
1758 MATCH TypeInstance::deduceType(Scope *sc, | |
1759 Type *tparam, TemplateParameters *parameters, | |
1760 Objects *dedtypes) | |
1761 { | |
1762 //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars()); | |
1763 //printf("\ttparam = %d, ", tparam->ty); tparam->print(); | |
1764 | |
1765 // Extra check | |
1766 if (tparam && tparam->ty == Tinstance) | |
1767 { | |
1768 TypeInstance *tp = (TypeInstance *)tparam; | |
1769 | |
1770 //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl); | |
1771 //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl); | |
1772 if (!tp->tempinst->tempdecl) | |
1773 { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars()); | |
1774 if (!tp->tempinst->name->equals(tempinst->name)) | |
1775 { | |
1776 /* Handle case of: | |
1777 * template Foo(T : sa!(T), alias sa) | |
1778 */ | |
1779 int i = templateIdentifierLookup(tp->tempinst->name, parameters); | |
1780 if (i == -1) | |
1781 { /* Didn't find it as a parameter identifier. Try looking | |
1782 * it up and seeing if is an alias. See Bugzilla 1454 | |
1783 */ | |
1784 Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL); | |
1785 if (s) | |
1786 { | |
1787 s = s->toAlias(); | |
1788 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
1789 if (td && td == tempinst->tempdecl) | |
1790 goto L2; | |
1791 } | |
1792 goto Lnomatch; | |
1793 } | |
1794 TemplateParameter *tpx = (TemplateParameter *)parameters->data[i]; | |
1795 // This logic duplicates tpx->matchArg() | |
1796 TemplateAliasParameter *ta = tpx->isTemplateAliasParameter(); | |
1797 if (!ta) | |
1798 goto Lnomatch; | |
1799 Dsymbol *sa = tempinst->tempdecl; | |
1800 if (!sa) | |
1801 goto Lnomatch; | |
1802 if (ta->specAlias && sa != ta->specAlias) | |
1803 goto Lnomatch; | |
1804 if (dedtypes->data[i]) | |
1805 { // Must match already deduced symbol | |
1806 Dsymbol *s = (Dsymbol *)dedtypes->data[i]; | |
1807 | |
1808 if (s != sa) | |
1809 goto Lnomatch; | |
1810 } | |
1811 dedtypes->data[i] = sa; | |
1812 } | |
1813 } | |
1814 else if (tempinst->tempdecl != tp->tempinst->tempdecl) | |
1815 goto Lnomatch; | |
1816 | |
1817 L2: | |
1818 if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) | |
1819 goto Lnomatch; | |
1820 | |
1821 for (int i = 0; i < tempinst->tiargs->dim; i++) | |
1822 { | |
1823 //printf("\ttest: tempinst->tiargs[%d]\n", i); | |
1824 int j; | |
1825 Object *o1 = (Object *)tempinst->tiargs->data[i]; | |
1826 Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; | |
1827 | |
1828 Type *t1 = isType(o1); | |
1829 Type *t2 = isType(o2); | |
1830 | |
1831 Expression *e1 = isExpression(o1); | |
1832 Expression *e2 = isExpression(o2); | |
1833 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1834 Dsymbol *s1 = isDsymbol(o1); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1835 Dsymbol *s2 = isDsymbol(o2); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1836 |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1837 Tuple *v1 = isTuple(o1); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1838 Tuple *v2 = isTuple(o2); |
336 | 1839 #if 0 |
1840 if (t1) printf("t1 = %s\n", t1->toChars()); | |
1841 if (t2) printf("t2 = %s\n", t2->toChars()); | |
1842 if (e1) printf("e1 = %s\n", e1->toChars()); | |
1843 if (e2) printf("e2 = %s\n", e2->toChars()); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1844 if (s1) printf("s1 = %s\n", s1->toChars()); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1845 if (s2) printf("s2 = %s\n", s2->toChars()); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1846 if (v1) printf("v1 = %s\n", v1->toChars()); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1847 if (v2) printf("v2 = %s\n", v2->toChars()); |
336 | 1848 #endif |
1849 | |
1850 if (t1 && t2) | |
1851 { | |
1852 if (!t1->deduceType(sc, t2, parameters, dedtypes)) | |
1853 goto Lnomatch; | |
1854 } | |
1855 else if (e1 && e2) | |
1856 { | |
1857 if (!e1->equals(e2)) | |
1858 { if (e2->op == TOKvar) | |
1859 { | |
1860 /* | |
1861 * (T:Number!(e2), int e2) | |
1862 */ | |
1863 j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters); | |
1864 goto L1; | |
1865 } | |
1866 goto Lnomatch; | |
1867 } | |
1868 } | |
1869 else if (e1 && t2 && t2->ty == Tident) | |
1870 { | |
1871 j = templateParameterLookup(t2, parameters); | |
1872 L1: | |
1873 if (j == -1) | |
1874 goto Lnomatch; | |
1875 TemplateParameter *tp = (TemplateParameter *)parameters->data[j]; | |
1876 // BUG: use tp->matchArg() instead of the following | |
1877 TemplateValueParameter *tv = tp->isTemplateValueParameter(); | |
1878 if (!tv) | |
1879 goto Lnomatch; | |
1880 Expression *e = (Expression *)dedtypes->data[j]; | |
1881 if (e) | |
1882 { | |
1883 if (!e1->equals(e)) | |
1884 goto Lnomatch; | |
1885 } | |
1886 else | |
1887 { Type *vt = tv->valType->semantic(0, sc); | |
1888 MATCH m = (MATCH)e1->implicitConvTo(vt); | |
1889 if (!m) | |
1890 goto Lnomatch; | |
1891 dedtypes->data[j] = e1; | |
1892 } | |
1893 } | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1894 else if (s1 && t2 && t2->ty == Tident) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1895 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1896 j = templateParameterLookup(t2, parameters); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1897 if (j == -1) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1898 goto Lnomatch; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1899 TemplateParameter *tp = (TemplateParameter *)parameters->data[j]; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1900 // BUG: use tp->matchArg() instead of the following |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1901 TemplateAliasParameter *ta = tp->isTemplateAliasParameter(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1902 if (!ta) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1903 goto Lnomatch; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1904 Dsymbol *s = (Dsymbol *)dedtypes->data[j]; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1905 if (s) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1906 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1907 if (!s1->equals(s)) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1908 goto Lnomatch; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1909 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1910 else |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1911 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1912 dedtypes->data[j] = s1; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1913 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1914 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1915 else if (s1 && s2) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1916 { |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1917 if (!s1->equals(s2)) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1918 goto Lnomatch; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1919 } |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
1920 // BUG: Need to handle tuple parameters |
336 | 1921 else |
1922 goto Lnomatch; | |
1923 } | |
1924 } | |
1925 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1926 | |
1927 Lnomatch: | |
1928 return MATCHnomatch; | |
1929 } | |
1930 | |
1931 MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
1932 { | |
1933 //printf("TypeStruct::deduceType()\n"); | |
1934 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print(); | |
1935 //printf("\ttparam = %d, ", tparam->ty); tparam->print(); | |
1936 | |
1937 /* If this struct is a template struct, and we're matching | |
1938 * it against a template instance, convert the struct type | |
1939 * to a template instance, too, and try again. | |
1940 */ | |
1941 TemplateInstance *ti = sym->parent->isTemplateInstance(); | |
1942 | |
1943 if (tparam && tparam->ty == Tinstance) | |
1944 { | |
1945 if (ti && ti->toAlias() == sym) | |
1946 { | |
1947 TypeInstance *t = new TypeInstance(0, ti); | |
1948 return t->deduceType(sc, tparam, parameters, dedtypes); | |
1949 } | |
1950 | |
1951 /* Match things like: | |
1952 * S!(T).foo | |
1953 */ | |
1954 TypeInstance *tpi = (TypeInstance *)tparam; | |
1955 if (tpi->idents.dim) | |
1956 { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1]; | |
1957 if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) | |
1958 { | |
1959 Type *tparent = sym->parent->getType(); | |
1960 if (tparent) | |
1961 { | |
1962 /* Slice off the .foo in S!(T).foo | |
1963 */ | |
1964 tpi->idents.dim--; | |
1965 MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes); | |
1966 tpi->idents.dim++; | |
1967 return m; | |
1968 } | |
1969 } | |
1970 } | |
1971 } | |
1972 | |
1973 // Extra check | |
1974 if (tparam && tparam->ty == Tstruct) | |
1975 { | |
1976 TypeStruct *tp = (TypeStruct *)tparam; | |
1977 | |
1978 if (sym != tp->sym) | |
1979 return MATCHnomatch; | |
1980 } | |
1981 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1982 } | |
1983 | |
1984 MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
1985 { | |
1986 // Extra check | |
1987 if (tparam && tparam->ty == Tenum) | |
1988 { | |
1989 TypeEnum *tp = (TypeEnum *)tparam; | |
1990 | |
1991 if (sym != tp->sym) | |
1992 return MATCHnomatch; | |
1993 } | |
1994 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
1995 } | |
1996 | |
1997 MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
1998 { | |
1999 // Extra check | |
2000 if (tparam && tparam->ty == Ttypedef) | |
2001 { | |
2002 TypeTypedef *tp = (TypeTypedef *)tparam; | |
2003 | |
2004 if (sym != tp->sym) | |
2005 return MATCHnomatch; | |
2006 } | |
2007 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
2008 } | |
2009 | |
2010 MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) | |
2011 { | |
2012 //printf("TypeClass::deduceType(this = %s)\n", toChars()); | |
2013 | |
2014 /* If this class is a template class, and we're matching | |
2015 * it against a template instance, convert the class type | |
2016 * to a template instance, too, and try again. | |
2017 */ | |
2018 TemplateInstance *ti = sym->parent->isTemplateInstance(); | |
2019 | |
2020 if (tparam && tparam->ty == Tinstance) | |
2021 { | |
2022 if (ti && ti->toAlias() == sym) | |
2023 { | |
2024 TypeInstance *t = new TypeInstance(0, ti); | |
2025 return t->deduceType(sc, tparam, parameters, dedtypes); | |
2026 } | |
2027 | |
2028 /* Match things like: | |
2029 * S!(T).foo | |
2030 */ | |
2031 TypeInstance *tpi = (TypeInstance *)tparam; | |
2032 if (tpi->idents.dim) | |
2033 { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1]; | |
2034 if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) | |
2035 { | |
2036 Type *tparent = sym->parent->getType(); | |
2037 if (tparent) | |
2038 { | |
2039 /* Slice off the .foo in S!(T).foo | |
2040 */ | |
2041 tpi->idents.dim--; | |
2042 MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes); | |
2043 tpi->idents.dim++; | |
2044 return m; | |
2045 } | |
2046 } | |
2047 } | |
2048 } | |
2049 | |
2050 // Extra check | |
2051 if (tparam && tparam->ty == Tclass) | |
2052 { | |
2053 TypeClass *tp = (TypeClass *)tparam; | |
2054 | |
2055 //printf("\t%d\n", (MATCH) implicitConvTo(tp)); | |
2056 return (MATCH) implicitConvTo(tp); | |
2057 } | |
2058 return Type::deduceType(sc, tparam, parameters, dedtypes); | |
2059 } | |
2060 | |
2061 /* ======================== TemplateParameter =============================== */ | |
2062 | |
2063 TemplateParameter::TemplateParameter(Loc loc, Identifier *ident) | |
2064 { | |
2065 this->loc = loc; | |
2066 this->ident = ident; | |
2067 this->sparam = NULL; | |
2068 } | |
2069 | |
2070 TemplateTypeParameter *TemplateParameter::isTemplateTypeParameter() | |
2071 { | |
2072 return NULL; | |
2073 } | |
2074 | |
2075 TemplateValueParameter *TemplateParameter::isTemplateValueParameter() | |
2076 { | |
2077 return NULL; | |
2078 } | |
2079 | |
2080 TemplateAliasParameter *TemplateParameter::isTemplateAliasParameter() | |
2081 { | |
2082 return NULL; | |
2083 } | |
2084 | |
2085 TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter() | |
2086 { | |
2087 return NULL; | |
2088 } | |
2089 | |
2090 #if DMDV2 | |
2091 TemplateThisParameter *TemplateParameter::isTemplateThisParameter() | |
2092 { | |
2093 return NULL; | |
2094 } | |
2095 #endif | |
2096 | |
2097 /* ======================== TemplateTypeParameter =========================== */ | |
2098 | |
2099 // type-parameter | |
2100 | |
2101 TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, | |
2102 Type *defaultType) | |
2103 : TemplateParameter(loc, ident) | |
2104 { | |
2105 this->ident = ident; | |
2106 this->specType = specType; | |
2107 this->defaultType = defaultType; | |
2108 } | |
2109 | |
2110 TemplateTypeParameter *TemplateTypeParameter::isTemplateTypeParameter() | |
2111 { | |
2112 return this; | |
2113 } | |
2114 | |
2115 TemplateParameter *TemplateTypeParameter::syntaxCopy() | |
2116 { | |
2117 TemplateTypeParameter *tp = new TemplateTypeParameter(loc, ident, specType, defaultType); | |
2118 if (tp->specType) | |
2119 tp->specType = specType->syntaxCopy(); | |
2120 if (defaultType) | |
2121 tp->defaultType = defaultType->syntaxCopy(); | |
2122 return tp; | |
2123 } | |
2124 | |
2125 void TemplateTypeParameter::declareParameter(Scope *sc) | |
2126 { | |
2127 //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars()); | |
2128 TypeIdentifier *ti = new TypeIdentifier(loc, ident); | |
2129 sparam = new AliasDeclaration(loc, ident, ti); | |
2130 if (!sc->insert(sparam)) | |
2131 error(loc, "parameter '%s' multiply defined", ident->toChars()); | |
2132 } | |
2133 | |
2134 void TemplateTypeParameter::semantic(Scope *sc) | |
2135 { | |
2136 //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars()); | |
2137 if (specType) | |
2138 { | |
2139 specType = specType->semantic(loc, sc); | |
2140 } | |
2141 #if 0 // Don't do semantic() until instantiation | |
2142 if (defaultType) | |
2143 { | |
2144 defaultType = defaultType->semantic(loc, sc); | |
2145 } | |
2146 #endif | |
2147 } | |
2148 | |
2149 /**************************************** | |
2150 * Determine if two TemplateParameters are the same | |
2151 * as far as TemplateDeclaration overloading goes. | |
2152 * Returns: | |
2153 * 1 match | |
2154 * 0 no match | |
2155 */ | |
2156 | |
2157 int TemplateTypeParameter::overloadMatch(TemplateParameter *tp) | |
2158 { | |
2159 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); | |
2160 | |
2161 if (ttp) | |
2162 { | |
2163 if (specType != ttp->specType) | |
2164 goto Lnomatch; | |
2165 | |
2166 if (specType && !specType->equals(ttp->specType)) | |
2167 goto Lnomatch; | |
2168 | |
2169 return 1; // match | |
2170 } | |
2171 | |
2172 Lnomatch: | |
2173 return 0; | |
2174 } | |
2175 | |
2176 /******************************************* | |
2177 * Match to a particular TemplateParameter. | |
2178 * Input: | |
2179 * i i'th argument | |
2180 * tiargs[] actual arguments to template instance | |
2181 * parameters[] template parameters | |
2182 * dedtypes[] deduced arguments to template instance | |
2183 * *psparam set to symbol declared and initialized to dedtypes[i] | |
2184 */ | |
2185 | |
2186 MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs, | |
2187 int i, TemplateParameters *parameters, Objects *dedtypes, | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
2188 Declaration **psparam, int flags) |
336 | 2189 { |
2190 //printf("TemplateTypeParameter::matchArg()\n"); | |
2191 Type *t; | |
2192 Object *oarg; | |
2193 MATCH m = MATCHexact; | |
2194 Type *ta; | |
2195 | |
2196 if (i < tiargs->dim) | |
2197 oarg = (Object *)tiargs->data[i]; | |
2198 else | |
2199 { // Get default argument instead | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2200 oarg = defaultArg(loc, sc); |
336 | 2201 if (!oarg) |
2202 { assert(i < dedtypes->dim); | |
2203 // It might have already been deduced | |
2204 oarg = (Object *)dedtypes->data[i]; | |
2205 if (!oarg) | |
2206 goto Lnomatch; | |
2207 } | |
2208 } | |
2209 | |
2210 ta = isType(oarg); | |
2211 if (!ta) | |
2212 goto Lnomatch; | |
2213 //printf("ta is %s\n", ta->toChars()); | |
2214 | |
2215 t = (Type *)dedtypes->data[i]; | |
2216 | |
2217 if (specType) | |
2218 { | |
2219 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars()); | |
2220 MATCH m2 = ta->deduceType(sc, specType, parameters, dedtypes); | |
2221 if (m2 == MATCHnomatch) | |
2222 { //printf("\tfailed deduceType\n"); | |
2223 goto Lnomatch; | |
2224 } | |
2225 | |
2226 if (m2 < m) | |
2227 m = m2; | |
2228 t = (Type *)dedtypes->data[i]; | |
2229 } | |
2230 else | |
2231 { | |
2232 // So that matches with specializations are better | |
2233 m = MATCHconvert; | |
2234 if (t) | |
2235 { // Must match already deduced type | |
2236 | |
2237 m = MATCHexact; | |
2238 if (!t->equals(ta)) | |
2239 { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars()); | |
2240 goto Lnomatch; | |
2241 } | |
2242 } | |
2243 } | |
2244 | |
2245 if (!t) | |
2246 { | |
2247 dedtypes->data[i] = ta; | |
2248 t = ta; | |
2249 } | |
2250 *psparam = new AliasDeclaration(loc, ident, t); | |
2251 //printf("\tm = %d\n", m); | |
2252 return m; | |
2253 | |
2254 Lnomatch: | |
2255 *psparam = NULL; | |
2256 //printf("\tm = %d\n", MATCHnomatch); | |
2257 return MATCHnomatch; | |
2258 } | |
2259 | |
2260 | |
2261 void TemplateTypeParameter::print(Object *oarg, Object *oded) | |
2262 { | |
2263 printf(" %s\n", ident->toChars()); | |
2264 | |
2265 Type *t = isType(oarg); | |
2266 Type *ta = isType(oded); | |
2267 | |
2268 assert(ta); | |
2269 | |
2270 if (specType) | |
2271 printf("\tSpecialization: %s\n", specType->toChars()); | |
2272 if (defaultType) | |
2273 printf("\tDefault: %s\n", defaultType->toChars()); | |
2274 printf("\tArgument: %s\n", t ? t->toChars() : "NULL"); | |
2275 printf("\tDeduced Type: %s\n", ta->toChars()); | |
2276 } | |
2277 | |
2278 | |
2279 void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2280 { | |
2281 buf->writestring(ident->toChars()); | |
2282 if (specType) | |
2283 { | |
2284 buf->writestring(" : "); | |
2285 specType->toCBuffer(buf, NULL, hgs); | |
2286 } | |
2287 if (defaultType) | |
2288 { | |
2289 buf->writestring(" = "); | |
2290 defaultType->toCBuffer(buf, NULL, hgs); | |
2291 } | |
2292 } | |
2293 | |
2294 | |
2295 void *TemplateTypeParameter::dummyArg() | |
2296 { Type *t; | |
2297 | |
2298 if (specType) | |
2299 t = specType; | |
2300 else | |
2301 { // Use this for alias-parameter's too (?) | |
2302 t = new TypeIdentifier(loc, ident); | |
2303 } | |
2304 return (void *)t; | |
2305 } | |
2306 | |
2307 | |
2308 Object *TemplateTypeParameter::specialization() | |
2309 { | |
2310 return specType; | |
2311 } | |
2312 | |
2313 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2314 Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc) |
336 | 2315 { |
2316 Type *t; | |
2317 | |
2318 t = defaultType; | |
2319 if (t) | |
2320 { | |
2321 t = t->syntaxCopy(); | |
2322 t = t->semantic(loc, sc); | |
2323 } | |
2324 return t; | |
2325 } | |
2326 | |
2327 /* ======================== TemplateThisParameter =========================== */ | |
2328 | |
2329 #if DMDV2 | |
2330 // this-parameter | |
2331 | |
2332 TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident, | |
2333 Type *specType, | |
2334 Type *defaultType) | |
2335 : TemplateTypeParameter(loc, ident, specType, defaultType) | |
2336 { | |
2337 } | |
2338 | |
2339 TemplateThisParameter *TemplateThisParameter::isTemplateThisParameter() | |
2340 { | |
2341 return this; | |
2342 } | |
2343 | |
2344 TemplateParameter *TemplateThisParameter::syntaxCopy() | |
2345 { | |
2346 TemplateThisParameter *tp = new TemplateThisParameter(loc, ident, specType, defaultType); | |
2347 if (tp->specType) | |
2348 tp->specType = specType->syntaxCopy(); | |
2349 if (defaultType) | |
2350 tp->defaultType = defaultType->syntaxCopy(); | |
2351 return tp; | |
2352 } | |
2353 | |
2354 void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2355 { | |
2356 buf->writestring("this "); | |
2357 TemplateTypeParameter::toCBuffer(buf, hgs); | |
2358 } | |
2359 #endif | |
2360 | |
2361 /* ======================== TemplateAliasParameter ========================== */ | |
2362 | |
2363 // alias-parameter | |
2364 | |
2365 Dsymbol *TemplateAliasParameter::sdummy = NULL; | |
2366 | |
2367 TemplateAliasParameter::TemplateAliasParameter(Loc loc, Identifier *ident, Type *specAliasT, Type *defaultAlias) | |
2368 : TemplateParameter(loc, ident) | |
2369 { | |
2370 this->ident = ident; | |
2371 this->specAliasT = specAliasT; | |
2372 this->defaultAlias = defaultAlias; | |
2373 | |
2374 this->specAlias = NULL; | |
2375 } | |
2376 | |
2377 TemplateAliasParameter *TemplateAliasParameter::isTemplateAliasParameter() | |
2378 { | |
2379 return this; | |
2380 } | |
2381 | |
2382 TemplateParameter *TemplateAliasParameter::syntaxCopy() | |
2383 { | |
2384 TemplateAliasParameter *tp = new TemplateAliasParameter(loc, ident, specAliasT, defaultAlias); | |
2385 if (tp->specAliasT) | |
2386 tp->specAliasT = specAliasT->syntaxCopy(); | |
2387 if (defaultAlias) | |
2388 tp->defaultAlias = defaultAlias->syntaxCopy(); | |
2389 return tp; | |
2390 } | |
2391 | |
2392 void TemplateAliasParameter::declareParameter(Scope *sc) | |
2393 { | |
2394 TypeIdentifier *ti = new TypeIdentifier(loc, ident); | |
2395 sparam = new AliasDeclaration(loc, ident, ti); | |
2396 if (!sc->insert(sparam)) | |
2397 error(loc, "parameter '%s' multiply defined", ident->toChars()); | |
2398 } | |
2399 | |
2400 void TemplateAliasParameter::semantic(Scope *sc) | |
2401 { | |
2402 if (specAliasT) | |
2403 { | |
2404 specAlias = specAliasT->toDsymbol(sc); | |
2405 if (!specAlias) | |
2406 error(loc, "%s is not a symbol", specAliasT->toChars()); | |
2407 } | |
2408 #if 0 // Don't do semantic() until instantiation | |
2409 if (defaultAlias) | |
2410 defaultAlias = defaultAlias->semantic(loc, sc); | |
2411 #endif | |
2412 } | |
2413 | |
2414 int TemplateAliasParameter::overloadMatch(TemplateParameter *tp) | |
2415 { | |
2416 TemplateAliasParameter *tap = tp->isTemplateAliasParameter(); | |
2417 | |
2418 if (tap) | |
2419 { | |
2420 if (specAlias != tap->specAlias) | |
2421 goto Lnomatch; | |
2422 | |
2423 return 1; // match | |
2424 } | |
2425 | |
2426 Lnomatch: | |
2427 return 0; | |
2428 } | |
2429 | |
2430 MATCH TemplateAliasParameter::matchArg(Scope *sc, | |
2431 Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
2432 Declaration **psparam, int flags) |
336 | 2433 { |
2434 Dsymbol *sa; | |
2435 Object *oarg; | |
2436 Expression *ea; | |
2437 | |
2438 //printf("TemplateAliasParameter::matchArg()\n"); | |
2439 | |
2440 if (i < tiargs->dim) | |
2441 oarg = (Object *)tiargs->data[i]; | |
2442 else | |
2443 { // Get default argument instead | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2444 oarg = defaultArg(loc, sc); |
336 | 2445 if (!oarg) |
2446 { assert(i < dedtypes->dim); | |
2447 // It might have already been deduced | |
2448 oarg = (Object *)dedtypes->data[i]; | |
2449 if (!oarg) | |
2450 goto Lnomatch; | |
2451 } | |
2452 } | |
2453 | |
2454 sa = getDsymbol(oarg); | |
2455 if (!sa) | |
2456 goto Lnomatch; | |
2457 | |
2458 if (specAlias) | |
2459 { | |
2460 if (!sa || sa == sdummy) | |
2461 goto Lnomatch; | |
2462 if (sa != specAlias) | |
2463 goto Lnomatch; | |
2464 } | |
2465 else if (dedtypes->data[i]) | |
2466 { // Must match already deduced symbol | |
2467 Dsymbol *s = (Dsymbol *)dedtypes->data[i]; | |
2468 | |
2469 if (!sa || s != sa) | |
2470 goto Lnomatch; | |
2471 } | |
2472 dedtypes->data[i] = sa; | |
2473 | |
2474 *psparam = new AliasDeclaration(loc, ident, sa); | |
2475 return MATCHexact; | |
2476 | |
2477 Lnomatch: | |
2478 *psparam = NULL; | |
2479 return MATCHnomatch; | |
2480 } | |
2481 | |
2482 | |
2483 void TemplateAliasParameter::print(Object *oarg, Object *oded) | |
2484 { | |
2485 printf(" %s\n", ident->toChars()); | |
2486 | |
2487 Dsymbol *sa = isDsymbol(oded); | |
2488 assert(sa); | |
2489 | |
2490 printf("\tArgument alias: %s\n", sa->toChars()); | |
2491 } | |
2492 | |
2493 void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2494 { | |
2495 buf->writestring("alias "); | |
2496 buf->writestring(ident->toChars()); | |
2497 if (specAliasT) | |
2498 { | |
2499 buf->writestring(" : "); | |
2500 specAliasT->toCBuffer(buf, NULL, hgs); | |
2501 } | |
2502 if (defaultAlias) | |
2503 { | |
2504 buf->writestring(" = "); | |
2505 defaultAlias->toCBuffer(buf, NULL, hgs); | |
2506 } | |
2507 } | |
2508 | |
2509 | |
2510 void *TemplateAliasParameter::dummyArg() | |
2511 { Dsymbol *s; | |
2512 | |
2513 s = specAlias; | |
2514 if (!s) | |
2515 { | |
2516 if (!sdummy) | |
2517 sdummy = new Dsymbol(); | |
2518 s = sdummy; | |
2519 } | |
2520 return (void*)s; | |
2521 } | |
2522 | |
2523 | |
2524 Object *TemplateAliasParameter::specialization() | |
2525 { | |
2526 return specAliasT; | |
2527 } | |
2528 | |
2529 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2530 Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc) |
336 | 2531 { |
2532 Dsymbol *s = NULL; | |
2533 | |
2534 if (defaultAlias) | |
2535 { | |
2536 s = defaultAlias->toDsymbol(sc); | |
2537 if (!s) | |
2538 error("%s is not a symbol", defaultAlias->toChars()); | |
2539 } | |
2540 return s; | |
2541 } | |
2542 | |
2543 /* ======================== TemplateValueParameter ========================== */ | |
2544 | |
2545 // value-parameter | |
2546 | |
2547 Expression *TemplateValueParameter::edummy = NULL; | |
2548 | |
2549 TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, | |
2550 Expression *specValue, Expression *defaultValue) | |
2551 : TemplateParameter(loc, ident) | |
2552 { | |
2553 this->ident = ident; | |
2554 this->valType = valType; | |
2555 this->specValue = specValue; | |
2556 this->defaultValue = defaultValue; | |
2557 } | |
2558 | |
2559 TemplateValueParameter *TemplateValueParameter::isTemplateValueParameter() | |
2560 { | |
2561 return this; | |
2562 } | |
2563 | |
2564 TemplateParameter *TemplateValueParameter::syntaxCopy() | |
2565 { | |
2566 TemplateValueParameter *tp = | |
2567 new TemplateValueParameter(loc, ident, valType, specValue, defaultValue); | |
2568 tp->valType = valType->syntaxCopy(); | |
2569 if (specValue) | |
2570 tp->specValue = specValue->syntaxCopy(); | |
2571 if (defaultValue) | |
2572 tp->defaultValue = defaultValue->syntaxCopy(); | |
2573 return tp; | |
2574 } | |
2575 | |
2576 void TemplateValueParameter::declareParameter(Scope *sc) | |
2577 { | |
2578 VarDeclaration *v = new VarDeclaration(loc, valType, ident, NULL); | |
2579 v->storage_class = STCtemplateparameter; | |
2580 if (!sc->insert(v)) | |
2581 error(loc, "parameter '%s' multiply defined", ident->toChars()); | |
2582 sparam = v; | |
2583 } | |
2584 | |
2585 void TemplateValueParameter::semantic(Scope *sc) | |
2586 { | |
2587 sparam->semantic(sc); | |
2588 valType = valType->semantic(loc, sc); | |
2589 if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && | |
2590 valType->ty != Tident) | |
2591 error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars()); | |
2592 | |
2593 if (specValue) | |
2594 { Expression *e = specValue; | |
2595 | |
2596 e = e->semantic(sc); | |
2597 e = e->implicitCastTo(sc, valType); | |
2598 e = e->optimize(WANTvalue | WANTinterpret); | |
2599 if (e->op == TOKint64 || e->op == TOKfloat64 || | |
2600 e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring) | |
2601 specValue = e; | |
2602 //e->toInteger(); | |
2603 } | |
2604 | |
2605 #if 0 // defer semantic analysis to arg match | |
2606 if (defaultValue) | |
2607 { Expression *e = defaultValue; | |
2608 | |
2609 e = e->semantic(sc); | |
2610 e = e->implicitCastTo(sc, valType); | |
2611 e = e->optimize(WANTvalue | WANTinterpret); | |
2612 if (e->op == TOKint64) | |
2613 defaultValue = e; | |
2614 //e->toInteger(); | |
2615 } | |
2616 #endif | |
2617 } | |
2618 | |
2619 int TemplateValueParameter::overloadMatch(TemplateParameter *tp) | |
2620 { | |
2621 TemplateValueParameter *tvp = tp->isTemplateValueParameter(); | |
2622 | |
2623 if (tvp) | |
2624 { | |
2625 if (valType != tvp->valType) | |
2626 goto Lnomatch; | |
2627 | |
2628 if (valType && !valType->equals(tvp->valType)) | |
2629 goto Lnomatch; | |
2630 | |
2631 if (specValue != tvp->specValue) | |
2632 goto Lnomatch; | |
2633 | |
2634 return 1; // match | |
2635 } | |
2636 | |
2637 Lnomatch: | |
2638 return 0; | |
2639 } | |
2640 | |
2641 | |
2642 MATCH TemplateValueParameter::matchArg(Scope *sc, | |
2643 Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
2644 Declaration **psparam, int flags) |
336 | 2645 { |
2646 //printf("TemplateValueParameter::matchArg()\n"); | |
2647 | |
2648 Initializer *init; | |
2649 Declaration *sparam; | |
2650 MATCH m = MATCHexact; | |
2651 Expression *ei; | |
2652 Object *oarg; | |
2653 | |
2654 if (i < tiargs->dim) | |
2655 oarg = (Object *)tiargs->data[i]; | |
2656 else | |
2657 { // Get default argument instead | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2658 oarg = defaultArg(loc, sc); |
336 | 2659 if (!oarg) |
2660 { assert(i < dedtypes->dim); | |
2661 // It might have already been deduced | |
2662 oarg = (Object *)dedtypes->data[i]; | |
2663 if (!oarg) | |
2664 goto Lnomatch; | |
2665 } | |
2666 } | |
2667 | |
2668 ei = isExpression(oarg); | |
2669 Type *vt; | |
2670 | |
2671 if (!ei && oarg) | |
2672 goto Lnomatch; | |
2673 | |
2674 if (specValue) | |
2675 { | |
2676 if (!ei || ei == edummy) | |
2677 goto Lnomatch; | |
2678 | |
2679 Expression *e = specValue; | |
2680 | |
2681 e = e->semantic(sc); | |
2682 e = e->implicitCastTo(sc, valType); | |
2683 e = e->optimize(WANTvalue | WANTinterpret); | |
2684 | |
2685 ei = ei->syntaxCopy(); | |
2686 ei = ei->semantic(sc); | |
2687 ei = ei->optimize(WANTvalue | WANTinterpret); | |
2688 //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars()); | |
2689 //printf("e : %s, %s\n", e->toChars(), e->type->toChars()); | |
2690 if (!ei->equals(e)) | |
2691 goto Lnomatch; | |
2692 } | |
2693 else if (dedtypes->data[i]) | |
2694 { // Must match already deduced value | |
2695 Expression *e = (Expression *)dedtypes->data[i]; | |
2696 | |
2697 if (!ei || !ei->equals(e)) | |
2698 goto Lnomatch; | |
2699 } | |
2700 Lmatch: | |
2701 //printf("valType: %s, ty = %d\n", valType->toChars(), valType->ty); | |
2702 vt = valType->semantic(0, sc); | |
2703 //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars()); | |
2704 if (ei->type) | |
2705 { | |
2706 m = (MATCH)ei->implicitConvTo(vt); | |
2707 //printf("m: %d\n", m); | |
2708 if (!m) | |
2709 goto Lnomatch; | |
2710 } | |
2711 dedtypes->data[i] = ei; | |
2712 | |
2713 init = new ExpInitializer(loc, ei); | |
2714 sparam = new VarDeclaration(loc, vt, ident, init); | |
2715 sparam->storage_class = STCconst; | |
2716 *psparam = sparam; | |
2717 return m; | |
2718 | |
2719 Lnomatch: | |
2720 //printf("\tno match\n"); | |
2721 *psparam = NULL; | |
2722 return MATCHnomatch; | |
2723 } | |
2724 | |
2725 | |
2726 void TemplateValueParameter::print(Object *oarg, Object *oded) | |
2727 { | |
2728 printf(" %s\n", ident->toChars()); | |
2729 | |
2730 Expression *ea = isExpression(oded); | |
2731 | |
2732 if (specValue) | |
2733 printf("\tSpecialization: %s\n", specValue->toChars()); | |
2734 printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL"); | |
2735 } | |
2736 | |
2737 | |
2738 void TemplateValueParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2739 { | |
2740 valType->toCBuffer(buf, ident, hgs); | |
2741 if (specValue) | |
2742 { | |
2743 buf->writestring(" : "); | |
2744 specValue->toCBuffer(buf, hgs); | |
2745 } | |
2746 if (defaultValue) | |
2747 { | |
2748 buf->writestring(" = "); | |
2749 defaultValue->toCBuffer(buf, hgs); | |
2750 } | |
2751 } | |
2752 | |
2753 | |
2754 void *TemplateValueParameter::dummyArg() | |
2755 { Expression *e; | |
2756 | |
2757 e = specValue; | |
2758 if (!e) | |
2759 { | |
2760 // Create a dummy value | |
2761 if (!edummy) | |
2762 edummy = valType->defaultInit(); | |
2763 e = edummy; | |
2764 } | |
2765 return (void *)e; | |
2766 } | |
2767 | |
2768 | |
2769 Object *TemplateValueParameter::specialization() | |
2770 { | |
2771 return specValue; | |
2772 } | |
2773 | |
2774 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2775 Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc) |
336 | 2776 { |
2777 Expression *e = defaultValue; | |
2778 if (e) | |
2779 { | |
2780 e = e->syntaxCopy(); | |
2781 e = e->semantic(sc); | |
2782 #if DMDV2 | |
2783 if (e->op == TOKdefault) | |
2784 { DefaultInitExp *de = (DefaultInitExp *)e; | |
2785 e = de->resolve(loc, sc); | |
2786 } | |
2787 #endif | |
2788 } | |
2789 return e; | |
2790 } | |
2791 | |
2792 /* ======================== TemplateTupleParameter ========================== */ | |
2793 | |
2794 // variadic-parameter | |
2795 | |
2796 TemplateTupleParameter::TemplateTupleParameter(Loc loc, Identifier *ident) | |
2797 : TemplateParameter(loc, ident) | |
2798 { | |
2799 this->ident = ident; | |
2800 } | |
2801 | |
2802 TemplateTupleParameter *TemplateTupleParameter::isTemplateTupleParameter() | |
2803 { | |
2804 return this; | |
2805 } | |
2806 | |
2807 TemplateParameter *TemplateTupleParameter::syntaxCopy() | |
2808 { | |
2809 TemplateTupleParameter *tp = new TemplateTupleParameter(loc, ident); | |
2810 return tp; | |
2811 } | |
2812 | |
2813 void TemplateTupleParameter::declareParameter(Scope *sc) | |
2814 { | |
2815 TypeIdentifier *ti = new TypeIdentifier(loc, ident); | |
2816 sparam = new AliasDeclaration(loc, ident, ti); | |
2817 if (!sc->insert(sparam)) | |
2818 error(loc, "parameter '%s' multiply defined", ident->toChars()); | |
2819 } | |
2820 | |
2821 void TemplateTupleParameter::semantic(Scope *sc) | |
2822 { | |
2823 } | |
2824 | |
2825 int TemplateTupleParameter::overloadMatch(TemplateParameter *tp) | |
2826 { | |
2827 TemplateTupleParameter *tvp = tp->isTemplateTupleParameter(); | |
2828 | |
2829 if (tvp) | |
2830 { | |
2831 return 1; // match | |
2832 } | |
2833 | |
2834 Lnomatch: | |
2835 return 0; | |
2836 } | |
2837 | |
2838 MATCH TemplateTupleParameter::matchArg(Scope *sc, | |
2839 Objects *tiargs, int i, TemplateParameters *parameters, | |
2840 Objects *dedtypes, | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
2841 Declaration **psparam, int flags) |
336 | 2842 { |
2843 //printf("TemplateTupleParameter::matchArg()\n"); | |
2844 | |
2845 /* The rest of the actual arguments (tiargs[]) form the match | |
2846 * for the variadic parameter. | |
2847 */ | |
2848 assert(i + 1 == dedtypes->dim); // must be the last one | |
2849 Tuple *ovar; | |
2850 if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i])) | |
2851 ovar = isTuple((Object *)tiargs->data[i]); | |
2852 else | |
2853 { | |
2854 ovar = new Tuple(); | |
2855 //printf("ovar = %p\n", ovar); | |
2856 if (i < tiargs->dim) | |
2857 { | |
2858 //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim); | |
2859 ovar->objects.setDim(tiargs->dim - i); | |
2860 for (size_t j = 0; j < ovar->objects.dim; j++) | |
2861 ovar->objects.data[j] = tiargs->data[i + j]; | |
2862 } | |
2863 } | |
2864 *psparam = new TupleDeclaration(loc, ident, &ovar->objects); | |
2865 dedtypes->data[i] = (void *)ovar; | |
2866 return MATCHexact; | |
2867 } | |
2868 | |
2869 | |
2870 void TemplateTupleParameter::print(Object *oarg, Object *oded) | |
2871 { | |
2872 printf(" %s... [", ident->toChars()); | |
2873 Tuple *v = isTuple(oded); | |
2874 assert(v); | |
2875 | |
2876 //printf("|%d| ", v->objects.dim); | |
2877 for (int i = 0; i < v->objects.dim; i++) | |
2878 { | |
2879 if (i) | |
2880 printf(", "); | |
2881 | |
2882 Object *o = (Object *)v->objects.data[i]; | |
2883 | |
2884 Dsymbol *sa = isDsymbol(o); | |
2885 if (sa) | |
2886 printf("alias: %s", sa->toChars()); | |
2887 | |
2888 Type *ta = isType(o); | |
2889 if (ta) | |
2890 printf("type: %s", ta->toChars()); | |
2891 | |
2892 Expression *ea = isExpression(o); | |
2893 if (ea) | |
2894 printf("exp: %s", ea->toChars()); | |
2895 | |
2896 assert(!isTuple(o)); // no nested Tuple arguments | |
2897 } | |
2898 | |
2899 printf("]\n"); | |
2900 } | |
2901 | |
2902 void TemplateTupleParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2903 { | |
2904 buf->writestring(ident->toChars()); | |
2905 buf->writestring("..."); | |
2906 } | |
2907 | |
2908 | |
2909 void *TemplateTupleParameter::dummyArg() | |
2910 { | |
2911 return NULL; | |
2912 } | |
2913 | |
2914 | |
2915 Object *TemplateTupleParameter::specialization() | |
2916 { | |
2917 return NULL; | |
2918 } | |
2919 | |
2920 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2921 Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc) |
336 | 2922 { |
2923 return NULL; | |
2924 } | |
2925 | |
2926 /* ======================== TemplateInstance ================================ */ | |
2927 | |
2928 TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) | |
2929 : ScopeDsymbol(NULL) | |
2930 { | |
2931 #if LOG | |
2932 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null"); | |
2933 #endif | |
2934 this->loc = loc; | |
2935 this->name = ident; | |
2936 this->tiargs = NULL; | |
2937 this->tempdecl = NULL; | |
2938 this->inst = NULL; | |
2939 this->argsym = NULL; | |
2940 this->aliasdecl = NULL; | |
2941 this->semanticdone = 0; | |
2942 this->semantictiargsdone = 0; | |
2943 this->withsym = NULL; | |
2944 this->nest = 0; | |
2945 this->havetempdecl = 0; | |
2946 this->isnested = NULL; | |
2947 this->errors = 0; | |
948
780530d1cad3
Revert templates to old behavior.
Christian Kamm <kamm incasoftware de>
parents:
946
diff
changeset
|
2948 |
780530d1cad3
Revert templates to old behavior.
Christian Kamm <kamm incasoftware de>
parents:
946
diff
changeset
|
2949 // LDC |
1067
7ce8355fbcc6
Improved template emission control for singleobj building.
Christian Kamm <kamm incasoftware de>
parents:
948
diff
changeset
|
2950 this->emittedInModule = NULL; |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
2951 this->tinst = NULL; |
948
780530d1cad3
Revert templates to old behavior.
Christian Kamm <kamm incasoftware de>
parents:
946
diff
changeset
|
2952 this->tmodule = NULL; |
336 | 2953 } |
2954 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2955 /***************** |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2956 * This constructor is only called when we figured out which function |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2957 * template to instantiate. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
2958 */ |
336 | 2959 |
2960 TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs) | |
2961 : ScopeDsymbol(NULL) | |
2962 { | |
2963 #if LOG | |
2964 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td->toChars()); | |
2965 #endif | |
2966 this->loc = loc; | |
2967 this->name = td->ident; | |
2968 this->tiargs = tiargs; | |
2969 this->tempdecl = td; | |
2970 this->inst = NULL; | |
2971 this->argsym = NULL; | |
2972 this->aliasdecl = NULL; | |
2973 this->semanticdone = 0; | |
2974 this->semantictiargsdone = 1; | |
2975 this->withsym = NULL; | |
2976 this->nest = 0; | |
2977 this->havetempdecl = 1; | |
2978 this->isnested = NULL; | |
2979 this->errors = 0; | |
940
39519a1ff603
Changed the way LDC determines if a template instantiation needs to get a definition, seems to speed up compile times quite a bit in some cases.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
876
diff
changeset
|
2980 |
39519a1ff603
Changed the way LDC determines if a template instantiation needs to get a definition, seems to speed up compile times quite a bit in some cases.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
876
diff
changeset
|
2981 // LDC |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
2982 this->tinst = NULL; |
940
39519a1ff603
Changed the way LDC determines if a template instantiation needs to get a definition, seems to speed up compile times quite a bit in some cases.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
876
diff
changeset
|
2983 this->tmodule = NULL; |
336 | 2984 |
2985 assert((size_t)tempdecl->scope > 0x10000); | |
2986 } | |
2987 | |
2988 | |
2989 Objects *TemplateInstance::arraySyntaxCopy(Objects *objs) | |
2990 { | |
2991 Objects *a = NULL; | |
2992 if (objs) | |
2993 { a = new Objects(); | |
2994 a->setDim(objs->dim); | |
2995 for (size_t i = 0; i < objs->dim; i++) | |
2996 { | |
2997 Type *ta = isType((Object *)objs->data[i]); | |
2998 if (ta) | |
2999 a->data[i] = ta->syntaxCopy(); | |
3000 else | |
3001 { | |
3002 Expression *ea = isExpression((Object *)objs->data[i]); | |
3003 assert(ea); | |
3004 a->data[i] = ea->syntaxCopy(); | |
3005 } | |
3006 } | |
3007 } | |
3008 return a; | |
3009 } | |
3010 | |
3011 Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s) | |
3012 { | |
3013 TemplateInstance *ti; | |
3014 | |
3015 if (s) | |
3016 ti = (TemplateInstance *)s; | |
3017 else | |
3018 ti = new TemplateInstance(loc, name); | |
3019 | |
3020 ti->tiargs = arraySyntaxCopy(tiargs); | |
3021 | |
3022 ScopeDsymbol::syntaxCopy(ti); | |
3023 return ti; | |
3024 } | |
3025 | |
3026 | |
3027 void TemplateInstance::semantic(Scope *sc) | |
3028 { | |
3029 if (global.errors) | |
3030 { | |
3031 if (!global.gag) | |
3032 { | |
3033 /* Trying to soldier on rarely generates useful messages | |
3034 * at this point. | |
3035 */ | |
3036 fatal(); | |
3037 } | |
3038 return; | |
3039 } | |
3040 #if LOG | |
3041 printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); | |
3042 #endif | |
3043 if (inst) // if semantic() was already run | |
3044 { | |
3045 #if LOG | |
3046 printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst->toChars(), inst); | |
3047 #endif | |
3048 return; | |
3049 } | |
3050 | |
3051 if (semanticdone != 0) | |
3052 { | |
3053 error(loc, "recursive template expansion"); | |
3054 // inst = this; | |
3055 return; | |
3056 } | |
3057 semanticdone = 1; | |
3058 | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3059 // get the enclosing template instance from the scope tinst |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3060 tinst = sc->tinst; |
946
1714836f2c0b
Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h.
Christian Kamm <kamm incasoftware de>
parents:
940
diff
changeset
|
3061 |
1714836f2c0b
Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h.
Christian Kamm <kamm incasoftware de>
parents:
940
diff
changeset
|
3062 // get the module of the outermost enclosing instantiation |
1714836f2c0b
Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h.
Christian Kamm <kamm incasoftware de>
parents:
940
diff
changeset
|
3063 if (tinst) |
1714836f2c0b
Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h.
Christian Kamm <kamm incasoftware de>
parents:
940
diff
changeset
|
3064 tmodule = tinst->tmodule; |
1714836f2c0b
Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h.
Christian Kamm <kamm incasoftware de>
parents:
940
diff
changeset
|
3065 else |
1714836f2c0b
Mostly rewrite debug info generation in terms of llvm/Analysis/DebugInfo.h.
Christian Kamm <kamm incasoftware de>
parents:
940
diff
changeset
|
3066 tmodule = sc->module; |
948
780530d1cad3
Revert templates to old behavior.
Christian Kamm <kamm incasoftware de>
parents:
946
diff
changeset
|
3067 //printf("%s in %s\n", toChars(), tmodule->toChars()); |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3068 |
336 | 3069 #if LOG |
3070 printf("\tdo semantic\n"); | |
3071 #endif | |
3072 if (havetempdecl) | |
3073 { | |
3074 assert((size_t)tempdecl->scope > 0x10000); | |
3075 // Deduce tdtypes | |
3076 tdtypes.setDim(tempdecl->parameters->dim); | |
3077 if (!tempdecl->matchWithInstance(this, &tdtypes, 0)) | |
3078 { | |
3079 error("incompatible arguments for template instantiation"); | |
3080 inst = this; | |
3081 return; | |
3082 } | |
3083 } | |
3084 else | |
3085 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3086 /* Run semantic on each argument, place results in tiargs[] |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3087 * (if we havetempdecl, then tiargs is already evaluated) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3088 */ |
336 | 3089 semanticTiargs(sc); |
3090 | |
3091 tempdecl = findTemplateDeclaration(sc); | |
3092 if (tempdecl) | |
3093 tempdecl = findBestMatch(sc); | |
3094 if (!tempdecl || global.errors) | |
3095 { inst = this; | |
3096 //printf("error return %p, %d\n", tempdecl, global.errors); | |
3097 return; // error recovery | |
3098 } | |
3099 } | |
3100 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3101 hasNestedArgs(tiargs); |
336 | 3102 |
3103 /* See if there is an existing TemplateInstantiation that already | |
3104 * implements the typeargs. If so, just refer to that one instead. | |
3105 */ | |
3106 | |
3107 for (size_t i = 0; i < tempdecl->instances.dim; i++) | |
3108 { | |
3109 TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i]; | |
3110 #if LOG | |
3111 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars()); | |
3112 #endif | |
3113 assert(tdtypes.dim == ti->tdtypes.dim); | |
3114 | |
3115 // Nesting must match | |
3116 if (isnested != ti->isnested) | |
3117 continue; | |
3118 #if 0 | |
3119 if (isnested && sc->parent != ti->parent) | |
3120 continue; | |
3121 #endif | |
3122 for (size_t j = 0; j < tdtypes.dim; j++) | |
3123 { Object *o1 = (Object *)tdtypes.data[j]; | |
3124 Object *o2 = (Object *)ti->tdtypes.data[j]; | |
3125 if (!match(o1, o2, tempdecl, sc)) | |
3126 goto L1; | |
3127 } | |
3128 | |
3129 // It's a match | |
3130 inst = ti; | |
3131 parent = ti->parent; | |
3132 #if LOG | |
3133 printf("\tit's a match with instance %p\n", inst); | |
3134 #endif | |
3135 return; | |
3136 | |
3137 L1: | |
3138 ; | |
3139 } | |
3140 | |
3141 /* So, we need to implement 'this' instance. | |
3142 */ | |
3143 #if LOG | |
3144 printf("\timplement template instance '%s'\n", toChars()); | |
3145 #endif | |
3146 unsigned errorsave = global.errors; | |
3147 inst = this; | |
3148 int tempdecl_instance_idx = tempdecl->instances.dim; | |
3149 tempdecl->instances.push(this); | |
3150 parent = tempdecl->parent; | |
3151 //printf("parent = '%s'\n", parent->kind()); | |
3152 | |
3153 ident = genIdent(); // need an identifier for name mangling purposes. | |
3154 | |
3155 #if 1 | |
3156 if (isnested) | |
3157 parent = isnested; | |
3158 #endif | |
3159 //printf("parent = '%s'\n", parent->kind()); | |
3160 | |
3161 // Add 'this' to the enclosing scope's members[] so the semantic routines | |
3162 // will get called on the instance members | |
3163 #if 1 | |
3164 int dosemantic3 = 0; | |
3165 { Array *a; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3166 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3167 Scope *scx = sc; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3168 #if 0 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3169 for (scx = sc; scx; scx = scx->enclosing) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3170 if (scx->scopesym) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3171 break; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3172 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3173 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3174 //if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3175 if (scx && scx->scopesym && |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3176 scx->scopesym->members && !scx->scopesym->isTemplateMixin() |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3177 #if 1 // removed because it bloated compile times |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3178 /* The problem is if A imports B, and B imports A, and both A |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3179 * and B instantiate the same template, does the compilation of A |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3180 * or the compilation of B do the actual instantiation? |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3181 * |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3182 * see bugzilla 2500. |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3183 */ |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3184 && !scx->module->selfImports() |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3185 #endif |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3186 ) |
336 | 3187 { |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3188 //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3189 a = scx->scopesym->members; |
336 | 3190 } |
3191 else | |
3192 { Module *m = sc->module->importedFrom; | |
3193 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); | |
3194 a = m->members; | |
3195 if (m->semanticdone >= 3) | |
3196 dosemantic3 = 1; | |
3197 } | |
3198 for (int i = 0; 1; i++) | |
3199 { | |
3200 if (i == a->dim) | |
3201 { | |
3202 a->push(this); | |
3203 break; | |
3204 } | |
3205 if (this == (Dsymbol *)a->data[i]) // if already in Array | |
3206 break; | |
3207 } | |
3208 } | |
3209 #endif | |
3210 | |
3211 // Copy the syntax trees from the TemplateDeclaration | |
3212 members = Dsymbol::arraySyntaxCopy(tempdecl->members); | |
3213 | |
3214 // Create our own scope for the template parameters | |
3215 Scope *scope = tempdecl->scope; | |
3216 if (!scope) | |
3217 { | |
3218 error("forward reference to template declaration %s\n", tempdecl->toChars()); | |
3219 return; | |
3220 } | |
3221 | |
3222 #if LOG | |
3223 printf("\tcreate scope for template parameters '%s'\n", toChars()); | |
3224 #endif | |
3225 argsym = new ScopeDsymbol(); | |
3226 argsym->parent = scope->parent; | |
3227 scope = scope->push(argsym); | |
3228 | |
3229 // Declare each template parameter as an alias for the argument type | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3230 Scope *paramscope = scope->push(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3231 paramscope->stc = 0; |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3232 declareParameters(paramscope); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3233 paramscope->pop(); |
336 | 3234 |
3235 // Add members of template instance to template instance symbol table | |
3236 // parent = scope->scopesym; | |
3237 symtab = new DsymbolTable(); | |
3238 int memnum = 0; | |
3239 for (int i = 0; i < members->dim; i++) | |
3240 { | |
3241 Dsymbol *s = (Dsymbol *)members->data[i]; | |
3242 #if LOG | |
3243 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum); | |
3244 #endif | |
3245 memnum |= s->addMember(scope, this, memnum); | |
3246 } | |
3247 #if LOG | |
3248 printf("adding members done\n"); | |
3249 #endif | |
3250 | |
3251 /* See if there is only one member of template instance, and that | |
3252 * member has the same name as the template instance. | |
3253 * If so, this template instance becomes an alias for that member. | |
3254 */ | |
3255 //printf("members->dim = %d\n", members->dim); | |
3256 if (members->dim) | |
3257 { | |
3258 Dsymbol *s; | |
3259 if (Dsymbol::oneMembers(members, &s) && s) | |
3260 { | |
3261 //printf("s->kind = '%s'\n", s->kind()); | |
3262 //s->print(); | |
3263 //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars()); | |
3264 if (s->ident && s->ident->equals(tempdecl->ident)) | |
3265 { | |
3266 //printf("setting aliasdecl\n"); | |
3267 aliasdecl = new AliasDeclaration(loc, s->ident, s); | |
1089
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3268 |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3269 // LDC propagate internal information |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3270 if (tempdecl->llvmInternal) { |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3271 s->llvmInternal = tempdecl->llvmInternal; |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3272 if (FuncDeclaration* fd = s->isFuncDeclaration()) { |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3273 fd->intrinsicName = tempdecl->intrinsicName; |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3274 } |
d33b0d4b816a
Make sure instantiations of template intrinsics are marked as intrinsics.
Frits van Bommel <fvbommel wxs.nl>
parents:
1067
diff
changeset
|
3275 } |
336 | 3276 } |
3277 } | |
3278 } | |
3279 | |
3280 // Do semantic() analysis on template instance members | |
3281 #if LOG | |
3282 printf("\tdo semantic() on template instance members '%s'\n", toChars()); | |
3283 #endif | |
3284 Scope *sc2; | |
3285 sc2 = scope->push(this); | |
3286 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); | |
3287 sc2->parent = /*isnested ? sc->parent :*/ this; | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3288 sc2->tinst = this; |
336 | 3289 |
3290 #if !IN_LLVM | |
3291 #if _WIN32 | |
3292 __try | |
3293 { | |
3294 #endif | |
3295 #endif | |
3296 for (int i = 0; i < members->dim; i++) | |
3297 { | |
3298 Dsymbol *s = (Dsymbol *)members->data[i]; | |
3299 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); | |
3300 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); | |
3301 // if (isnested) | |
3302 // s->parent = sc->parent; | |
3303 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); | |
3304 s->semantic(sc2); | |
3305 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); | |
3306 sc2->module->runDeferredSemantic(); | |
3307 } | |
3308 #if !IN_LLVM | |
3309 #if _WIN32 | |
3310 } | |
3311 __except (__ehfilter(GetExceptionInformation())) | |
3312 { | |
3313 global.gag = 0; // ensure error message gets printed | |
3314 error("recursive expansion"); | |
3315 fatal(); | |
3316 } | |
3317 #endif | |
3318 #endif | |
3319 | |
3320 /* If any of the instantiation members didn't get semantic() run | |
3321 * on them due to forward references, we cannot run semantic2() | |
3322 * or semantic3() yet. | |
3323 */ | |
3324 for (size_t i = 0; i < Module::deferred.dim; i++) | |
3325 { Dsymbol *sd = (Dsymbol *)Module::deferred.data[i]; | |
3326 | |
3327 if (sd->parent == this) | |
3328 goto Laftersemantic; | |
3329 } | |
3330 | |
3331 /* The problem is when to parse the initializer for a variable. | |
3332 * Perhaps VarDeclaration::semantic() should do it like it does | |
3333 * for initializers inside a function. | |
3334 */ | |
3335 // if (sc->parent->isFuncDeclaration()) | |
3336 | |
3337 /* BUG 782: this has problems if the classes this depends on | |
3338 * are forward referenced. Find a way to defer semantic() | |
3339 * on this template. | |
3340 */ | |
3341 semantic2(sc2); | |
3342 | |
3343 if (sc->func || dosemantic3) | |
3344 { | |
3345 semantic3(sc2); | |
3346 } | |
3347 | |
3348 Laftersemantic: | |
3349 sc2->pop(); | |
3350 | |
3351 scope->pop(); | |
3352 | |
3353 // Give additional context info if error occurred during instantiation | |
3354 if (global.errors != errorsave) | |
3355 { | |
3356 error("error instantiating"); | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3357 if(tinst) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3358 tinst->printInstantiationTrace(); |
336 | 3359 errors = 1; |
3360 if (global.gag) | |
3361 tempdecl->instances.remove(tempdecl_instance_idx); | |
3362 } | |
3363 | |
3364 #if LOG | |
3365 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); | |
3366 #endif | |
3367 } | |
3368 | |
3369 | |
3370 void TemplateInstance::semanticTiargs(Scope *sc) | |
3371 { | |
3372 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); | |
3373 if (semantictiargsdone) | |
3374 return; | |
3375 semantictiargsdone = 1; | |
3376 semanticTiargs(loc, sc, tiargs); | |
3377 } | |
3378 | |
3379 void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs) | |
3380 { | |
3381 // Run semantic on each argument, place results in tiargs[] | |
3382 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); | |
3383 if (!tiargs) | |
3384 return; | |
3385 for (size_t j = 0; j < tiargs->dim; j++) | |
3386 { | |
3387 Object *o = (Object *)tiargs->data[j]; | |
3388 Type *ta = isType(o); | |
3389 Expression *ea = isExpression(o); | |
3390 Dsymbol *sa = isDsymbol(o); | |
3391 | |
3392 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta); | |
3393 if (ta) | |
3394 { | |
3395 //printf("type %s\n", ta->toChars()); | |
3396 // It might really be an Expression or an Alias | |
3397 ta->resolve(loc, sc, &ea, &ta, &sa); | |
3398 if (ea) | |
3399 { | |
3400 ea = ea->semantic(sc); | |
3401 ea = ea->optimize(WANTvalue | WANTinterpret); | |
3402 tiargs->data[j] = ea; | |
3403 } | |
3404 else if (sa) | |
3405 { tiargs->data[j] = sa; | |
3406 TupleDeclaration *d = sa->toAlias()->isTupleDeclaration(); | |
3407 if (d) | |
3408 { | |
3409 size_t dim = d->objects->dim; | |
3410 tiargs->remove(j); | |
3411 tiargs->insert(j, d->objects); | |
3412 j--; | |
3413 } | |
3414 } | |
3415 else if (ta) | |
3416 { | |
3417 if (ta->ty == Ttuple) | |
3418 { // Expand tuple | |
3419 TypeTuple *tt = (TypeTuple *)ta; | |
3420 size_t dim = tt->arguments->dim; | |
3421 tiargs->remove(j); | |
3422 if (dim) | |
3423 { tiargs->reserve(dim); | |
3424 for (size_t i = 0; i < dim; i++) | |
3425 { Argument *arg = (Argument *)tt->arguments->data[i]; | |
3426 tiargs->insert(j + i, arg->type); | |
3427 } | |
3428 } | |
3429 j--; | |
3430 } | |
3431 else | |
3432 tiargs->data[j] = ta; | |
3433 } | |
3434 else | |
3435 { | |
3436 assert(global.errors); | |
3437 tiargs->data[j] = Type::terror; | |
3438 } | |
3439 } | |
3440 else if (ea) | |
3441 { | |
3442 if (!ea) | |
3443 { assert(global.errors); | |
3444 ea = new IntegerExp(0); | |
3445 } | |
3446 assert(ea); | |
3447 ea = ea->semantic(sc); | |
3448 ea = ea->optimize(WANTvalue | WANTinterpret); | |
3449 tiargs->data[j] = ea; | |
3450 if (ea->op == TOKtype) | |
3451 tiargs->data[j] = ea->type; | |
3452 } | |
3453 else if (sa) | |
3454 { | |
3455 } | |
3456 else | |
3457 { | |
3458 assert(0); | |
3459 } | |
3460 //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]); | |
3461 } | |
3462 #if 0 | |
3463 printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this); | |
3464 for (size_t j = 0; j < tiargs->dim; j++) | |
3465 { | |
3466 Object *o = (Object *)tiargs->data[j]; | |
3467 Type *ta = isType(o); | |
3468 Expression *ea = isExpression(o); | |
3469 Dsymbol *sa = isDsymbol(o); | |
3470 Tuple *va = isTuple(o); | |
3471 | |
3472 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va); | |
3473 } | |
3474 #endif | |
3475 } | |
3476 | |
3477 /********************************************** | |
3478 * Find template declaration corresponding to template instance. | |
3479 */ | |
3480 | |
3481 TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) | |
3482 { | |
3483 //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars()); | |
3484 if (!tempdecl) | |
3485 { | |
3486 /* Given: | |
3487 * foo!( ... ) | |
3488 * figure out which TemplateDeclaration foo refers to. | |
3489 */ | |
3490 Dsymbol *s; | |
3491 Dsymbol *scopesym; | |
3492 Identifier *id; | |
3493 int i; | |
3494 | |
3495 id = name; | |
3496 s = sc->search(loc, id, &scopesym); | |
3497 if (!s) | |
3498 { error("identifier '%s' is not defined", id->toChars()); | |
3499 return NULL; | |
3500 } | |
3501 #if LOG | |
3502 printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind()); | |
3503 if (s->parent) | |
3504 printf("s->parent = '%s'\n", s->parent->toChars()); | |
3505 #endif | |
3506 withsym = scopesym->isWithScopeSymbol(); | |
3507 | |
3508 /* We might have found an alias within a template when | |
3509 * we really want the template. | |
3510 */ | |
3511 TemplateInstance *ti; | |
3512 if (s->parent && | |
3513 (ti = s->parent->isTemplateInstance()) != NULL) | |
3514 { | |
3515 if ( | |
3516 (ti->name == id || | |
3517 ti->toAlias()->ident == id) | |
3518 && | |
3519 ti->tempdecl) | |
3520 { | |
3521 /* This is so that one can refer to the enclosing | |
3522 * template, even if it has the same name as a member | |
3523 * of the template, if it has a !(arguments) | |
3524 */ | |
3525 tempdecl = ti->tempdecl; | |
3526 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
3527 tempdecl = tempdecl->overroot; // then get the start | |
3528 s = tempdecl; | |
3529 } | |
3530 } | |
3531 | |
3532 s = s->toAlias(); | |
3533 | |
3534 /* It should be a TemplateDeclaration, not some other symbol | |
3535 */ | |
3536 tempdecl = s->isTemplateDeclaration(); | |
3537 if (!tempdecl) | |
3538 { | |
3539 if (!s->parent && global.errors) | |
3540 return NULL; | |
3541 if (!s->parent && s->getType()) | |
3542 { Dsymbol *s2 = s->getType()->toDsymbol(sc); | |
3543 if (!s2) | |
3544 { | |
3545 error("%s is not a template declaration, it is a %s", id->toChars(), s->kind()); | |
3546 return NULL; | |
3547 } | |
3548 s = s2; | |
3549 } | |
3550 #ifdef DEBUG | |
3551 //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars()); | |
3552 #endif | |
3553 //assert(s->parent); | |
3554 TemplateInstance *ti = s->parent ? s->parent->isTemplateInstance() : NULL; | |
3555 if (ti && | |
3556 (ti->name == id || | |
3557 ti->toAlias()->ident == id) | |
3558 && | |
3559 ti->tempdecl) | |
3560 { | |
3561 /* This is so that one can refer to the enclosing | |
3562 * template, even if it has the same name as a member | |
3563 * of the template, if it has a !(arguments) | |
3564 */ | |
3565 tempdecl = ti->tempdecl; | |
3566 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
3567 tempdecl = tempdecl->overroot; // then get the start | |
3568 } | |
3569 else | |
3570 { | |
3571 error("%s is not a template declaration, it is a %s", id->toChars(), s->kind()); | |
3572 return NULL; | |
3573 } | |
3574 } | |
3575 } | |
3576 else | |
3577 assert(tempdecl->isTemplateDeclaration()); | |
3578 return tempdecl; | |
3579 } | |
3580 | |
3581 TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) | |
3582 { | |
3583 /* Since there can be multiple TemplateDeclaration's with the same | |
3584 * name, look for the best match. | |
3585 */ | |
3586 TemplateDeclaration *td_ambig = NULL; | |
3587 TemplateDeclaration *td_best = NULL; | |
3588 MATCH m_best = MATCHnomatch; | |
3589 Objects dedtypes; | |
3590 | |
3591 #if LOG | |
3592 printf("TemplateInstance::findBestMatch()\n"); | |
3593 #endif | |
3594 for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) | |
3595 { | |
3596 MATCH m; | |
3597 | |
3598 //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]); | |
3599 | |
3600 // If more arguments than parameters, | |
3601 // then this is no match. | |
3602 if (td->parameters->dim < tiargs->dim) | |
3603 { | |
3604 if (!td->isVariadic()) | |
3605 continue; | |
3606 } | |
3607 | |
3608 dedtypes.setDim(td->parameters->dim); | |
3609 dedtypes.zero(); | |
3610 if (!td->scope) | |
3611 { | |
3612 error("forward reference to template declaration %s", td->toChars()); | |
3613 return NULL; | |
3614 } | |
3615 m = td->matchWithInstance(this, &dedtypes, 0); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3616 //printf("matchWithInstance = %d\n", m); |
336 | 3617 if (!m) // no match at all |
3618 continue; | |
3619 | |
3620 if (m < m_best) | |
3621 goto Ltd_best; | |
3622 if (m > m_best) | |
3623 goto Ltd; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3624 |
336 | 3625 { |
3626 // Disambiguate by picking the most specialized TemplateDeclaration | |
3627 int c1 = td->leastAsSpecialized(td_best); | |
3628 int c2 = td_best->leastAsSpecialized(td); | |
3629 //printf("c1 = %d, c2 = %d\n", c1, c2); | |
3630 | |
3631 if (c1 > c2) | |
3632 goto Ltd; | |
3633 else if (c1 < c2) | |
3634 goto Ltd_best; | |
3635 else | |
3636 goto Lambig; | |
3637 } | |
3638 | |
3639 Lambig: // td_best and td are ambiguous | |
3640 td_ambig = td; | |
3641 continue; | |
3642 | |
3643 Ltd_best: // td_best is the best match so far | |
3644 td_ambig = NULL; | |
3645 continue; | |
3646 | |
3647 Ltd: // td is the new best match | |
3648 td_ambig = NULL; | |
3649 td_best = td; | |
3650 m_best = m; | |
3651 tdtypes.setDim(dedtypes.dim); | |
3652 memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * sizeof(void *)); | |
3653 continue; | |
3654 } | |
3655 | |
3656 if (!td_best) | |
3657 { | |
3658 error("%s does not match any template declaration", toChars()); | |
3659 return NULL; | |
3660 } | |
3661 if (td_ambig) | |
3662 { | |
3663 error("%s matches more than one template declaration, %s and %s", | |
3664 toChars(), td_best->toChars(), td_ambig->toChars()); | |
3665 } | |
3666 | |
3667 /* The best match is td_best | |
3668 */ | |
3669 tempdecl = td_best; | |
3670 | |
3671 #if 0 | |
3672 /* Cast any value arguments to be same type as value parameter | |
3673 */ | |
3674 for (size_t i = 0; i < tiargs->dim; i++) | |
3675 { Object *o = (Object *)tiargs->data[i]; | |
3676 Expression *ea = isExpression(o); // value argument | |
3677 TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; | |
3678 assert(tp); | |
3679 TemplateValueParameter *tvp = tp->isTemplateValueParameter(); | |
3680 if (tvp) | |
3681 { | |
3682 assert(ea); | |
3683 ea = ea->castTo(tvp->valType); | |
3684 ea = ea->optimize(WANTvalue | WANTinterpret); | |
3685 tiargs->data[i] = (Object *)ea; | |
3686 } | |
3687 } | |
3688 #endif | |
3689 | |
3690 #if LOG | |
3691 printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars()); | |
3692 #endif | |
3693 return tempdecl; | |
3694 } | |
3695 | |
3696 | |
3697 /***************************************** | |
3698 * Determines if a TemplateInstance will need a nested | |
3699 * generation of the TemplateDeclaration. | |
3700 */ | |
3701 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3702 int TemplateInstance::hasNestedArgs(Objects *args) |
336 | 3703 { int nested = 0; |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3704 //printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars()); |
336 | 3705 |
3706 /* A nested instance happens when an argument references a local | |
3707 * symbol that is on the stack. | |
3708 */ | |
3709 for (size_t i = 0; i < args->dim; i++) | |
3710 { Object *o = (Object *)args->data[i]; | |
3711 Expression *ea = isExpression(o); | |
3712 Dsymbol *sa = isDsymbol(o); | |
3713 Tuple *va = isTuple(o); | |
3714 if (ea) | |
3715 { | |
3716 if (ea->op == TOKvar) | |
3717 { | |
3718 sa = ((VarExp *)ea)->var; | |
3719 goto Lsa; | |
3720 } | |
3721 if (ea->op == TOKfunction) | |
3722 { | |
3723 sa = ((FuncExp *)ea)->fd; | |
3724 goto Lsa; | |
3725 } | |
3726 } | |
3727 else if (sa) | |
3728 { | |
3729 Lsa: | |
3730 Declaration *d = sa->isDeclaration(); | |
3731 if (d && !d->isDataseg() && | |
3732 #if DMDV2 | |
3733 !(d->storage_class & STCmanifest) && | |
3734 #endif | |
3735 (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && | |
3736 !isTemplateMixin()) | |
3737 { | |
3738 // if module level template | |
3739 if (tempdecl->toParent()->isModule()) | |
3740 { Dsymbol *dparent = d->toParent(); | |
3741 if (!isnested) | |
3742 isnested = dparent; | |
3743 else if (isnested != dparent) | |
3744 { | |
3745 /* Select the more deeply nested of the two. | |
3746 * Error if one is not nested inside the other. | |
3747 */ | |
3748 for (Dsymbol *p = isnested; p; p = p->parent) | |
3749 { | |
3750 if (p == dparent) | |
3751 goto L1; // isnested is most nested | |
3752 } | |
876
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3753 for (Dsymbol *p = dparent; p; p = p->parent) |
336 | 3754 { |
3755 if (p == isnested) | |
3756 { isnested = dparent; | |
3757 goto L1; // dparent is most nested | |
3758 } | |
3759 } | |
876
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3760 error("%s is nested in both %s and %s", |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3761 toChars(), isnested->toChars(), dparent->toChars()); |
336 | 3762 } |
3763 L1: | |
3764 //printf("\tnested inside %s\n", isnested->toChars()); | |
3765 nested |= 1; | |
3766 } | |
3767 else | |
3768 error("cannot use local '%s' as template parameter", d->toChars()); | |
3769 } | |
3770 } | |
3771 else if (va) | |
3772 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3773 nested |= hasNestedArgs(&va->objects); |
336 | 3774 } |
3775 } | |
3776 return nested; | |
3777 } | |
3778 | |
3779 /**************************************** | |
3780 * This instance needs an identifier for name mangling purposes. | |
3781 * Create one by taking the template declaration name and adding | |
3782 * the type signature for it. | |
3783 */ | |
3784 | |
3785 Identifier *TemplateInstance::genIdent() | |
3786 { OutBuffer buf; | |
3787 char *id; | |
3788 Objects *args; | |
3789 | |
3790 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); | |
3791 id = tempdecl->ident->toChars(); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3792 buf.printf("__T%zu%s", strlen(id), id); |
336 | 3793 args = tiargs; |
3794 for (int i = 0; i < args->dim; i++) | |
3795 { Object *o = (Object *)args->data[i]; | |
3796 Type *ta = isType(o); | |
3797 Expression *ea = isExpression(o); | |
3798 Dsymbol *sa = isDsymbol(o); | |
3799 Tuple *va = isTuple(o); | |
3800 //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va); | |
3801 if (ta) | |
3802 { | |
3803 buf.writeByte('T'); | |
3804 if (ta->deco) | |
3805 buf.writestring(ta->deco); | |
3806 else | |
3807 { | |
3808 #ifdef DEBUG | |
3809 printf("ta = %d, %s\n", ta->ty, ta->toChars()); | |
3810 #endif | |
3811 assert(global.errors); | |
3812 } | |
3813 } | |
3814 else if (ea) | |
3815 { sinteger_t v; | |
3816 real_t r; | |
3817 | |
3818 if (ea->op == TOKvar) | |
3819 { | |
3820 sa = ((VarExp *)ea)->var; | |
3821 ea = NULL; | |
3822 goto Lsa; | |
3823 } | |
3824 if (ea->op == TOKfunction) | |
3825 { | |
3826 sa = ((FuncExp *)ea)->fd; | |
3827 ea = NULL; | |
3828 goto Lsa; | |
3829 } | |
3830 buf.writeByte('V'); | |
3831 if (ea->op == TOKtuple) | |
3832 { ea->error("tuple is not a valid template value argument"); | |
3833 continue; | |
3834 } | |
3835 #if 1 | |
3836 /* Use deco that matches what it would be for a function parameter | |
3837 */ | |
3838 buf.writestring(ea->type->deco); | |
3839 #else | |
3840 // Use type of parameter, not type of argument | |
3841 TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; | |
3842 assert(tp); | |
3843 TemplateValueParameter *tvp = tp->isTemplateValueParameter(); | |
3844 assert(tvp); | |
3845 buf.writestring(tvp->valType->deco); | |
3846 #endif | |
3847 ea->toMangleBuffer(&buf); | |
3848 } | |
3849 else if (sa) | |
3850 { | |
3851 Lsa: | |
3852 buf.writeByte('S'); | |
3853 Declaration *d = sa->isDeclaration(); | |
3854 if (d && !d->type->deco) | |
3855 error("forward reference of %s", d->toChars()); | |
3856 else | |
3857 { | |
3858 char *p = sa->mangle(); | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1089
diff
changeset
|
3859 buf.printf("%zu%s", strlen(p), p); |
336 | 3860 } |
3861 } | |
3862 else if (va) | |
3863 { | |
3864 assert(i + 1 == args->dim); // must be last one | |
3865 args = &va->objects; | |
3866 i = -1; | |
3867 } | |
3868 else | |
3869 assert(0); | |
3870 } | |
3871 buf.writeByte('Z'); | |
3872 id = buf.toChars(); | |
3873 buf.data = NULL; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3874 //printf("\tgenIdent = %s\n", id); |
336 | 3875 return new Identifier(id, TOKidentifier); |
3876 } | |
3877 | |
3878 | |
3879 /**************************************************** | |
3880 * Declare parameters of template instance, initialize them with the | |
3881 * template instance arguments. | |
3882 */ | |
3883 | |
3884 void TemplateInstance::declareParameters(Scope *scope) | |
3885 { | |
3886 //printf("TemplateInstance::declareParameters()\n"); | |
3887 for (int i = 0; i < tdtypes.dim; i++) | |
3888 { | |
3889 TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; | |
3890 //Object *o = (Object *)tiargs->data[i]; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
3891 Object *o = (Object *)tdtypes.data[i]; // initializer for tp |
336 | 3892 |
3893 //printf("\ttdtypes[%d] = %p\n", i, o); | |
3894 tempdecl->declareParameter(scope, tp, o); | |
3895 } | |
3896 } | |
3897 | |
3898 | |
3899 void TemplateInstance::semantic2(Scope *sc) | |
3900 { int i; | |
3901 | |
3902 if (semanticdone >= 2) | |
3903 return; | |
3904 semanticdone = 2; | |
3905 #if LOG | |
3906 printf("+TemplateInstance::semantic2('%s')\n", toChars()); | |
3907 #endif | |
3908 if (!errors && members) | |
3909 { | |
3910 sc = tempdecl->scope; | |
3911 assert(sc); | |
3912 sc = sc->push(argsym); | |
3913 sc = sc->push(this); | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3914 sc->tinst = this; |
336 | 3915 for (i = 0; i < members->dim; i++) |
3916 { | |
3917 Dsymbol *s = (Dsymbol *)members->data[i]; | |
3918 #if LOG | |
3919 printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); | |
3920 #endif | |
3921 s->semantic2(sc); | |
3922 } | |
3923 sc = sc->pop(); | |
3924 sc->pop(); | |
3925 } | |
3926 #if LOG | |
3927 printf("-TemplateInstance::semantic2('%s')\n", toChars()); | |
3928 #endif | |
3929 } | |
3930 | |
3931 void TemplateInstance::semantic3(Scope *sc) | |
3932 { | |
3933 #if LOG | |
3934 printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone); | |
3935 #endif | |
3936 //if (toChars()[0] == 'D') *(char*)0=0; | |
3937 if (semanticdone >= 3) | |
3938 return; | |
3939 semanticdone = 3; | |
3940 if (!errors && members) | |
3941 { | |
3942 sc = tempdecl->scope; | |
3943 sc = sc->push(argsym); | |
3944 sc = sc->push(this); | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
3945 sc->tinst = this; |
336 | 3946 for (int i = 0; i < members->dim; i++) |
3947 { | |
3948 Dsymbol *s = (Dsymbol *)members->data[i]; | |
3949 s->semantic3(sc); | |
3950 } | |
3951 sc = sc->pop(); | |
3952 sc->pop(); | |
3953 } | |
3954 } | |
3955 | |
3956 void TemplateInstance::toObjFile(int multiobj) | |
3957 { | |
3958 #if LOG | |
3959 printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this); | |
3960 #endif | |
3961 if (!errors && members) | |
3962 { | |
3963 if (multiobj) | |
3964 // Append to list of object files to be written later | |
3965 //obj_append(this); | |
3966 assert(0 && "multiobj"); | |
3967 else | |
3968 { | |
3969 for (int i = 0; i < members->dim; i++) | |
3970 { | |
3971 Dsymbol *s = (Dsymbol *)members->data[i]; | |
3972 s->toObjFile(multiobj); | |
3973 } | |
3974 } | |
3975 } | |
3976 } | |
3977 | |
3978 void TemplateInstance::inlineScan() | |
3979 { | |
3980 #if LOG | |
3981 printf("TemplateInstance::inlineScan('%s')\n", toChars()); | |
3982 #endif | |
3983 if (!errors && members) | |
3984 { | |
3985 for (int i = 0; i < members->dim; i++) | |
3986 { | |
3987 Dsymbol *s = (Dsymbol *)members->data[i]; | |
3988 s->inlineScan(); | |
3989 } | |
3990 } | |
3991 } | |
3992 | |
3993 void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3994 { | |
3995 int i; | |
3996 | |
3997 Identifier *id = name; | |
3998 buf->writestring(id->toChars()); | |
3999 buf->writestring("!("); | |
4000 if (nest) | |
4001 buf->writestring("..."); | |
4002 else | |
4003 { | |
4004 nest++; | |
4005 Objects *args = tiargs; | |
4006 for (i = 0; i < args->dim; i++) | |
4007 { | |
4008 if (i) | |
4009 buf->writeByte(','); | |
4010 Object *oarg = (Object *)args->data[i]; | |
4011 ObjectToCBuffer(buf, hgs, oarg); | |
4012 } | |
4013 nest--; | |
4014 } | |
4015 buf->writeByte(')'); | |
4016 } | |
4017 | |
4018 | |
4019 Dsymbol *TemplateInstance::toAlias() | |
4020 { | |
4021 #if LOG | |
4022 printf("TemplateInstance::toAlias()\n"); | |
4023 #endif | |
4024 if (!inst) | |
4025 { error("cannot resolve forward reference"); | |
4026 return this; | |
4027 } | |
4028 | |
4029 if (inst != this) | |
4030 return inst->toAlias(); | |
4031 | |
4032 if (aliasdecl) | |
4033 return aliasdecl->toAlias(); | |
4034 | |
4035 return inst; | |
4036 } | |
4037 | |
4038 AliasDeclaration *TemplateInstance::isAliasDeclaration() | |
4039 { | |
4040 return aliasdecl; | |
4041 } | |
4042 | |
4043 const char *TemplateInstance::kind() | |
4044 { | |
4045 return "template instance"; | |
4046 } | |
4047 | |
4048 int TemplateInstance::oneMember(Dsymbol **ps) | |
4049 { | |
4050 *ps = NULL; | |
4051 return TRUE; | |
4052 } | |
4053 | |
4054 char *TemplateInstance::toChars() | |
4055 { | |
4056 OutBuffer buf; | |
4057 HdrGenState hgs; | |
4058 char *s; | |
4059 | |
4060 toCBuffer(&buf, &hgs); | |
4061 s = buf.toChars(); | |
4062 buf.data = NULL; | |
4063 return s; | |
4064 } | |
4065 | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4066 void TemplateInstance::printInstantiationTrace() |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4067 { |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4068 if(global.gag) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4069 return; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4070 |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4071 const int max_shown = 6; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4072 |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4073 // determine instantiation depth |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4074 int n_instantiations = 1; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4075 TemplateInstance* cur = this; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4076 while(cur = cur->tinst) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4077 ++n_instantiations; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4078 |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4079 // show full trace only if it's short or verbose is on |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4080 if(n_instantiations <= max_shown || global.params.verbose) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4081 { |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4082 cur = this; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4083 while(cur) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4084 { |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4085 fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars()); |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4086 cur = cur->tinst; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4087 } |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4088 } |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4089 else |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4090 { |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4091 cur = this; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4092 size_t i = 0; |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4093 for(; i < max_shown/2; ++i, cur = cur->tinst) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4094 fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars()); |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4095 fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown); |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4096 for(; i < n_instantiations - max_shown + max_shown/2; ++i, cur = cur->tinst) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4097 {} |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4098 for(; i < n_instantiations; ++i, cur = cur->tinst) |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4099 fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars()); |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4100 } |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4101 } |
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
527
diff
changeset
|
4102 |
336 | 4103 /* ======================== TemplateMixin ================================ */ |
4104 | |
4105 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, | |
4106 Array *idents, Objects *tiargs) | |
4107 : TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1]) | |
4108 { | |
4109 //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : ""); | |
4110 this->ident = ident; | |
4111 this->tqual = tqual; | |
4112 this->idents = idents; | |
4113 this->tiargs = tiargs ? tiargs : new Objects(); | |
4114 this->scope = NULL; | |
4115 } | |
4116 | |
4117 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) | |
4118 { TemplateMixin *tm; | |
4119 | |
4120 Array *ids = new Array(); | |
4121 ids->setDim(idents->dim); | |
4122 for (int i = 0; i < idents->dim; i++) | |
4123 { // Matches TypeQualified::syntaxCopyHelper() | |
4124 Identifier *id = (Identifier *)idents->data[i]; | |
4125 if (id->dyncast() == DYNCAST_DSYMBOL) | |
4126 { | |
4127 TemplateInstance *ti = (TemplateInstance *)id; | |
4128 | |
4129 ti = (TemplateInstance *)ti->syntaxCopy(NULL); | |
4130 id = (Identifier *)ti; | |
4131 } | |
4132 ids->data[i] = id; | |
4133 } | |
4134 | |
4135 tm = new TemplateMixin(loc, ident, | |
4136 (Type *)(tqual ? tqual->syntaxCopy() : NULL), | |
4137 ids, tiargs); | |
4138 TemplateInstance::syntaxCopy(tm); | |
4139 return tm; | |
4140 } | |
4141 | |
4142 void TemplateMixin::semantic(Scope *sc) | |
4143 { | |
4144 #if LOG | |
4145 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); | |
4146 fflush(stdout); | |
4147 #endif | |
4148 if (semanticdone && | |
4149 // This for when a class/struct contains mixin members, and | |
4150 // is done over because of forward references | |
4151 (!parent || !toParent()->isAggregateDeclaration())) | |
4152 { | |
4153 #if LOG | |
4154 printf("\tsemantic done\n"); | |
4155 #endif | |
4156 return; | |
4157 } | |
4158 if (!semanticdone) | |
4159 semanticdone = 1; | |
4160 #if LOG | |
4161 printf("\tdo semantic\n"); | |
4162 #endif | |
4163 | |
4164 #if !IN_LLVM | |
4165 // dont know what this is | |
4166 util_progress(); | |
4167 #endif | |
4168 | |
4169 Scope *scx = NULL; | |
4170 if (scope) | |
4171 { sc = scope; | |
4172 scx = scope; // save so we don't make redundant copies | |
4173 scope = NULL; | |
4174 } | |
4175 | |
4176 // Follow qualifications to find the TemplateDeclaration | |
4177 if (!tempdecl) | |
4178 { Dsymbol *s; | |
4179 int i; | |
4180 Identifier *id; | |
4181 | |
4182 if (tqual) | |
4183 { s = tqual->toDsymbol(sc); | |
4184 i = 0; | |
4185 } | |
4186 else | |
4187 { | |
4188 i = 1; | |
4189 id = (Identifier *)idents->data[0]; | |
4190 switch (id->dyncast()) | |
4191 { | |
4192 case DYNCAST_IDENTIFIER: | |
4193 s = sc->search(loc, id, NULL); | |
4194 break; | |
4195 | |
4196 case DYNCAST_DSYMBOL: | |
4197 { | |
4198 TemplateInstance *ti = (TemplateInstance *)id; | |
4199 ti->semantic(sc); | |
4200 s = ti; | |
4201 break; | |
4202 } | |
4203 default: | |
4204 assert(0); | |
4205 } | |
4206 } | |
4207 | |
4208 for (; i < idents->dim; i++) | |
4209 { | |
4210 if (!s) | |
4211 break; | |
4212 id = (Identifier *)idents->data[i]; | |
4213 s = s->searchX(loc, sc, id); | |
4214 } | |
4215 if (!s) | |
4216 { | |
4217 error("is not defined"); | |
4218 inst = this; | |
4219 return; | |
4220 } | |
4221 tempdecl = s->toAlias()->isTemplateDeclaration(); | |
4222 if (!tempdecl) | |
4223 { | |
4224 error("%s isn't a template", s->toChars()); | |
4225 inst = this; | |
4226 return; | |
4227 } | |
4228 } | |
4229 | |
4230 // Look for forward reference | |
4231 assert(tempdecl); | |
4232 for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) | |
4233 { | |
4234 if (!td->scope) | |
4235 { | |
4236 /* Cannot handle forward references if mixin is a struct member, | |
4237 * because addField must happen during struct's semantic, not | |
4238 * during the mixin semantic. | |
4239 * runDeferred will re-run mixin's semantic outside of the struct's | |
4240 * semantic. | |
4241 */ | |
4242 semanticdone = 0; | |
4243 AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); | |
4244 if (ad) | |
4245 ad->sizeok = 2; | |
4246 else | |
4247 { | |
4248 // Forward reference | |
4249 //printf("forward reference - deferring\n"); | |
4250 scope = scx ? scx : new Scope(*sc); | |
4251 scope->setNoFree(); | |
4252 scope->module->addDeferredSemantic(this); | |
4253 } | |
4254 return; | |
4255 } | |
4256 } | |
4257 | |
4258 // Run semantic on each argument, place results in tiargs[] | |
4259 semanticTiargs(sc); | |
4260 | |
4261 tempdecl = findBestMatch(sc); | |
4262 if (!tempdecl) | |
4263 { inst = this; | |
4264 return; // error recovery | |
4265 } | |
4266 | |
4267 if (!ident) | |
4268 ident = genIdent(); | |
4269 | |
4270 inst = this; | |
4271 parent = sc->parent; | |
4272 | |
4273 /* Detect recursive mixin instantiations. | |
4274 */ | |
4275 for (Dsymbol *s = parent; s; s = s->parent) | |
4276 { | |
4277 //printf("\ts = '%s'\n", s->toChars()); | |
4278 TemplateMixin *tm = s->isTemplateMixin(); | |
4279 if (!tm || tempdecl != tm->tempdecl) | |
4280 continue; | |
4281 | |
4282 /* Different argument list lengths happen with variadic args | |
4283 */ | |
4284 if (tiargs->dim != tm->tiargs->dim) | |
4285 continue; | |
4286 | |
4287 for (int i = 0; i < tiargs->dim; i++) | |
4288 { Object *o = (Object *)tiargs->data[i]; | |
4289 Type *ta = isType(o); | |
4290 Expression *ea = isExpression(o); | |
4291 Dsymbol *sa = isDsymbol(o); | |
4292 Object *tmo = (Object *)tm->tiargs->data[i]; | |
4293 if (ta) | |
4294 { | |
4295 Type *tmta = isType(tmo); | |
4296 if (!tmta) | |
4297 goto Lcontinue; | |
4298 if (!ta->equals(tmta)) | |
4299 goto Lcontinue; | |
4300 } | |
4301 else if (ea) | |
4302 { Expression *tme = isExpression(tmo); | |
4303 if (!tme || !ea->equals(tme)) | |
4304 goto Lcontinue; | |
4305 } | |
4306 else if (sa) | |
4307 { | |
4308 Dsymbol *tmsa = isDsymbol(tmo); | |
4309 if (sa != tmsa) | |
4310 goto Lcontinue; | |
4311 } | |
4312 else | |
4313 assert(0); | |
4314 } | |
4315 error("recursive mixin instantiation"); | |
4316 return; | |
4317 | |
4318 Lcontinue: | |
4319 continue; | |
4320 } | |
4321 | |
4322 // Copy the syntax trees from the TemplateDeclaration | |
4323 members = Dsymbol::arraySyntaxCopy(tempdecl->members); | |
4324 if (!members) | |
4325 return; | |
4326 | |
4327 symtab = new DsymbolTable(); | |
4328 | |
4329 for (Scope *sce = sc; 1; sce = sce->enclosing) | |
4330 { | |
4331 ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym; | |
4332 if (sds) | |
4333 { | |
4334 sds->importScope(this, PROTpublic); | |
4335 break; | |
4336 } | |
4337 } | |
4338 | |
4339 #if LOG | |
4340 printf("\tcreate scope for template parameters '%s'\n", toChars()); | |
4341 #endif | |
4342 Scope *scy = sc; | |
4343 scy = sc->push(this); | |
4344 scy->parent = this; | |
4345 | |
4346 argsym = new ScopeDsymbol(); | |
4347 argsym->parent = scy->parent; | |
4348 Scope *scope = scy->push(argsym); | |
4349 | |
4350 unsigned errorsave = global.errors; | |
4351 | |
4352 // Declare each template parameter as an alias for the argument type | |
4353 declareParameters(scope); | |
4354 | |
4355 // Add members to enclosing scope, as well as this scope | |
4356 for (unsigned i = 0; i < members->dim; i++) | |
4357 { Dsymbol *s; | |
4358 | |
4359 s = (Dsymbol *)members->data[i]; | |
4360 s->addMember(scope, this, i); | |
4361 //sc->insert(s); | |
4362 //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); | |
4363 //printf("s->parent = %s\n", s->parent->toChars()); | |
4364 } | |
4365 | |
4366 // Do semantic() analysis on template instance members | |
4367 #if LOG | |
4368 printf("\tdo semantic() on template instance members '%s'\n", toChars()); | |
4369 #endif | |
4370 Scope *sc2; | |
4371 sc2 = scope->push(this); | |
4372 sc2->offset = sc->offset; | |
4373 for (int i = 0; i < members->dim; i++) | |
4374 { | |
4375 Dsymbol *s = (Dsymbol *)members->data[i]; | |
4376 s->semantic(sc2); | |
4377 } | |
4378 sc->offset = sc2->offset; | |
4379 | |
4380 /* The problem is when to parse the initializer for a variable. | |
4381 * Perhaps VarDeclaration::semantic() should do it like it does | |
4382 * for initializers inside a function. | |
4383 */ | |
4384 // if (sc->parent->isFuncDeclaration()) | |
4385 | |
4386 semantic2(sc2); | |
4387 | |
4388 if (sc->func) | |
4389 { | |
4390 semantic3(sc2); | |
4391 } | |
4392 | |
4393 // Give additional context info if error occurred during instantiation | |
4394 if (global.errors != errorsave) | |
4395 { | |
4396 error("error instantiating"); | |
4397 } | |
4398 | |
4399 sc2->pop(); | |
4400 | |
4401 scope->pop(); | |
4402 | |
4403 // if (!isAnonymous()) | |
4404 { | |
4405 scy->pop(); | |
4406 } | |
4407 #if LOG | |
4408 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); | |
4409 #endif | |
4410 } | |
4411 | |
4412 void TemplateMixin::semantic2(Scope *sc) | |
4413 { int i; | |
4414 | |
4415 if (semanticdone >= 2) | |
4416 return; | |
4417 semanticdone = 2; | |
4418 #if LOG | |
4419 printf("+TemplateMixin::semantic2('%s')\n", toChars()); | |
4420 #endif | |
4421 if (members) | |
4422 { | |
4423 assert(sc); | |
4424 sc = sc->push(argsym); | |
4425 sc = sc->push(this); | |
4426 for (i = 0; i < members->dim; i++) | |
4427 { | |
4428 Dsymbol *s = (Dsymbol *)members->data[i]; | |
4429 #if LOG | |
4430 printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); | |
4431 #endif | |
4432 s->semantic2(sc); | |
4433 } | |
4434 sc = sc->pop(); | |
4435 sc->pop(); | |
4436 } | |
4437 #if LOG | |
4438 printf("-TemplateMixin::semantic2('%s')\n", toChars()); | |
4439 #endif | |
4440 } | |
4441 | |
4442 void TemplateMixin::semantic3(Scope *sc) | |
4443 { int i; | |
4444 | |
4445 if (semanticdone >= 3) | |
4446 return; | |
4447 semanticdone = 3; | |
4448 #if LOG | |
4449 printf("TemplateMixin::semantic3('%s')\n", toChars()); | |
4450 #endif | |
4451 if (members) | |
4452 { | |
4453 sc = sc->push(argsym); | |
4454 sc = sc->push(this); | |
4455 for (i = 0; i < members->dim; i++) | |
4456 { | |
4457 Dsymbol *s = (Dsymbol *)members->data[i]; | |
4458 s->semantic3(sc); | |
4459 } | |
4460 sc = sc->pop(); | |
4461 sc->pop(); | |
4462 } | |
4463 } | |
4464 | |
4465 void TemplateMixin::inlineScan() | |
4466 { | |
4467 TemplateInstance::inlineScan(); | |
4468 } | |
4469 | |
4470 const char *TemplateMixin::kind() | |
4471 { | |
4472 return "mixin"; | |
4473 } | |
4474 | |
4475 int TemplateMixin::oneMember(Dsymbol **ps) | |
4476 { | |
4477 return Dsymbol::oneMember(ps); | |
4478 } | |
4479 | |
4480 int TemplateMixin::hasPointers() | |
4481 { | |
4482 //printf("TemplateMixin::hasPointers() %s\n", toChars()); | |
4483 for (size_t i = 0; i < members->dim; i++) | |
4484 { | |
4485 Dsymbol *s = (Dsymbol *)members->data[i]; | |
4486 //printf(" s = %s %s\n", s->kind(), s->toChars()); | |
4487 if (s->hasPointers()) | |
4488 { | |
4489 return 1; | |
4490 } | |
4491 } | |
4492 return 0; | |
4493 } | |
4494 | |
4495 char *TemplateMixin::toChars() | |
4496 { | |
4497 OutBuffer buf; | |
4498 HdrGenState hgs; | |
4499 char *s; | |
4500 | |
4501 TemplateInstance::toCBuffer(&buf, &hgs); | |
4502 s = buf.toChars(); | |
4503 buf.data = NULL; | |
4504 return s; | |
4505 } | |
4506 | |
4507 void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4508 { | |
4509 buf->writestring("mixin "); | |
4510 | |
4511 for (int i = 0; i < idents->dim; i++) | |
4512 { Identifier *id = (Identifier *)idents->data[i]; | |
4513 | |
4514 if (i) | |
4515 buf->writeByte('.'); | |
4516 buf->writestring(id->toChars()); | |
4517 } | |
4518 buf->writestring("!("); | |
4519 if (tiargs) | |
4520 { | |
4521 for (int i = 0; i < tiargs->dim; i++) | |
4522 { if (i) | |
4523 buf->writebyte(','); | |
4524 Object *oarg = (Object *)tiargs->data[i]; | |
4525 Type *t = isType(oarg); | |
4526 Expression *e = isExpression(oarg); | |
4527 Dsymbol *s = isDsymbol(oarg); | |
4528 if (t) | |
4529 t->toCBuffer(buf, NULL, hgs); | |
4530 else if (e) | |
4531 e->toCBuffer(buf, hgs); | |
4532 else if (s) | |
4533 { | |
4534 char *p = s->ident ? s->ident->toChars() : s->toChars(); | |
4535 buf->writestring(p); | |
4536 } | |
4537 else if (!oarg) | |
4538 { | |
4539 buf->writestring("NULL"); | |
4540 } | |
4541 else | |
4542 { | |
4543 assert(0); | |
4544 } | |
4545 } | |
4546 } | |
4547 buf->writebyte(')'); | |
4548 if (ident) | |
4549 { | |
4550 buf->writebyte(' '); | |
4551 buf->writestring(ident->toChars()); | |
4552 } | |
4553 buf->writebyte(';'); | |
4554 buf->writenl(); | |
4555 } | |
4556 | |
4557 | |
4558 void TemplateMixin::toObjFile(int multiobj) | |
4559 { | |
4560 //printf("TemplateMixin::toObjFile('%s')\n", toChars()); | |
4561 TemplateInstance::toObjFile(multiobj); | |
4562 } | |
4563 |