Mercurial > projects > ddmd
annotate dmd/TemplateInstance.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | 206db751bd4c |
children | e7769d53e750 |
rev | line source |
---|---|
0 | 1 module dmd.TemplateInstance; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.ScopeDsymbol; |
5 import dmd.IntegerExp; | |
6 import dmd.Identifier; | |
7 import dmd.ArrayTypes; | |
8 import dmd.TupleDeclaration; | |
9 import dmd.TemplateParameter; | |
10 import dmd.AliasDeclaration; | |
11 import dmd.TemplateDeclaration; | |
12 import dmd.TupleExp; | |
13 import dmd.WithScopeSymbol; | |
14 import dmd.Dsymbol; | |
15 import dmd.Module; | |
16 import dmd.ArrayTypes; | |
17 import dmd.Loc; | |
18 import dmd.Global; | |
19 import dmd.Util; | |
20 import dmd.Type; | |
21 import dmd.Expression; | |
22 import dmd.Tuple; | |
23 import dmd.STC; | |
24 import dmd.TOK; | |
25 import dmd.TY; | |
26 import dmd.TypeTuple; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
27 import dmd.Parameter; |
0 | 28 import dmd.WANT; |
29 import dmd.ExpInitializer; | |
30 import dmd.Array; | |
31 import dmd.DsymbolTable; | |
32 import dmd.Scope; | |
33 import dmd.OutBuffer; | |
34 import dmd.HdrGenState; | |
35 import dmd.VarDeclaration; | |
36 import dmd.VarExp; | |
37 import dmd.FuncExp; | |
38 import dmd.Declaration; | |
39 import dmd.MATCH; | |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
40 import dmd.TypeFunction; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
41 import dmd.TemplateTupleParameter; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
42 import dmd.FuncDeclaration; |
135 | 43 import dmd.OverloadSet; |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
44 import dmd.templates.Util; |
0 | 45 |
46 import dmd.backend.glue; | |
47 | |
48 Tuple isTuple(Object o) | |
49 { | |
50 //return dynamic_cast<Tuple *>(o); | |
51 ///if (!o || o.dyncast() != DYNCAST_TUPLE) | |
52 /// return null; | |
53 return cast(Tuple)o; | |
54 } | |
55 | |
56 /****************************** | |
57 * If o1 matches o2, return 1. | |
58 * Else, return 0. | |
59 */ | |
60 | |
61 bool match(Object o1, Object o2, TemplateDeclaration tempdecl, Scope sc) | |
62 { | |
63 Type t1 = isType(o1); | |
64 Type t2 = isType(o2); | |
65 Expression e1 = isExpression(o1); | |
66 Expression e2 = isExpression(o2); | |
67 Dsymbol s1 = isDsymbol(o1); | |
68 Dsymbol s2 = isDsymbol(o2); | |
69 Tuple v1 = isTuple(o1); | |
70 Tuple v2 = isTuple(o2); | |
71 | |
72 //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); | |
73 | |
74 /* A proper implementation of the various equals() overrides | |
75 * should make it possible to just do o1.equals(o2), but | |
76 * we'll do that another day. | |
77 */ | |
78 | |
79 if (t1) | |
80 { | |
81 /* if t1 is an instance of ti, then give error | |
82 * about recursive expansions. | |
83 */ | |
84 Dsymbol s = t1.toDsymbol(sc); | |
85 if (s && s.parent) | |
86 { | |
87 TemplateInstance ti1 = s.parent.isTemplateInstance(); | |
88 if (ti1 && ti1.tempdecl == tempdecl) | |
89 { | |
90 for (Scope sc1 = sc; sc1; sc1 = sc1.enclosing) | |
91 { | |
92 if (sc1.scopesym == ti1) | |
93 { | |
94 error("recursive template expansion for template argument %s", t1.toChars()); | |
95 return true; // fake a match | |
96 } | |
97 } | |
98 } | |
99 } | |
100 | |
101 //printf("t1 = %s\n", t1.toChars()); | |
102 //printf("t2 = %s\n", t2.toChars()); | |
103 if (!t2 || !t1.equals(t2)) | |
104 goto Lnomatch; | |
105 } | |
106 else if (e1) | |
107 { | |
108 static if (false) { | |
109 if (e1 && e2) | |
110 { | |
111 printf("match %d\n", e1.equals(e2)); | |
112 e1.print(); | |
113 e2.print(); | |
114 e1.type.print(); | |
115 e2.type.print(); | |
116 } | |
117 } | |
118 if (!e2) | |
119 goto Lnomatch; | |
120 if (!e1.equals(e2)) | |
121 goto Lnomatch; | |
122 } | |
123 else if (s1) | |
124 { | |
125 //printf("%p %s, %p %s\n", s1, s1.toChars(), s2, s2.toChars()); | |
126 if (!s2 || !s1.equals(s2) || s1.parent != s2.parent) | |
127 { | |
128 goto Lnomatch; | |
129 } | |
130 version (DMDV2) { | |
131 VarDeclaration vv1 = s1.isVarDeclaration(); | |
132 VarDeclaration vv2 = s2.isVarDeclaration(); | |
133 if (vv1 && vv2 && vv1.storage_class & vv2.storage_class & STCmanifest) | |
134 { | |
135 ExpInitializer ei1 = vv1.init.isExpInitializer(); | |
136 ExpInitializer ei2 = vv2.init.isExpInitializer(); | |
137 if (ei1 && ei2 && !ei1.exp.equals(ei2.exp)) | |
138 goto Lnomatch; | |
139 } | |
140 } | |
141 } | |
142 else if (v1) | |
143 { | |
144 if (!v2) | |
145 goto Lnomatch; | |
146 | |
147 if (v1.objects.dim != v2.objects.dim) | |
148 goto Lnomatch; | |
149 | |
150 for (size_t i = 0; i < v1.objects.dim; i++) | |
151 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
152 if (!match(v1.objects[i], v2.objects[i], tempdecl, sc)) |
0 | 153 goto Lnomatch; |
154 } | |
155 } | |
156 //printf("match\n"); | |
157 return true; // match | |
158 | |
159 Lnomatch: | |
160 //printf("nomatch\n"); | |
161 return false; // nomatch; | |
162 } | |
163 | |
164 class TemplateInstance : ScopeDsymbol | |
165 { | |
166 /* Given: | |
167 * foo!(args) => | |
168 * name = foo | |
169 * tiargs = args | |
170 */ | |
171 Identifier name; | |
172 //Array idents; | |
173 Objects tiargs; // Array of Types/Expressions of template | |
174 // instance arguments [int*, char, 10*10] | |
175 | |
176 Objects tdtypes; // Array of Types/Expressions corresponding | |
177 // to TemplateDeclaration.parameters | |
178 // [int, char, 100] | |
179 | |
180 TemplateDeclaration tempdecl; // referenced by foo.bar.abc | |
181 TemplateInstance inst; // refer to existing instance | |
182 TemplateInstance tinst; // enclosing template instance | |
183 ScopeDsymbol argsym; // argument symbol table | |
184 AliasDeclaration aliasdecl; // !=null if instance is an alias for its | |
185 // sole member | |
186 WithScopeSymbol withsym; // if a member of a with statement | |
187 int semanticRun; // has semantic() been done? | |
188 int semantictiargsdone; // has semanticTiargs() been done? | |
189 int nest; // for recursion detection | |
190 int havetempdecl; // 1 if used second constructor | |
191 Dsymbol isnested; // if referencing local symbols, this is the context | |
192 int errors; // 1 if compiled with errors | |
193 version (IN_GCC) { | |
194 /* On some targets, it is necessary to know whether a symbol | |
195 will be emitted in the output or not before the symbol | |
196 is used. This can be different from getModule(). */ | |
197 Module objFileModule; | |
198 } | |
199 | |
200 this(Loc loc, Identifier ident) | |
201 { | |
202 super(null); | |
203 | |
204 version (LOG) { | |
205 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident.toChars() : "null"); | |
206 } | |
207 this.loc = loc; | |
208 this.name = ident; | |
209 | |
210 tdtypes = new Objects(); | |
211 } | |
212 | |
213 /***************** | |
214 * This constructor is only called when we figured out which function | |
215 * template to instantiate. | |
216 */ | |
217 this(Loc loc, TemplateDeclaration td, Objects tiargs) | |
218 { | |
219 super(null); | |
220 | |
221 version (LOG) { | |
222 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td.toChars()); | |
223 } | |
224 this.loc = loc; | |
225 this.name = td.ident; | |
226 this.tiargs = tiargs; | |
227 this.tempdecl = td; | |
228 this.semantictiargsdone = 1; | |
229 this.havetempdecl = 1; | |
230 | |
231 assert(cast(size_t)cast(void*)tempdecl.scope_ > 0x10000); | |
232 | |
233 tdtypes = new Objects(); | |
234 } | |
235 | |
236 static Objects arraySyntaxCopy(Objects objs) | |
237 { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
238 Objects a = null; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
239 if (objs) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
240 { a = new Objects(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
241 a.setDim(objs.dim); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
242 for (size_t i = 0; i < objs.dim; i++) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
243 { |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
244 a[i] = objectSyntaxCopy(objs[i]); |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
245 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
246 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
247 return a; |
0 | 248 } |
249 | |
72 | 250 override Dsymbol syntaxCopy(Dsymbol s) |
0 | 251 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
252 TemplateInstance ti; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
253 |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
254 if (s) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
255 ti = cast(TemplateInstance)s; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
256 else |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
257 ti = new TemplateInstance(loc, name); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
258 |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
259 ti.tiargs = arraySyntaxCopy(tiargs); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
260 |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
261 ScopeDsymbol.syntaxCopy(ti); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
262 return ti; |
0 | 263 } |
264 | |
72 | 265 override void semantic(Scope sc) |
0 | 266 { |
135 | 267 semantic(sc, null); |
268 } | |
269 | |
270 void semantic(Scope sc, Expressions fargs) | |
271 { | |
0 | 272 if (global.errors) |
273 { | |
274 if (!global.gag) | |
275 { | |
276 /* Trying to soldier on rarely generates useful messages | |
277 * at this point. | |
278 */ | |
279 fatal(); | |
280 } | |
281 return; | |
282 } | |
283 | |
284 version (LOG) { | |
285 printf("\n+TemplateInstance.semantic('%s', this=%p)\n", toChars(), this); | |
286 } | |
287 | |
288 if (inst) // if semantic() was already run | |
289 { | |
290 version (LOG) { | |
291 printf("-TemplateInstance.semantic('%s', this=%p) already run\n", inst.toChars(), inst); | |
292 } | |
293 return; | |
294 } | |
295 | |
296 // get the enclosing template instance from the scope tinst | |
297 tinst = sc.tinst; | |
298 | |
299 if (semanticRun != 0) | |
300 { | |
301 error(loc, "recursive template expansion"); | |
302 // inst = this; | |
303 return; | |
304 } | |
305 | |
306 semanticRun = 1; | |
307 | |
308 version (LOG) { | |
309 printf("\tdo semantic\n"); | |
310 } | |
311 if (havetempdecl) | |
312 { | |
313 assert(cast(size_t)cast(void*)tempdecl.scope_ > 0x10000); | |
314 | |
315 // Deduce tdtypes | |
316 tdtypes.setDim(tempdecl.parameters.dim); | |
317 if (!tempdecl.matchWithInstance(this, tdtypes, 2)) | |
318 { | |
319 error("incompatible arguments for template instantiation"); | |
320 inst = this; | |
321 return; | |
322 } | |
323 } | |
324 else | |
325 { | |
326 /* Run semantic on each argument, place results in tiargs[] | |
327 * (if we havetempdecl, then tiargs is already evaluated) | |
328 */ | |
329 semanticTiargs(sc); | |
330 | |
331 tempdecl = findTemplateDeclaration(sc); | |
332 if (tempdecl) | |
333 tempdecl = findBestMatch(sc); | |
334 | |
335 if (!tempdecl || global.errors) | |
336 { | |
337 inst = this; | |
338 //printf("error return %p, %d\n", tempdecl, global.errors); | |
339 return; // error recovery | |
340 } | |
341 } | |
342 | |
343 hasNestedArgs(tiargs); | |
344 | |
345 /* See if there is an existing TemplateInstantiation that already | |
346 * implements the typeargs. If so, just refer to that one instead. | |
347 */ | |
348 | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
349 foreach (ti; tempdecl.instances) |
0 | 350 { |
351 version (LOG) { | |
352 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti.toChars()); | |
353 } | |
354 assert(tdtypes.dim == ti.tdtypes.dim); | |
355 | |
356 // Nesting must match | |
357 if (isnested !is ti.isnested) | |
358 { | |
359 //printf("test2 isnested %s ti.isnested %s\n", isnested ? isnested.toChars() : "", ti.isnested ? ti.isnested.toChars() : ""); | |
360 continue; | |
361 } | |
362 static if (false) { | |
363 if (isnested && sc.parent != ti.parent) | |
364 continue; | |
365 } | |
366 for (size_t j = 0; j < tdtypes.dim; j++) | |
367 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
368 Object o1 = tdtypes[j]; |
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
369 Object o2 = ti.tdtypes[j]; |
0 | 370 if (!match(o1, o2, tempdecl, sc)) |
371 { | |
372 goto L1; | |
135 | 373 } |
374 } | |
375 | |
376 /* Template functions may have different instantiations based on | |
377 * "auto ref" parameters. | |
378 */ | |
379 if (fargs) | |
380 { | |
381 FuncDeclaration fd = ti.toAlias().isFuncDeclaration(); | |
382 if (fd) | |
383 { | |
384 auto fparameters = fd.getParameters(null); | |
385 size_t nfparams = Parameter.dim(fparameters); // Num function parameters | |
386 for (int i = 0; i < nfparams && i < fargs.dim; i++) | |
387 { auto fparam = Parameter.getNth(fparameters, i); | |
388 auto farg = fargs[i]; | |
389 if (fparam.storageClass & STCauto) // if "auto ref" | |
390 { | |
391 if (farg.isLvalue()) | |
392 { if (!(fparam.storageClass & STC.STCref)) | |
393 goto L1; // auto ref's don't match | |
394 } | |
395 else | |
396 { if (fparam.storageClass & STC.STCref) | |
397 goto L1; // auto ref's don't match | |
398 } | |
399 } | |
400 } | |
0 | 401 } |
402 } | |
403 | |
404 // It's a match | |
405 inst = ti; | |
406 parent = ti.parent; | |
407 version (LOG) { | |
408 printf("\tit's a match with instance %p\n", inst); | |
409 } | |
410 return; | |
411 | |
412 L1: | |
413 ; | |
414 } | |
415 | |
416 /* So, we need to implement 'this' instance. | |
417 */ | |
418 version (LOG) { | |
419 printf("\timplement template instance '%s'\n", toChars()); | |
420 } | |
421 uint errorsave = global.errors; | |
422 inst = this; | |
423 int tempdecl_instance_idx = tempdecl.instances.dim; | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
126
diff
changeset
|
424 tempdecl.instances.push(this); |
0 | 425 parent = tempdecl.parent; |
426 //printf("parent = '%s'\n", parent.kind()); | |
427 | |
428 ident = genIdent(); // need an identifier for name mangling purposes. | |
429 | |
430 static if (true) { | |
431 if (isnested) | |
432 parent = isnested; | |
433 } | |
434 //printf("parent = '%s'\n", parent.kind()); | |
435 | |
436 // Add 'this' to the enclosing scope's members[] so the semantic routines | |
437 // will get called on the instance members | |
438 static if (true) { | |
439 int dosemantic3 = 0; | |
440 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
441 Dsymbols a; |
0 | 442 |
443 Scope scx = sc; | |
444 static if (false) { | |
445 for (scx = sc; scx; scx = scx.enclosing) | |
446 if (scx.scopesym) | |
447 break; | |
448 } | |
449 | |
450 //if (scx && scx.scopesym) printf("3: scx is %s %s\n", scx.scopesym.kind(), scx.scopesym.toChars()); | |
451 if (scx && scx.scopesym && | |
452 scx.scopesym.members && !scx.scopesym.isTemplateMixin() | |
453 | |
454 /// static if (false) { // removed because it bloated compile times | |
455 /// /* The problem is if A imports B, and B imports A, and both A | |
456 /// * and B instantiate the same template, does the compilation of A | |
457 /// * or the compilation of B do the actual instantiation? | |
458 /// * | |
459 /// * see bugzilla 2500. | |
460 /// */ | |
461 /// && !scx.module.selfImports() | |
462 /// } | |
463 ) | |
464 { | |
465 //printf("\t1: adding to %s %s\n", scx.scopesym.kind(), scx.scopesym.toChars()); | |
466 a = scx.scopesym.members; | |
467 } | |
468 else | |
469 { Module m = sc.module_.importedFrom; | |
470 //printf("\t2: adding to module %s instead of module %s\n", m.toChars(), sc.module.toChars()); | |
471 a = m.members; | |
472 if (m.semanticRun >= 3) | |
473 dosemantic3 = 1; | |
474 } | |
475 | |
476 for (int i = 0; 1; i++) | |
477 { | |
478 if (i == a.dim) | |
479 { | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
480 a.push(this); |
0 | 481 break; |
482 } | |
483 | |
74
7e0d548de9e6
Switch Arrays of Dsymbols to the new templated Vector type
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
484 if (this is a[i]) // if already in Array |
0 | 485 break; |
486 } | |
487 } | |
488 } | |
489 | |
490 // Copy the syntax trees from the TemplateDeclaration | |
491 members = Dsymbol.arraySyntaxCopy(tempdecl.members); | |
492 | |
493 // Create our own scope for the template parameters | |
494 Scope scope_ = tempdecl.scope_; | |
495 if (!tempdecl.semanticRun) | |
496 { | |
497 error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl.toChars()); | |
498 return; | |
499 } | |
500 | |
501 version (LOG) { | |
502 printf("\tcreate scope for template parameters '%s'\n", toChars()); | |
503 } | |
504 argsym = new ScopeDsymbol(); | |
505 argsym.parent = scope_.parent; | |
506 scope_ = scope_.push(argsym); | |
507 // scope.stc = 0; | |
508 | |
509 // Declare each template parameter as an alias for the argument type | |
510 Scope paramscope = scope_.push(); | |
511 paramscope.stc = STCundefined; | |
512 declareParameters(paramscope); | |
513 paramscope.pop(); | |
514 | |
515 // Add members of template instance to template instance symbol table | |
516 // parent = scope.scopesym; | |
517 symtab = new DsymbolTable(); | |
13 | 518 bool memnum = false; |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
519 foreach(Dsymbol s; members) |
0 | 520 { |
521 version (LOG) { | |
522 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s.toChars(), s, s.kind(), this.toChars(), memnum); | |
523 } | |
524 memnum |= s.addMember(scope_, this, memnum); | |
525 } | |
526 | |
527 version (LOG) { | |
528 printf("adding members done\n"); | |
529 } | |
530 | |
531 /* See if there is only one member of template instance, and that | |
532 * member has the same name as the template instance. | |
533 * If so, this template instance becomes an alias for that member. | |
534 */ | |
535 //printf("members.dim = %d\n", members.dim); | |
536 if (members.dim) | |
537 { | |
538 Dsymbol s; | |
539 if (Dsymbol.oneMembers(members, &s) && s) | |
540 { | |
541 //printf("s.kind = '%s'\n", s.kind()); | |
542 //s.print(); | |
543 //printf("'%s', '%s'\n", s.ident.toChars(), tempdecl.ident.toChars()); | |
544 if (s.ident && s.ident.equals(tempdecl.ident)) | |
545 { | |
546 //printf("setting aliasdecl\n"); | |
547 aliasdecl = new AliasDeclaration(loc, s.ident, s); | |
548 } | |
549 } | |
550 } | |
135 | 551 |
552 /* If function template declaration | |
553 */ | |
554 if (fargs && aliasdecl) | |
555 { | |
556 FuncDeclaration fd = aliasdecl.toAlias().isFuncDeclaration(); | |
557 if (fd) | |
558 { | |
559 /* Transmit fargs to type so that TypeFunction::semantic() can | |
560 * resolve any "auto ref" storage classes. | |
561 */ | |
562 auto tf = cast(TypeFunction)fd.type; | |
563 if (tf && tf.ty == TY.Tfunction) | |
564 tf.fargs = fargs; | |
565 } | |
566 } | |
0 | 567 |
568 // Do semantic() analysis on template instance members | |
569 version (LOG) { | |
570 printf("\tdo semantic() on template instance members '%s'\n", toChars()); | |
571 } | |
572 Scope sc2; | |
573 sc2 = scope_.push(this); | |
574 //printf("isnested = %d, sc.parent = %s\n", isnested, sc.parent.toChars()); | |
575 sc2.parent = /*isnested ? sc.parent :*/ this; | |
576 sc2.tinst = this; | |
577 | |
578 try | |
579 { | |
79 | 580 // static int nest; |
0 | 581 //printf("%d\n", nest); |
582 if (++nest > 500) | |
583 { | |
584 global.gag = 0; // ensure error message gets printed | |
585 error("recursive expansion"); | |
586 fatal(); | |
587 } | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
588 foreach(Dsymbol s; members) |
0 | 589 { |
590 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s.toChars(), s, s.kind(), this.toChars()); | |
591 //printf("test: isnested = %d, sc2.parent = %s\n", isnested, sc2.parent.toChars()); | |
592 // if (isnested) | |
593 // s.parent = sc.parent; | |
594 //printf("test3: isnested = %d, s.parent = %s\n", isnested, s.parent.toChars()); | |
595 s.semantic(sc2); | |
596 //printf("test4: isnested = %d, s.parent = %s\n", isnested, s.parent.toChars()); | |
597 sc2.module_.runDeferredSemantic(); | |
598 } | |
599 --nest; | |
600 } | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
601 catch (Exception e) |
0 | 602 { |
603 global.gag = 0; // ensure error message gets printed | |
604 error("recursive expansion"); | |
605 fatal(); | |
606 } | |
607 | |
608 /* If any of the instantiation members didn't get semantic() run | |
609 * on them due to forward references, we cannot run semantic2() | |
610 * or semantic3() yet. | |
611 */ | |
612 for (size_t i = 0; i < Module.deferred.dim; i++) | |
613 { | |
614 Dsymbol sd = cast(Dsymbol)Module.deferred.data[i]; | |
615 | |
616 if (sd.parent is this) | |
617 goto Laftersemantic; | |
618 } | |
619 | |
620 /* The problem is when to parse the initializer for a variable. | |
621 * Perhaps VarDeclaration.semantic() should do it like it does | |
622 * for initializers inside a function. | |
623 */ | |
624 // if (sc.parent.isFuncDeclaration()) | |
625 | |
626 /* BUG 782: this has problems if the classes this depends on | |
627 * are forward referenced. Find a way to defer semantic() | |
628 * on this template. | |
629 */ | |
630 semantic2(sc2); | |
631 | |
632 if (sc.func || dosemantic3) | |
633 { | |
79 | 634 try |
635 { | |
636 // static int nest; // TODO: | |
637 if (++nest > 300) | |
638 { | |
639 global.gag = 0; // ensure error message gets printed | |
640 error("recursive expansion"); | |
641 fatal(); | |
642 } | |
643 semantic3(sc2); | |
644 --nest; | |
645 } | |
646 catch (Exception e) | |
647 { | |
648 global.gag = 0; // ensure error message gets printed | |
649 error("recursive expansion"); | |
650 fatal(); | |
651 } | |
0 | 652 } |
653 | |
654 Laftersemantic: | |
655 sc2.pop(); | |
656 | |
657 scope_.pop(); | |
658 | |
659 // Give additional context info if error occurred during instantiation | |
660 if (global.errors != errorsave) | |
661 { | |
662 error("error instantiating"); | |
135 | 663 if (tinst) |
0 | 664 { |
665 tinst.printInstantiationTrace(); | |
666 } | |
667 errors = 1; | |
668 if (global.gag) | |
669 tempdecl.instances.remove(tempdecl_instance_idx); | |
670 } | |
671 | |
672 version (LOG) { | |
673 printf("-TemplateInstance.semantic('%s', this=%p)\n", toChars(), this); | |
674 } | |
675 } | |
676 | |
72 | 677 override void semantic2(Scope sc) |
0 | 678 { |
679 if (semanticRun >= 2) | |
680 return; | |
681 | |
682 semanticRun = 2; | |
683 version (LOG) { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
684 printf("+TemplateInstance.semantic2('%s')\n", toChars()); |
0 | 685 } |
686 | |
687 if (!errors && members) | |
688 { | |
689 sc = tempdecl.scope_; | |
690 assert(sc); | |
691 sc = sc.push(argsym); | |
692 sc = sc.push(this); | |
693 sc.tinst = this; | |
694 | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
695 foreach(Dsymbol s; members) |
0 | 696 { |
697 version (LOG) { | |
698 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); | |
699 } | |
700 s.semantic2(sc); | |
701 } | |
702 | |
703 sc = sc.pop(); | |
704 sc.pop(); | |
705 } | |
706 | |
707 version (LOG) { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
708 printf("-TemplateInstance.semantic2('%s')\n", toChars()); |
0 | 709 } |
710 } | |
711 | |
72 | 712 override void semantic3(Scope sc) |
0 | 713 { |
714 version (LOG) { | |
715 printf("TemplateInstance.semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun); | |
716 } | |
717 //if (toChars()[0] == 'D') *(char*)0=0; | |
718 if (semanticRun >= 3) | |
719 return; | |
720 semanticRun = 3; | |
721 if (!errors && members) | |
722 { | |
723 sc = tempdecl.scope_; | |
724 sc = sc.push(argsym); | |
725 sc = sc.push(this); | |
726 sc.tinst = this; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
727 foreach(Dsymbol s; members) |
0 | 728 s.semantic3(sc); |
729 sc = sc.pop(); | |
730 sc.pop(); | |
731 } | |
732 } | |
733 | |
72 | 734 override void inlineScan() |
0 | 735 { |
736 version (LOG) { | |
737 printf("TemplateInstance.inlineScan('%s')\n", toChars()); | |
738 } | |
739 if (!errors && members) | |
740 { | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
741 foreach(Dsymbol s; members) |
0 | 742 s.inlineScan(); |
743 } | |
744 } | |
745 | |
72 | 746 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 747 { |
748 int i; | |
749 | |
750 Identifier id = name; | |
751 buf.writestring(id.toChars()); | |
752 buf.writestring("!("); | |
753 if (nest) | |
754 buf.writestring("..."); | |
755 else | |
756 { | |
757 nest++; | |
758 Objects args = tiargs; | |
759 for (i = 0; i < args.dim; i++) | |
760 { | |
761 if (i) | |
762 buf.writeByte(','); | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
763 Object oarg = args[i]; |
0 | 764 ObjectToCBuffer(buf, hgs, oarg); |
765 } | |
766 nest--; | |
767 } | |
768 buf.writeByte(')'); | |
769 } | |
770 | |
72 | 771 override Dsymbol toAlias() // resolve real symbol |
0 | 772 { |
79 | 773 version (LOG) |
774 { | |
775 writef("TemplateInstance.toAlias()\n"); | |
0 | 776 } |
777 if (!inst) | |
778 { | |
779 error("cannot resolve forward reference"); | |
79 | 780 errors = 1; |
0 | 781 return this; |
782 } | |
783 | |
784 if (inst !is this) | |
785 return inst.toAlias(); | |
786 | |
787 if (aliasdecl) | |
788 { | |
789 return aliasdecl.toAlias(); | |
790 } | |
791 | |
792 return inst; | |
793 } | |
794 | |
72 | 795 override string kind() |
0 | 796 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
797 return "template instance"; |
0 | 798 } |
799 | |
72 | 800 override bool oneMember(Dsymbol* ps) |
0 | 801 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
802 *ps = null; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
803 return true; |
0 | 804 } |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
805 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
806 /***************************************************** |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
807 * Determine if template instance is really a template function, |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
808 * and that template function needs to infer types from the function |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
809 * arguments. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
810 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
811 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
812 bool needsTypeInference(Scope sc) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
813 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
814 //printf("TemplateInstance::needsTypeInference() %s\n", toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
815 if (!tempdecl) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
816 tempdecl = findTemplateDeclaration(sc); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
817 for (TemplateDeclaration td = tempdecl; td; td = td.overnext) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
818 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
819 /* If any of the overloaded template declarations need inference, |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
820 * then return TRUE |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
821 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
822 FuncDeclaration fd; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
823 if (!td.onemember || |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
824 (fd = td.onemember.toAlias().isFuncDeclaration()) is null || |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
825 fd.type.ty != TY.Tfunction) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
826 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
827 /* Not a template function, therefore type inference is not possible. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
828 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
829 //printf("false\n"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
830 return false; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
831 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
832 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
833 /* Determine if the instance arguments, tiargs, are all that is necessary |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
834 * to instantiate the template. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
835 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
836 TemplateTupleParameter tp = td.isVariadic(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
837 //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
838 TypeFunction fdtype = cast(TypeFunction)fd.type; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
839 if (Parameter.dim(fdtype.parameters) && |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
840 (tp || tiargs.dim < td.parameters.dim)) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
841 return true; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
842 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
843 //printf("false\n"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
844 return false; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
845 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
846 |
72 | 847 override string toChars() |
0 | 848 { |
849 scope OutBuffer buf = new OutBuffer(); | |
850 HdrGenState hgs; | |
851 | |
852 toCBuffer(buf, &hgs); | |
853 return buf.extractString(); | |
854 } | |
855 | |
72 | 856 override string mangle() |
0 | 857 { |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
858 OutBuffer buf = new OutBuffer(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
859 string id; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
860 |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
861 static if (0) { |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
862 printf("TemplateInstance.mangle() %s", toChars()); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
863 if (parent) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
864 printf(" parent = %s %s", parent.kind(), parent.toChars()); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
865 printf("\n"); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
866 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
867 id = ident ? ident.toChars() : toChars(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
868 if (!tempdecl) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
869 error("is not defined"); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
870 else if (tempdecl.parent) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
871 { |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
872 string p = tempdecl.parent.mangle(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
873 if (p[0] == '_' && p[1] == 'D') |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
874 p = p[2..$]; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
875 buf.writestring(p); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
876 } |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
877 buf.printf("%d%s", id.length, id); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
878 id = buf.toChars(); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
879 buf.data = null; |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
880 //printf("TemplateInstance.mangle() %s = %s\n", toChars(), id); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
881 return id; |
0 | 882 } |
883 | |
135 | 884 /************************************** |
885 * Given an error instantiating the TemplateInstance, | |
886 * give the nested TemplateInstance instantiations that got | |
887 * us here. Those are a list threaded into the nested scopes. | |
888 */ | |
0 | 889 void printInstantiationTrace() |
890 { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
891 if (global.gag) |
135 | 892 return; |
893 /+ | |
894 const int max_shown = 6; | |
895 const string format = "%s: instantiated from here: %s\n"; | |
896 | |
897 // determine instantiation depth and number of recursive instantiations | |
898 int n_instantiations = 1; | |
899 int n_totalrecursions = 0; | |
900 for (TemplateInstance cur = this; cur; cur = cur.tinst) | |
901 { | |
902 ++n_instantiations; | |
903 // If two instantiations use the same declaration, they are recursive. | |
904 // (this works even if they are instantiated from different places in the | |
905 // same template). | |
906 // In principle, we could also check for multiple-template recursion, but it's | |
907 // probably not worthwhile. | |
908 if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl | |
909 && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc)) | |
910 ++n_totalrecursions; | |
911 } | |
912 | |
913 // show full trace only if it's short or verbose is on | |
914 if (n_instantiations <= max_shown || global.params.verbose) | |
915 { | |
916 for (TemplateInstance cur = this; cur; cur = cur.tinst) | |
917 { | |
918 fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars()); | |
919 } | |
920 } | |
921 else if (n_instantiations - n_totalrecursions <= max_shown) | |
922 { | |
923 // By collapsing recursive instantiations into a single line, | |
924 // we can stay under the limit. | |
925 int recursionDepth=0; | |
926 for (TemplateInstance cur = this; cur; cur = cur.tinst) | |
927 { | |
928 if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl | |
929 && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc)) | |
930 { | |
931 ++recursionDepth; | |
932 } | |
933 else | |
934 { | |
935 if (recursionDepth) | |
936 fprintf(stdmsg, "%s: %d recursive instantiations from here: %s\n", cur.loc.toChars(), recursionDepth+2, cur.toChars()); | |
937 else | |
938 fprintf(stdmsg,format, cur.loc.toChars(), cur.toChars()); | |
939 recursionDepth = 0; | |
940 } | |
941 } | |
942 } | |
943 else | |
944 { | |
945 // Even after collapsing the recursions, the depth is too deep. | |
946 // Just display the first few and last few instantiations. | |
947 size_t i = 0; | |
948 for (TemplateInstance cur = this; cur; cur = cur.tinst) | |
949 { | |
950 if (i == max_shown / 2) | |
951 fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown); | |
952 | |
953 if (i < max_shown / 2 || | |
954 i >= n_instantiations - max_shown + max_shown / 2) | |
955 fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars()); | |
956 ++i; | |
957 } | |
958 } | |
959 +/ | |
0 | 960 } |
961 | |
72 | 962 override void toObjFile(int multiobj) // compile to .obj file |
0 | 963 { |
964 version (LOG) { | |
965 printf("TemplateInstance.toObjFile('%s', this = %p)\n", toChars(), this); | |
966 } | |
967 if (!errors && members) | |
968 { | |
969 if (multiobj) | |
970 // Append to list of object files to be written later | |
971 obj_append(this); | |
972 else | |
973 { | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
74
diff
changeset
|
974 foreach(Dsymbol s; members) |
0 | 975 s.toObjFile(multiobj); |
976 } | |
977 } | |
978 } | |
979 | |
980 // Internal | |
981 /********************************** | |
982 * Input: | |
983 * flags 1: replace const variables with their initializers | |
984 */ | |
985 static void semanticTiargs(Loc loc, Scope sc, Objects tiargs, int flags) | |
986 { | |
987 // Run semantic on each argument, place results in tiargs[] | |
988 //printf("+TemplateInstance.semanticTiargs() %s\n", toChars()); | |
989 if (!tiargs) | |
990 return; | |
991 for (size_t j = 0; j < tiargs.dim; j++) | |
992 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
993 Object o = tiargs[j]; |
0 | 994 Type ta = isType(o); |
995 Expression ea = isExpression(o); | |
996 Dsymbol sa = isDsymbol(o); | |
997 | |
998 //printf("1: tiargs.data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta); | |
999 if (ta) | |
1000 { | |
1001 //printf("type %s\n", ta.toChars()); | |
1002 // It might really be an Expression or an Alias | |
1003 ta.resolve(loc, sc, &ea, &ta, &sa); | |
1004 if (ea) | |
1005 { | |
1006 ea = ea.semantic(sc); | |
1007 /* This test is to skip substituting a const var with | |
1008 * its initializer. The problem is the initializer won't | |
1009 * match with an 'alias' parameter. Instead, do the | |
1010 * const substitution in TemplateValueParameter.matchArg(). | |
1011 */ | |
1012 if (ea.op != TOKvar || flags & 1) | |
1013 ea = ea.optimize(WANTvalue | WANTinterpret); | |
1014 | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1015 tiargs[j] = ea; |
0 | 1016 } |
1017 else if (sa) | |
1018 { | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1019 tiargs[j] = sa; |
0 | 1020 TupleDeclaration d = sa.toAlias().isTupleDeclaration(); |
1021 if (d) | |
1022 { | |
1023 size_t dim = d.objects.dim; | |
1024 tiargs.remove(j); | |
1025 tiargs.insert(j, d.objects); | |
1026 j--; | |
1027 } | |
1028 } | |
1029 else if (ta) | |
1030 { | |
1031 Ltype: | |
1032 if (ta.ty == Ttuple) | |
1033 { | |
1034 // Expand tuple | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
1035 auto tt = cast(TypeTuple)ta; |
0 | 1036 size_t dim = tt.arguments.dim; |
1037 tiargs.remove(j); | |
1038 if (dim) | |
1039 { | |
1040 tiargs.reserve(dim); | |
1041 for (size_t i = 0; i < dim; i++) | |
1042 { | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
121
diff
changeset
|
1043 auto arg = tt.arguments[i]; |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1044 tiargs.insert(j + i, arg.type); |
0 | 1045 } |
1046 } | |
1047 j--; | |
1048 } | |
1049 else | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1050 tiargs[j] = ta; |
0 | 1051 } |
1052 else | |
1053 { | |
1054 assert(global.errors); | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1055 tiargs[j] = Type.terror; |
0 | 1056 } |
1057 } | |
1058 else if (ea) | |
1059 { | |
1060 if (!ea) | |
1061 { | |
1062 assert(global.errors); | |
1063 ea = new IntegerExp(0); | |
1064 } | |
1065 assert(ea); | |
1066 ea = ea.semantic(sc); | |
1067 if (ea.op != TOKvar || flags & 1) | |
1068 ea = ea.optimize(WANTvalue | WANTinterpret); | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1069 tiargs[j] = ea; |
0 | 1070 if (ea.op == TOKtype) |
1071 { | |
1072 ta = ea.type; | |
1073 goto Ltype; | |
1074 } | |
1075 if (ea.op == TOKtuple) | |
1076 { | |
1077 // Expand tuple | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
1078 auto te = cast(TupleExp)ea; |
0 | 1079 size_t dim = te.exps.dim; |
1080 tiargs.remove(j); | |
1081 if (dim) | |
1082 { | |
1083 tiargs.reserve(dim); | |
1084 for (size_t i = 0; i < dim; i++) | |
94
3a0b150c9841
Objects -> Vector!Object iteration 1
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
91
diff
changeset
|
1085 tiargs.insert(j + i, te.exps[i]); |
0 | 1086 } |
1087 j--; | |
1088 } | |
1089 } | |
1090 else if (sa) | |
1091 { | |
1092 TemplateDeclaration td = sa.isTemplateDeclaration(); | |
1093 if (td && !td.semanticRun && td.literal) | |
1094 td.semantic(sc); | |
1095 } | |
1096 else | |
1097 { | |
1098 assert(0); | |
1099 } | |
1100 //printf("1: tiargs.data[%d] = %p\n", j, tiargs.data[j]); | |
1101 } | |
1102 | |
1103 static if (false) { | |
1104 printf("-TemplateInstance.semanticTiargs('%s', this=%p)\n", toChars(), this); | |
1105 for (size_t j = 0; j < tiargs.dim; j++) | |
1106 { | |
1107 Object o = cast(Object)tiargs.data[j]; | |
1108 Type ta = isType(o); | |
1109 Expression ea = isExpression(o); | |
1110 Dsymbol sa = isDsymbol(o); | |
1111 Tuple va = isTuple(o); | |
1112 | |
1113 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va); | |
1114 } | |
1115 } | |
1116 } | |
1117 | |
1118 void semanticTiargs(Scope sc) | |
1119 { | |
1120 //printf("+TemplateInstance.semanticTiargs() %s\n", toChars()); | |
1121 if (semantictiargsdone) | |
1122 return; | |
1123 | |
1124 semantictiargsdone = 1; | |
1125 semanticTiargs(loc, sc, tiargs, 0); | |
1126 } | |
1127 | |
1128 /********************************************** | |
1129 * Find template declaration corresponding to template instance. | |
1130 */ | |
1131 TemplateDeclaration findTemplateDeclaration(Scope sc) | |
1132 { | |
1133 //printf("TemplateInstance.findTemplateDeclaration() %s\n", toChars()); | |
1134 if (!tempdecl) | |
1135 { | |
1136 /* Given: | |
1137 * foo!( ... ) | |
1138 * figure out which TemplateDeclaration foo refers to. | |
1139 */ | |
1140 Dsymbol s; | |
1141 Dsymbol scopesym; | |
1142 int i; | |
1143 | |
1144 Identifier id = name; | |
1145 s = sc.search(loc, id, &scopesym); | |
1146 if (!s) | |
1147 { | |
135 | 1148 error("template '%s' is not defined", id.toChars()); |
0 | 1149 return null; |
1150 } | |
135 | 1151 |
1152 /* If an OverloadSet, look for a unique member that is a template declaration | |
1153 */ | |
1154 OverloadSet os = s.isOverloadSet(); | |
1155 if (os) | |
1156 { | |
1157 s = null; | |
1158 foreach (s2; os.a) | |
1159 { | |
1160 if (s2.isTemplateDeclaration()) | |
1161 { | |
1162 if (s) | |
1163 error("ambiguous template declaration %s and %s", s.toPrettyChars(), s2.toPrettyChars()); | |
1164 s = s2; | |
1165 } | |
1166 } | |
1167 if (!s) | |
1168 { | |
1169 error("template '%s' is not defined", id.toChars()); | |
1170 return null; | |
1171 } | |
1172 } | |
1173 | |
0 | 1174 version (LOG) { |
1175 printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind()); | |
1176 if (s.parent) | |
1177 printf("s.parent = '%s'\n", s.parent.toChars()); | |
1178 } | |
1179 withsym = scopesym.isWithScopeSymbol(); | |
1180 | |
1181 /* We might have found an alias within a template when | |
1182 * we really want the template. | |
1183 */ | |
1184 TemplateInstance ti; | |
1185 if (s.parent && | |
1186 (ti = s.parent.isTemplateInstance()) !is null) | |
1187 { | |
1188 if ( | |
1189 (ti.name == id || | |
1190 ti.toAlias().ident == id) | |
1191 && | |
1192 ti.tempdecl | |
1193 ) | |
1194 { | |
1195 /* This is so that one can refer to the enclosing | |
1196 * template, even if it has the same name as a member | |
1197 * of the template, if it has a !(arguments) | |
1198 */ | |
1199 tempdecl = ti.tempdecl; | |
1200 if (tempdecl.overroot) // if not start of overloaded list of TemplateDeclaration's | |
1201 tempdecl = tempdecl.overroot; // then get the start | |
1202 | |
1203 s = tempdecl; | |
1204 } | |
1205 } | |
1206 | |
1207 s = s.toAlias(); | |
1208 | |
1209 /* It should be a TemplateDeclaration, not some other symbol | |
1210 */ | |
1211 tempdecl = s.isTemplateDeclaration(); | |
1212 if (!tempdecl) | |
1213 { | |
1214 if (!s.parent && global.errors) | |
1215 return null; | |
1216 if (!s.parent && s.getType()) | |
1217 { | |
1218 Dsymbol s2 = s.getType().toDsymbol(sc); | |
1219 if (!s2) | |
1220 { | |
1221 error("%s is not a template declaration, it is a %s", id.toChars(), s.kind()); | |
1222 return null; | |
1223 } | |
1224 s = s2; | |
1225 } | |
1226 debug { | |
1227 //if (!s.parent) printf("s = %s %s\n", s.kind(), s.toChars()); | |
1228 } | |
1229 //assert(s.parent); | |
1230 TemplateInstance ti2 = s.parent ? s.parent.isTemplateInstance() : null; | |
1231 if (ti2 && | |
1232 (ti2.name == id || | |
1233 ti2.toAlias().ident == id) | |
1234 && | |
1235 ti2.tempdecl | |
1236 ) | |
1237 { | |
1238 /* This is so that one can refer to the enclosing | |
1239 * template, even if it has the same name as a member | |
1240 * of the template, if it has a !(arguments) | |
1241 */ | |
1242 tempdecl = ti2.tempdecl; | |
1243 if (tempdecl.overroot) // if not start of overloaded list of TemplateDeclaration's | |
1244 tempdecl = tempdecl.overroot; // then get the start | |
1245 } | |
1246 else | |
1247 { | |
1248 error("%s is not a template declaration, it is a %s", id.toChars(), s.kind()); | |
1249 return null; | |
1250 } | |
1251 } | |
1252 } | |
1253 else | |
1254 assert(tempdecl.isTemplateDeclaration()); | |
1255 | |
1256 return tempdecl; | |
1257 } | |
1258 | |
1259 TemplateDeclaration findBestMatch(Scope sc) | |
1260 { | |
1261 /* Since there can be multiple TemplateDeclaration's with the same | |
1262 * name, look for the best match. | |
1263 */ | |
1264 TemplateDeclaration td_ambig = null; | |
1265 TemplateDeclaration td_best = null; | |
1266 MATCH m_best = MATCHnomatch; | |
1267 scope Objects dedtypes = new Objects(); | |
1268 | |
1269 version (LOG) { | |
1270 printf("TemplateInstance.findBestMatch()\n"); | |
1271 } | |
1272 // First look for forward references | |
1273 for (TemplateDeclaration td = tempdecl; td; td = td.overnext) | |
1274 { | |
1275 if (!td.semanticRun) | |
1276 { | |
1277 if (td.scope_) | |
1278 { | |
1279 // Try to fix forward reference | |
1280 td.semantic(td.scope_); | |
1281 } | |
1282 if (!td.semanticRun) | |
1283 { | |
1284 error("%s forward references template declaration %s\n", toChars(), td.toChars()); | |
1285 return null; | |
1286 } | |
1287 } | |
1288 } | |
1289 | |
1290 for (TemplateDeclaration td = tempdecl; td; td = td.overnext) | |
1291 { | |
1292 MATCH m; | |
1293 | |
1294 //if (tiargs.dim) printf("2: tiargs.dim = %d, data[0] = %p\n", tiargs.dim, tiargs.data[0]); | |
1295 | |
1296 // If more arguments than parameters, | |
1297 // then this is no match. | |
1298 if (td.parameters.dim < tiargs.dim) | |
1299 { | |
1300 if (!td.isVariadic()) | |
1301 continue; | |
1302 } | |
1303 | |
1304 dedtypes.setDim(td.parameters.dim); | |
1305 dedtypes.zero(); | |
1306 assert(td.semanticRun); | |
1307 m = td.matchWithInstance(this, dedtypes, 0); | |
1308 //printf("matchWithInstance = %d\n", m); | |
1309 if (!m) // no match at all | |
1310 continue; | |
1311 | |
1312 if (m < m_best) | |
1313 goto Ltd_best; | |
1314 if (m > m_best) | |
1315 goto Ltd; | |
1316 | |
1317 { | |
1318 // Disambiguate by picking the most specialized TemplateDeclaration | |
1319 MATCH c1 = td.leastAsSpecialized(td_best); | |
1320 MATCH c2 = td_best.leastAsSpecialized(td); | |
1321 //printf("c1 = %d, c2 = %d\n", c1, c2); | |
1322 | |
1323 if (c1 > c2) | |
1324 goto Ltd; | |
1325 else if (c1 < c2) | |
1326 goto Ltd_best; | |
1327 else | |
1328 goto Lambig; | |
1329 } | |
1330 | |
1331 Lambig: // td_best and td are ambiguous | |
1332 td_ambig = td; | |
1333 continue; | |
1334 | |
1335 Ltd_best: // td_best is the best match so far | |
1336 td_ambig = null; | |
1337 continue; | |
1338 | |
1339 Ltd: // td is the new best match | |
1340 td_ambig = null; | |
1341 td_best = td; | |
1342 m_best = m; | |
1343 tdtypes.setDim(dedtypes.dim); | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
1344 memcpy(tdtypes.ptr, dedtypes.ptr, tdtypes.dim * (void*).sizeof); |
0 | 1345 continue; |
1346 } | |
1347 | |
1348 if (!td_best) | |
1349 { | |
1350 if (tempdecl && !tempdecl.overnext) | |
1351 // Only one template, so we can give better error message | |
1352 error("%s does not match template declaration %s", toChars(), tempdecl.toChars()); | |
1353 else | |
1354 error("%s does not match any template declaration", toChars()); | |
1355 return null; | |
1356 } | |
1357 | |
1358 if (td_ambig) | |
1359 { | |
1360 error("%s matches more than one template declaration, %s and %s", | |
1361 toChars(), td_best.toChars(), td_ambig.toChars()); | |
1362 } | |
1363 | |
1364 /* The best match is td_best | |
1365 */ | |
1366 tempdecl = td_best; | |
1367 | |
1368 static if (false) { | |
1369 /* Cast any value arguments to be same type as value parameter | |
1370 */ | |
1371 for (size_t i = 0; i < tiargs.dim; i++) | |
1372 { | |
1373 Object o = cast(Object)tiargs.data[i]; | |
1374 Expression ea = isExpression(o); // value argument | |
1375 TemplateParameter tp = cast(TemplateParameter)tempdecl.parameters.data[i]; | |
1376 assert(tp); | |
1377 TemplateValueParameter tvp = tp.isTemplateValueParameter(); | |
1378 if (tvp) | |
1379 { | |
1380 assert(ea); | |
1381 ea = ea.castTo(tvp.valType); | |
1382 ea = ea.optimize(WANTvalue | WANTinterpret); | |
1383 tiargs.data[i] = cast(Object)ea; | |
1384 } | |
1385 } | |
1386 } | |
1387 | |
1388 version (LOG) { | |
1389 printf("\tIt's a match with template declaration '%s'\n", tempdecl.toChars()); | |
1390 } | |
1391 return tempdecl; | |
1392 } | |
1393 | |
1394 /**************************************************** | |
1395 * Declare parameters of template instance, initialize them with the | |
1396 * template instance arguments. | |
1397 */ | |
1398 void declareParameters(Scope sc) | |
1399 { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1400 //printf("TemplateInstance.declareParameters()\n"); |
0 | 1401 for (int i = 0; i < tdtypes.dim; i++) |
1402 { | |
121
347de076ad34
TemplateParameters -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1403 auto tp = tempdecl.parameters[i]; |
0 | 1404 //Object o = cast(Object)tiargs.data[i]; |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
1405 Object o = tdtypes[i]; // initializer for tp |
0 | 1406 |
1407 //printf("\ttdtypes[%d] = %p\n", i, o); | |
1408 tempdecl.declareParameter(sc, tp, o); | |
1409 } | |
1410 } | |
1411 | |
1412 /***************************************** | |
1413 * Determines if a TemplateInstance will need a nested | |
1414 * generation of the TemplateDeclaration. | |
1415 */ | |
1416 bool hasNestedArgs(Objects args) | |
1417 { | |
1418 bool nested = false; | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1419 //printf("TemplateInstance.hasNestedArgs('%s')\n", tempdecl.ident.toChars()); |
0 | 1420 |
1421 /* A nested instance happens when an argument references a local | |
1422 * symbol that is on the stack. | |
1423 */ | |
1424 for (size_t i = 0; i < args.dim; i++) | |
1425 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
1426 Object o = args[i]; |
0 | 1427 Expression ea = isExpression(o); |
1428 Dsymbol sa = isDsymbol(o); | |
1429 Tuple va = isTuple(o); | |
1430 if (ea) | |
1431 { | |
1432 if (ea.op == TOKvar) | |
1433 { | |
1434 sa = (cast(VarExp)ea).var; | |
1435 goto Lsa; | |
1436 } | |
1437 if (ea.op == TOKfunction) | |
1438 { | |
1439 sa = (cast(FuncExp)ea).fd; | |
1440 goto Lsa; | |
1441 } | |
1442 } | |
1443 else if (sa) | |
1444 { | |
1445 Lsa: | |
1446 TemplateDeclaration td = sa.isTemplateDeclaration(); | |
96 | 1447 Declaration d = sa.isDeclaration(); |
1448 if ((td && td.literal) || | |
1449 (d && !d.isDataseg() && | |
1450 | |
1451 /// version (DMDV2) { // TODO: | |
0 | 1452 !(d.storage_class & STCmanifest) && |
1453 /// } | |
1454 (!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) && | |
96 | 1455 !isTemplateMixin() |
1456 )) | |
0 | 1457 { |
1458 // if module level template | |
1459 if (tempdecl.toParent().isModule()) | |
1460 { | |
1461 Dsymbol dparent = sa.toParent(); | |
1462 if (!isnested) | |
1463 isnested = dparent; | |
1464 else if (isnested != dparent) | |
1465 { | |
1466 /* Select the more deeply nested of the two. | |
1467 * Error if one is not nested inside the other. | |
1468 */ | |
1469 for (Dsymbol p = isnested; p; p = p.parent) | |
1470 { | |
1471 if (p == dparent) | |
1472 goto L1; // isnested is most nested | |
1473 } | |
1474 for (Dsymbol p = dparent; p; p = p.parent) | |
1475 { | |
1476 if (p == isnested) | |
1477 { | |
1478 isnested = dparent; | |
1479 goto L1; // dparent is most nested | |
1480 } | |
1481 } | |
1482 error("%s is nested in both %s and %s", | |
1483 toChars(), isnested.toChars(), dparent.toChars()); | |
1484 } | |
1485 L1: | |
1486 //printf("\tnested inside %s\n", isnested.toChars()); | |
1487 nested |= 1; | |
1488 } | |
1489 else | |
1490 error("cannot use local '%s' as parameter to non-global template %s", d.toChars(), tempdecl.toChars()); | |
1491 } | |
1492 } | |
1493 else if (va) | |
1494 { | |
1495 nested |= hasNestedArgs(va.objects); | |
1496 } | |
1497 } | |
1498 return nested; | |
1499 } | |
1500 | |
1501 /**************************************** | |
1502 * This instance needs an identifier for name mangling purposes. | |
1503 * Create one by taking the template declaration name and adding | |
1504 * the type signature for it. | |
1505 */ | |
1506 Identifier genIdent() | |
1507 { | |
1508 scope OutBuffer buf = new OutBuffer(); | |
1509 | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1510 //printf("TemplateInstance.genIdent('%s')\n", tempdecl.ident.toChars()); |
96 | 1511 string id = tempdecl.ident.toChars(); |
0 | 1512 buf.printf("__T%d%s", id.length, id); ///! |
96 | 1513 Objects args = tiargs; |
0 | 1514 for (int i = 0; i < args.dim; i++) |
1515 { | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
110
diff
changeset
|
1516 Object o = args[i]; |
0 | 1517 Type ta = isType(o); |
1518 Expression ea = isExpression(o); | |
1519 Dsymbol sa = isDsymbol(o); | |
1520 Tuple va = isTuple(o); | |
1521 //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va); | |
1522 if (ta) | |
1523 { | |
1524 buf.writeByte('T'); | |
1525 if (ta.deco) | |
1526 buf.writestring(ta.deco); | |
1527 else | |
1528 { | |
1529 debug writef("ta = %d, %s\n", ta.ty, ta.toChars()); | |
1530 assert(global.errors); | |
1531 } | |
1532 } | |
1533 else if (ea) | |
1534 { | |
1535 Lea: | |
1536 long v; | |
1537 real r; | |
1538 | |
1539 ea = ea.optimize(WANTvalue | WANTinterpret); | |
1540 if (ea.op == TOKvar) | |
1541 { | |
1542 sa = (cast(VarExp)ea).var; | |
1543 ea = null; | |
1544 goto Lsa; | |
1545 } | |
1546 if (ea.op == TOKfunction) | |
1547 { | |
1548 sa = (cast(FuncExp)ea).fd; | |
1549 ea = null; | |
1550 goto Lsa; | |
1551 } | |
1552 buf.writeByte('V'); | |
1553 if (ea.op == TOKtuple) | |
1554 { | |
1555 ea.error("tuple is not a valid template value argument"); | |
1556 continue; | |
1557 } | |
1558 static if (true) { | |
1559 /* Use deco that matches what it would be for a function parameter | |
1560 */ | |
1561 buf.writestring(ea.type.deco); | |
1562 } else { | |
1563 // Use type of parameter, not type of argument | |
1564 TemplateParameter tp = cast(TemplateParameter)tempdecl.parameters.data[i]; | |
1565 assert(tp); | |
1566 TemplateValueParameter tvp = tp.isTemplateValueParameter(); | |
1567 assert(tvp); | |
1568 buf.writestring(tvp.valType.deco); | |
1569 } | |
1570 ea.toMangleBuffer(buf); | |
1571 } | |
1572 else if (sa) | |
1573 { | |
1574 Lsa: | |
1575 buf.writeByte('S'); | |
1576 Declaration d = sa.isDeclaration(); | |
1577 if (d && (!d.type || !d.type.deco)) | |
1578 { | |
1579 error("forward reference of %s", d.toChars()); | |
1580 continue; | |
1581 } | |
1582 static if (false) { | |
1583 VarDeclaration v = sa.isVarDeclaration(); | |
1584 if (v && v.storage_class & STCmanifest) | |
1585 { | |
1586 ExpInitializer ei = v.init.isExpInitializer(); | |
1587 if (ei) | |
1588 { | |
1589 ea = ei.exp; | |
1590 goto Lea; | |
1591 } | |
1592 } | |
1593 } | |
1594 string p = sa.mangle(); | |
62 | 1595 ///buf.printf("%zu%s", p.length, p); |
1596 buf.printf("%su%s", p.length, p); | |
0 | 1597 } |
1598 else if (va) | |
1599 { | |
1600 assert(i + 1 == args.dim); // must be last one | |
1601 args = va.objects; | |
1602 i = -1; | |
1603 } | |
1604 else | |
1605 assert(0); | |
1606 } | |
1607 buf.writeByte('Z'); | |
1608 id = buf.toChars(); | |
1609 buf.data = null; | |
1610 //printf("\tgenIdent = %s\n", id); | |
1611 return new Identifier(id, TOKidentifier); | |
1612 } | |
1613 | |
72 | 1614 override TemplateInstance isTemplateInstance() { return this; } |
0 | 1615 |
72 | 1616 override AliasDeclaration isAliasDeclaration() |
0 | 1617 { |
1618 assert(false); | |
1619 } | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1620 } |