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