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