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