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