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