Mercurial > projects > ddmd
annotate dmd/TemplateDeclaration.d @ 49:0aa7d1437ada
AttribDeclaration.oneMember
Lexer.decodeUTF
WithStatement.ctor
StructDeclaration.syntaxCopy
CtorDeclaration.syntaxCopy
ConditionalStatement.syntaxCopy
ProtDeclaration.syntaxCopy
ArrayScopeSymbol.this
TemplateDeclaration.toChars
author | korDen |
---|---|
date | Sat, 21 Aug 2010 07:53:20 +0400 |
parents | d42cd5917df4 |
children | adf6f7f216ea |
rev | line source |
---|---|
0 | 1 module dmd.TemplateDeclaration; |
2 | |
3 import dmd.Loc; | |
4 import dmd.ScopeDsymbol; | |
5 import dmd.ArrayTypes; | |
6 import dmd.Dsymbol; | |
7 import dmd.STC; | |
8 import dmd.TemplateThisParameter; | |
9 import dmd.Global; | |
10 import dmd.Array; | |
11 import dmd.Identifier; | |
12 import dmd.TypeArray; | |
13 import dmd.Expression; | |
14 import dmd.Scope; | |
15 import dmd.TypeIdentifier; | |
16 import dmd.TypeDelegate; | |
17 import dmd.IntegerExp; | |
18 import dmd.TypeSArray; | |
19 import dmd.StringExp; | |
20 import dmd.TOK; | |
21 import dmd.Argument; | |
22 import dmd.CtorDeclaration; | |
23 import dmd.TypeFunction; | |
24 import dmd.TY; | |
25 import dmd.OutBuffer; | |
26 import dmd.Declaration; | |
27 import dmd.HdrGenState; | |
28 import dmd.TemplateInstance; | |
29 import dmd.WANT; | |
30 import dmd.FuncDeclaration; | |
31 import dmd.TemplateTupleParameter; | |
32 import dmd.MATCH; | |
33 import dmd.Type; | |
34 import dmd.Tuple; | |
35 import dmd.TupleDeclaration; | |
36 import dmd.Initializer; | |
37 import dmd.ExpInitializer; | |
38 import dmd.TemplateValueParameter; | |
39 import dmd.AliasDeclaration; | |
40 import dmd.VarDeclaration; | |
41 import dmd.TemplateParameter; | |
42 import dmd.TemplateTypeParameter; | |
43 | |
44 import dmd.expression.Util; | |
45 | |
46 import std.stdio; | |
47 | |
48 /************************************** | |
49 * Determine if TemplateDeclaration is variadic. | |
50 */ | |
51 | |
52 TemplateTupleParameter isVariadic(TemplateParameters parameters) | |
53 { | |
54 size_t dim = parameters.dim; | |
55 TemplateTupleParameter tp = null; | |
56 | |
57 if (dim) | |
58 tp = (cast(TemplateParameter)parameters.data[dim - 1]).isTemplateTupleParameter(); | |
59 | |
60 return tp; | |
61 } | |
62 | |
63 void ObjectToCBuffer(OutBuffer buf, HdrGenState* hgs, Object oarg) | |
64 { | |
65 //printf("ObjectToCBuffer()\n"); | |
66 Type t = isType(oarg); | |
67 Expression e = isExpression(oarg); | |
68 Dsymbol s = isDsymbol(oarg); | |
69 Tuple v = isTuple(oarg); | |
70 if (t) | |
71 { | |
72 //printf("\tt: %s ty = %d\n", t.toChars(), t.ty); | |
73 t.toCBuffer(buf, null, hgs); | |
74 } | |
75 else if (e) | |
76 e.toCBuffer(buf, hgs); | |
77 else if (s) | |
78 { | |
79 string p = s.ident ? s.ident.toChars() : s.toChars(); | |
80 buf.writestring(p); | |
81 } | |
82 else if (v) | |
83 { | |
84 Objects args = v.objects; | |
85 for (size_t i = 0; i < args.dim; i++) | |
86 { | |
87 if (i) | |
88 buf.writeByte(','); | |
89 Object o = cast(Object)args.data[i]; | |
90 ObjectToCBuffer(buf, hgs, o); | |
91 } | |
92 } | |
93 else if (!oarg) | |
94 { | |
95 buf.writestring("null"); | |
96 } | |
97 else | |
98 { | |
99 debug writef("bad Object = %p\n", oarg); | |
100 assert(0); | |
101 } | |
102 } | |
103 | |
104 class TemplateDeclaration : ScopeDsymbol | |
105 { | |
106 TemplateParameters parameters; // array of TemplateParameter's | |
107 | |
108 TemplateParameters origParameters; // originals for Ddoc | |
109 Expression constraint; | |
110 Array instances; // array of TemplateInstance's | |
111 | |
112 TemplateDeclaration overnext; // next overloaded TemplateDeclaration | |
113 TemplateDeclaration overroot; // first in overnext list | |
114 | |
115 int semanticRun; // 1 semantic() run | |
116 | |
117 Dsymbol onemember; // if !=NULL then one member of this template | |
118 | |
119 int literal; // this template declaration is a literal | |
120 | |
121 this(Loc loc, Identifier id, TemplateParameters parameters, Expression constraint, Array decldefs) | |
122 { | |
123 super(id); | |
124 | |
125 version (LOG) { | |
126 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id.toChars()); | |
127 } | |
128 static if (false) { | |
129 if (parameters) | |
130 for (int i = 0; i < parameters.dim; i++) | |
131 { | |
132 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
133 //printf("\tparameter[%d] = %p\n", i, tp); | |
134 TemplateTypeParameter ttp = tp.isTemplateTypeParameter(); | |
135 | |
136 if (ttp) | |
137 { | |
138 printf("\tparameter[%d] = %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : ""); | |
139 } | |
140 } | |
141 } | |
142 | |
143 this.loc = loc; | |
144 this.parameters = parameters; | |
145 this.origParameters = parameters; | |
146 this.constraint = constraint; | |
147 this.members = decldefs; | |
148 | |
149 instances = new Array(); | |
150 } | |
151 | |
152 Dsymbol syntaxCopy(Dsymbol) | |
153 { | |
154 assert(false); | |
155 } | |
156 | |
157 void semantic(Scope sc) | |
158 { | |
159 version (LOG) { | |
160 printf("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars()); | |
161 } | |
162 if (semanticRun) | |
163 return; // semantic() already run | |
164 semanticRun = 1; | |
165 | |
166 if (sc.func) | |
167 { | |
168 version (DMDV1) { | |
169 error("cannot declare template at function scope %s", sc.func.toChars()); | |
170 } | |
171 } | |
172 | |
173 if (/*global.params.useArrayBounds &&*/ sc.module_) | |
174 { | |
175 // Generate this function as it may be used | |
176 // when template is instantiated in other modules | |
177 sc.module_.toModuleArray(); | |
178 } | |
179 | |
180 if (/*global.params.useAssert &&*/ sc.module_) | |
181 { | |
182 // Generate this function as it may be used | |
183 // when template is instantiated in other modules | |
184 sc.module_.toModuleAssert(); | |
185 } | |
186 | |
187 /* Remember Scope for later instantiations, but make | |
188 * a copy since attributes can change. | |
189 */ | |
190 this.scope_ = new Scope(sc); /// A light copy | |
191 this.scope_.setNoFree(); | |
192 | |
193 // Set up scope for parameters | |
194 ScopeDsymbol paramsym = new ScopeDsymbol(); | |
195 paramsym.parent = sc.parent; | |
196 Scope paramscope = sc.push(paramsym); | |
197 paramscope.parameterSpecialization = 1; | |
198 paramscope.stc = STCundefined; | |
199 | |
200 if (!parent) | |
201 parent = sc.parent; | |
202 | |
203 if (global.params.doDocComments) | |
204 { | |
205 origParameters = new TemplateParameters(); | |
206 origParameters.setDim(parameters.dim); | |
207 for (int i = 0; i < parameters.dim; i++) | |
208 { | |
209 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
210 origParameters.data[i] = cast(void*)tp.syntaxCopy(); | |
211 } | |
212 } | |
213 | |
214 for (int i = 0; i < parameters.dim; i++) | |
215 { | |
216 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
217 tp.declareParameter(paramscope); | |
218 } | |
219 | |
220 for (int i = 0; i < parameters.dim; i++) | |
221 { | |
222 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
223 | |
224 tp.semantic(paramscope); | |
225 if (i + 1 != parameters.dim && tp.isTemplateTupleParameter()) | |
226 error("template tuple parameter must be last one"); | |
227 } | |
228 | |
229 paramscope.pop(); | |
230 | |
231 if (members) | |
232 { | |
233 Dsymbol s; | |
234 if (Dsymbol.oneMembers(members, &s)) | |
235 { | |
236 if (s && s.ident && s.ident.equals(ident)) | |
237 { | |
238 onemember = s; | |
239 s.parent = this; | |
240 } | |
241 } | |
242 } | |
243 | |
244 /* BUG: should check: | |
245 * o no virtual functions or non-static data members of classes | |
246 */ | |
247 } | |
248 | |
8
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
249 /********************************** |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
250 * Overload existing TemplateDeclaration 'this' with the new one 's'. |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
251 * Return !=0 if successful; i.e. no conflict. |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
252 */ |
0 | 253 bool overloadInsert(Dsymbol s) |
254 { | |
8
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
255 TemplateDeclaration f; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
256 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
257 version (LOG) { |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
258 printf("TemplateDeclaration.overloadInsert('%s')\n", s.toChars()); |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
259 } |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
260 f = s.isTemplateDeclaration(); |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
261 if (!f) |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
262 return false; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
263 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
264 for (TemplateDeclaration f2 = this; f2; f2 = f2.overnext) |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
265 { |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
266 static if (false) { |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
267 // Conflict if TemplateParameter's match |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
268 // Will get caught anyway later with TemplateInstance, but |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
269 // should check it now. |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
270 if (f.parameters.dim != f2.parameters.dim) |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
271 goto Lcontinue; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
272 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
273 for (int i = 0; i < f.parameters.dim; i++) |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
274 { |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
275 TemplateParameter p1 = cast(TemplateParameter)f.parameters.data[i]; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
276 TemplateParameter p2 = cast(TemplateParameter)f2.parameters.data[i]; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
277 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
278 if (!p1.overloadMatch(p2)) |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
279 goto Lcontinue; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
280 } |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
281 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
282 version (LOG) { |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
283 printf("\tfalse: conflict\n"); |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
284 } |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
285 return false; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
286 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
287 Lcontinue: |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
288 ; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
289 } |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
290 } |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
291 |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
292 f.overroot = this; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
293 ///*pf = f; |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
294 version (LOG) { |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
295 printf("\ttrue: no conflict\n"); |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
296 } |
d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
dkoroskin <>
parents:
0
diff
changeset
|
297 return true; |
0 | 298 } |
299 | |
300 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
301 { | |
302 assert(false); | |
303 } | |
304 | |
305 string kind() | |
306 { | |
307 assert(false); | |
308 } | |
309 | |
310 string toChars() | |
311 { | |
49 | 312 OutBuffer buf = new OutBuffer(); |
313 HdrGenState hgs; | |
314 | |
315 /// memset(&hgs, 0, hgs.sizeof); | |
316 buf.writestring(ident.toChars()); | |
317 buf.writeByte('('); | |
318 for (int i = 0; i < parameters.dim; i++) | |
319 { | |
320 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
321 if (i) | |
322 buf.writeByte(','); | |
323 tp.toCBuffer(buf, &hgs); | |
324 } | |
325 buf.writeByte(')'); | |
326 version (DMDV2) { | |
327 if (constraint) | |
328 { | |
329 buf.writestring(" if ("); | |
330 constraint.toCBuffer(buf, &hgs); | |
331 buf.writeByte(')'); | |
332 } | |
333 } | |
334 buf.writeByte(0); | |
335 return buf.extractString(); | |
0 | 336 } |
337 | |
338 void emitComment(Scope sc) | |
339 { | |
340 assert(false); | |
341 } | |
342 | |
343 // void toDocBuffer(OutBuffer *buf); | |
344 | |
345 /*************************************** | |
346 * Given that ti is an instance of this TemplateDeclaration, | |
347 * deduce the types of the parameters to this, and store | |
348 * those deduced types in dedtypes[]. | |
349 * Input: | |
350 * flag 1: don't do semantic() because of dummy types | |
351 * 2: don't change types in matchArg() | |
352 * Output: | |
353 * dedtypes deduced arguments | |
354 * Return match level. | |
355 */ | |
356 MATCH matchWithInstance(TemplateInstance ti, Objects dedtypes, int flag) | |
357 { | |
358 MATCH m; | |
359 int dedtypes_dim = dedtypes.dim; | |
360 | |
361 version (LOGM) { | |
362 printf("\n+TemplateDeclaration.matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti.toChars(), flag); | |
363 } | |
364 | |
365 static if (false) { | |
366 printf("dedtypes.dim = %d, parameters.dim = %d\n", dedtypes_dim, parameters.dim); | |
367 if (ti.tiargs.dim) | |
368 printf("ti.tiargs.dim = %d, [0] = %p\n", ti.tiargs.dim, ti.tiargs.data[0]); | |
369 } | |
370 dedtypes.zero(); | |
371 | |
372 int parameters_dim = parameters.dim; | |
373 int variadic = isVariadic() !is null; | |
374 | |
375 // If more arguments than parameters, no match | |
376 if (ti.tiargs.dim > parameters_dim && !variadic) | |
377 { | |
378 version (LOGM) { | |
379 printf(" no match: more arguments than parameters\n"); | |
380 } | |
381 return MATCHnomatch; | |
382 } | |
383 | |
384 assert(dedtypes_dim == parameters_dim); | |
385 assert(dedtypes_dim >= ti.tiargs.dim || variadic); | |
386 | |
387 // Set up scope for parameters | |
388 assert(cast(size_t)cast(void*)scope_ > 0x10000); | |
389 ScopeDsymbol paramsym = new ScopeDsymbol(); | |
390 paramsym.parent = scope_.parent; | |
391 Scope paramscope = scope_.push(paramsym); | |
392 paramscope.stc = STCundefined; | |
393 | |
394 // Attempt type deduction | |
395 m = MATCHexact; | |
396 for (int i = 0; i < dedtypes_dim; i++) | |
397 { | |
398 MATCH m2; | |
399 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
400 Declaration sparam; | |
401 | |
402 //printf("\targument [%d]\n", i); | |
403 version (LOGM) { | |
404 //printf("\targument [%d] is %s\n", i, oarg ? oarg.toChars() : "null"); | |
405 TemplateTypeParameter *ttp = tp.isTemplateTypeParameter(); | |
406 if (ttp) | |
407 printf("\tparameter[%d] is %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : ""); | |
408 } | |
409 | |
410 version (DMDV1) { | |
411 m2 = tp.matchArg(paramscope, ti.tiargs, i, parameters, dedtypes, &sparam); | |
412 } else { | |
413 m2 = tp.matchArg(paramscope, ti.tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0); | |
414 } | |
415 //printf("\tm2 = %d\n", m2); | |
416 | |
417 if (m2 == MATCHnomatch) | |
418 { | |
419 static if (false) { | |
420 printf("\tmatchArg() for parameter %i failed\n", i); | |
421 } | |
422 goto Lnomatch; | |
423 } | |
424 | |
425 if (m2 < m) | |
426 m = m2; | |
427 | |
428 if (!flag) | |
429 sparam.semantic(paramscope); | |
430 if (!paramscope.insert(sparam)) | |
431 goto Lnomatch; | |
432 } | |
433 | |
434 if (!flag) | |
435 { | |
436 /* Any parameter left without a type gets the type of | |
437 * its corresponding arg | |
438 */ | |
439 for (int i = 0; i < dedtypes_dim; i++) | |
440 { | |
441 if (!dedtypes.data[i]) | |
442 { | |
443 assert(i < ti.tiargs.dim); | |
444 dedtypes.data[i] = ti.tiargs.data[i]; | |
445 } | |
446 } | |
447 } | |
448 | |
449 version (DMDV2) { | |
450 if (m && constraint && !(flag & 1)) | |
451 { /* Check to see if constraint is satisfied. | |
452 */ | |
453 Expression e = constraint.syntaxCopy(); | |
454 paramscope.flags |= SCOPE.SCOPEstaticif; | |
455 e = e.semantic(paramscope); | |
456 e = e.optimize(WANTvalue | WANTinterpret); | |
457 if (e.isBool(true)) { | |
458 ; | |
459 } else if (e.isBool(false)) | |
460 goto Lnomatch; | |
461 else | |
462 { | |
463 e.error("constraint %s is not constant or does not evaluate to a bool", e.toChars()); | |
464 } | |
465 } | |
466 } | |
467 | |
468 version (LOGM) { | |
469 // Print out the results | |
470 printf("--------------------------\n"); | |
471 printf("template %s\n", toChars()); | |
472 printf("instance %s\n", ti.toChars()); | |
473 if (m) | |
474 { | |
475 for (int i = 0; i < dedtypes_dim; i++) | |
476 { | |
477 TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; | |
478 Object oarg; | |
479 | |
480 printf(" [%d]", i); | |
481 | |
482 if (i < ti.tiargs.dim) | |
483 oarg = cast(Object)ti.tiargs.data[i]; | |
484 else | |
485 oarg = null; | |
486 tp.print(oarg, cast(Object)dedtypes.data[i]); | |
487 } | |
488 } | |
489 else | |
490 goto Lnomatch; | |
491 } | |
492 | |
493 version (LOGM) { | |
494 printf(" match = %d\n", m); | |
495 } | |
496 goto Lret; | |
497 | |
498 Lnomatch: | |
499 version (LOGM) { | |
500 printf(" no match\n"); | |
501 } | |
502 m = MATCHnomatch; | |
503 | |
504 Lret: | |
505 paramscope.pop(); | |
506 version (LOGM) { | |
507 printf("-TemplateDeclaration.matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); | |
508 } | |
509 return m; | |
510 } | |
511 | |
512 MATCH leastAsSpecialized(TemplateDeclaration td2) | |
513 { | |
514 assert(false); | |
515 } | |
516 | |
517 /************************************************* | |
518 * Match function arguments against a specific template function. | |
519 * Input: | |
520 * loc instantiation location | |
521 * targsi Expression/Type initial list of template arguments | |
522 * ethis 'this' argument if !null | |
523 * fargs arguments to function | |
524 * Output: | |
525 * dedargs Expression/Type deduced template arguments | |
526 * Returns: | |
527 * match level | |
528 */ | |
529 MATCH deduceFunctionTemplateMatch(Loc loc, Objects targsi, Expression ethis, Expressions fargs, Objects dedargs) | |
530 { | |
531 size_t nfparams; | |
532 size_t nfargs; | |
533 size_t nargsi; // array size of targsi | |
534 int fptupindex = -1; | |
535 int tuple_dim = 0; | |
536 MATCH match = MATCHexact; | |
537 FuncDeclaration fd = onemember.toAlias().isFuncDeclaration(); | |
538 Arguments fparameters; // function parameter list | |
539 int fvarargs; // function varargs | |
540 scope Objects dedtypes = new Objects(); // for T:T*, the dedargs is the T*, dedtypes is the T | |
541 | |
542 static if (false) { | |
543 printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars()); | |
544 for (i = 0; i < fargs.dim; i++) | |
545 { | |
546 Expression e = cast(Expression)fargs.data[i]; | |
547 printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars()); | |
548 } | |
549 printf("fd = %s\n", fd.toChars()); | |
550 printf("fd.type = %p\n", fd.type); | |
551 } | |
552 | |
553 assert(cast(size_t)cast(void*)scope_ > 0x10000); | |
554 | |
555 dedargs.setDim(parameters.dim); | |
556 dedargs.zero(); | |
557 | |
558 dedtypes.setDim(parameters.dim); | |
559 dedtypes.zero(); | |
560 | |
561 // Set up scope for parameters | |
562 ScopeDsymbol paramsym = new ScopeDsymbol(); | |
563 paramsym.parent = scope_.parent; | |
564 Scope paramscope = scope_.push(paramsym); | |
565 | |
566 TemplateTupleParameter tp = isVariadic(); | |
567 | |
568 static if (false) { | |
569 for (i = 0; i < dedargs.dim; i++) | |
570 { | |
571 printf("\tdedarg[%d] = ", i); | |
572 Object oarg = cast(Object)dedargs.data[i]; | |
573 if (oarg) printf("%s", oarg.toChars()); | |
574 printf("\n"); | |
575 } | |
576 } | |
577 | |
578 | |
579 nargsi = 0; | |
580 if (targsi) | |
581 { // Set initial template arguments | |
582 size_t n; | |
583 | |
584 nargsi = targsi.dim; | |
585 n = parameters.dim; | |
586 if (tp) | |
587 n--; | |
588 if (nargsi > n) | |
589 { | |
590 if (!tp) | |
591 goto Lnomatch; | |
592 | |
593 /* The extra initial template arguments | |
594 * now form the tuple argument. | |
595 */ | |
596 Tuple t = new Tuple(); | |
597 assert(parameters.dim); | |
598 dedargs.data[parameters.dim - 1] = cast(void*)t; | |
599 | |
600 tuple_dim = nargsi - n; | |
601 t.objects.setDim(tuple_dim); | |
602 for (size_t i = 0; i < tuple_dim; i++) | |
603 { | |
604 t.objects.data[i] = cast(void*)targsi.data[n + i]; | |
605 } | |
606 declareParameter(paramscope, tp, t); | |
607 } | |
608 else | |
609 n = nargsi; | |
610 | |
611 memcpy(dedargs.data, targsi.data, n * (*dedargs.data).sizeof); | |
612 | |
613 for (size_t i = 0; i < n; i++) | |
614 { | |
615 assert(i < parameters.dim); | |
616 TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; | |
617 MATCH m; | |
618 Declaration sparam = null; | |
619 | |
620 m = tp2.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam); | |
621 //printf("\tdeduceType m = %d\n", m); | |
622 if (m == MATCHnomatch) | |
623 goto Lnomatch; | |
624 if (m < match) | |
625 match = m; | |
626 | |
627 sparam.semantic(paramscope); | |
628 if (!paramscope.insert(sparam)) | |
629 goto Lnomatch; | |
630 } | |
631 } | |
632 static if (false) { | |
633 for (i = 0; i < dedargs.dim; i++) | |
634 { | |
635 printf("\tdedarg[%d] = ", i); | |
636 Object oarg = cast(Object)dedargs.data[i]; | |
637 if (oarg) printf("%s", oarg.toChars()); | |
638 printf("\n"); | |
639 } | |
640 } | |
641 | |
642 if (fd.type) | |
643 { | |
644 assert(fd.type.ty == Tfunction); | |
645 TypeFunction fdtype = cast(TypeFunction)fd.type; | |
646 fparameters = fdtype.parameters; | |
647 fvarargs = fdtype.varargs; | |
648 } | |
649 else | |
650 { | |
651 CtorDeclaration fctor = fd.isCtorDeclaration(); | |
652 assert(fctor); | |
653 fparameters = fctor.arguments; | |
654 fvarargs = fctor.varargs; | |
655 } | |
656 | |
657 nfparams = Argument.dim(fparameters); // number of function parameters | |
658 nfargs = fargs ? fargs.dim : 0; // number of function arguments | |
659 | |
660 /* Check for match of function arguments with variadic template | |
661 * parameter, such as: | |
662 * | |
663 * template Foo(T, A...) { void Foo(T t, A a); } | |
664 * void main() { Foo(1,2,3); } | |
665 */ | |
666 if (tp) // if variadic | |
667 { | |
668 if (nfparams == 0) // if no function parameters | |
669 { | |
670 Tuple t = new Tuple(); | |
671 //printf("t = %p\n", t); | |
672 dedargs.data[parameters.dim - 1] = cast(void*)t; | |
673 declareParameter(paramscope, tp, t); | |
674 goto L2; | |
675 } | |
676 else if (nfargs < nfparams - 1) | |
677 goto L1; | |
678 else | |
679 { | |
680 /* Figure out which of the function parameters matches | |
681 * the tuple template parameter. Do this by matching | |
682 * type identifiers. | |
683 * Set the index of this function parameter to fptupindex. | |
684 */ | |
685 for (fptupindex = 0; fptupindex < nfparams; fptupindex++) | |
686 { | |
687 Argument fparam = cast(Argument)fparameters.data[fptupindex]; | |
688 if (fparam.type.ty != Tident) | |
689 continue; | |
690 TypeIdentifier tid = cast(TypeIdentifier)fparam.type; | |
691 if (!tp.ident.equals(tid.ident) || tid.idents.dim) | |
692 continue; | |
693 | |
694 if (fvarargs) // variadic function doesn't | |
695 goto Lnomatch; // go with variadic template | |
696 | |
697 /* The types of the function arguments | |
698 * now form the tuple argument. | |
699 */ | |
700 Tuple t = new Tuple(); | |
701 dedargs.data[parameters.dim - 1] = cast(void*)t; | |
702 | |
703 tuple_dim = nfargs - (nfparams - 1); | |
704 t.objects.setDim(tuple_dim); | |
705 for (size_t i = 0; i < tuple_dim; i++) | |
706 { | |
707 Expression farg = cast(Expression)fargs.data[fptupindex + i]; | |
708 t.objects.data[i] = cast(void*)farg.type; | |
709 } | |
710 declareParameter(paramscope, tp, t); | |
711 goto L2; | |
712 } | |
713 fptupindex = -1; | |
714 } | |
715 } | |
716 | |
717 L1: | |
718 if (nfparams == nfargs) { | |
719 ; | |
720 } else if (nfargs > nfparams) { | |
721 if (fvarargs == 0) | |
722 goto Lnomatch; // too many args, no match | |
723 match = MATCHconvert; // match ... with a conversion | |
724 } | |
725 | |
726 L2: | |
727 version (DMDV2) { | |
728 // Match 'ethis' to any TemplateThisParameter's | |
729 if (ethis) | |
730 { | |
731 for (size_t i = 0; i < parameters.dim; i++) | |
732 { | |
733 TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; | |
734 TemplateThisParameter ttp = tp2.isTemplateThisParameter(); | |
735 if (ttp) | |
736 { | |
737 MATCH m; | |
738 | |
739 Type t = new TypeIdentifier(Loc(0), ttp.ident); | |
740 m = ethis.type.deduceType(paramscope, t, parameters, dedtypes); | |
741 if (!m) | |
742 goto Lnomatch; | |
743 if (m < match) | |
744 match = m; // pick worst match | |
745 } | |
746 } | |
747 } | |
748 } | |
749 | |
750 // Loop through the function parameters | |
751 for (size_t i = 0; i < nfparams; i++) | |
752 { | |
753 /* Skip over function parameters which wound up | |
754 * as part of a template tuple parameter. | |
755 */ | |
756 if (i == fptupindex) | |
757 { | |
758 if (fptupindex == nfparams - 1) | |
759 break; | |
760 i += tuple_dim - 1; | |
761 continue; | |
762 } | |
763 | |
764 Argument fparam = Argument.getNth(fparameters, i); | |
765 | |
766 if (i >= nfargs) // if not enough arguments | |
767 { | |
768 if (fparam.defaultArg) | |
769 { | |
770 /* Default arguments do not participate in template argument | |
771 * deduction. | |
772 */ | |
773 goto Lmatch; | |
774 } | |
775 } | |
776 else | |
777 { | |
778 Expression farg = cast(Expression)fargs.data[i]; | |
779 static if (false) { | |
780 printf("\tfarg.type = %s\n", farg.type.toChars()); | |
781 printf("\tfparam.type = %s\n", fparam.type.toChars()); | |
782 } | |
783 Type argtype = farg.type; | |
784 | |
785 version (DMDV2) { | |
786 /* Allow string literals which are type [] to match with [dim] | |
787 */ | |
788 if (farg.op == TOKstring) | |
789 { | |
790 StringExp se = cast(StringExp)farg; | |
791 if (!se.committed && argtype.ty == Tarray && | |
792 fparam.type.toBasetype().ty == Tsarray) | |
793 { | |
794 argtype = new TypeSArray(argtype.nextOf(), new IntegerExp(se.loc, se.len, Type.tindex)); | |
795 argtype = argtype.semantic(se.loc, null); | |
796 argtype = argtype.invariantOf(); | |
797 } | |
798 } | |
799 } | |
800 | |
801 MATCH m; | |
802 m = argtype.deduceType(paramscope, fparam.type, parameters, dedtypes); | |
803 //printf("\tdeduceType m = %d\n", m); | |
804 | |
805 /* If no match, see if there's a conversion to a delegate | |
806 */ | |
807 if (!m && fparam.type.toBasetype().ty == Tdelegate) | |
808 { | |
809 TypeDelegate td = cast(TypeDelegate)fparam.type.toBasetype(); | |
810 TypeFunction tf = cast(TypeFunction)td.next; | |
811 | |
812 if (!tf.varargs && Argument.dim(tf.parameters) == 0) | |
813 { | |
814 m = farg.type.deduceType(paramscope, tf.next, parameters, dedtypes); | |
815 if (!m && tf.next.toBasetype().ty == Tvoid) | |
816 m = MATCHconvert; | |
817 } | |
818 //printf("\tm2 = %d\n", m); | |
819 } | |
820 | |
821 if (m) | |
822 { | |
823 if (m < match) | |
824 match = m; // pick worst match | |
825 continue; | |
826 } | |
827 } | |
828 | |
829 /* The following code for variadic arguments closely | |
830 * matches TypeFunction.callMatch() | |
831 */ | |
832 if (!(fvarargs == 2 && i + 1 == nfparams)) | |
833 goto Lnomatch; | |
834 | |
835 /* Check for match with function parameter T... | |
836 */ | |
837 Type tb = fparam.type.toBasetype(); | |
838 switch (tb.ty) | |
839 { | |
840 // Perhaps we can do better with this, see TypeFunction.callMatch() | |
841 case Tsarray: | |
842 { | |
843 TypeSArray tsa = cast(TypeSArray)tb; | |
844 ulong sz = tsa.dim.toInteger(); | |
845 if (sz != nfargs - i) | |
846 goto Lnomatch; | |
847 } | |
848 case Tarray: | |
849 { | |
850 TypeArray ta = cast(TypeArray)tb; | |
851 for (; i < nfargs; i++) | |
852 { | |
853 Expression arg = cast(Expression)fargs.data[i]; | |
854 assert(arg); | |
855 MATCH m; | |
856 /* If lazy array of delegates, | |
857 * convert arg(s) to delegate(s) | |
858 */ | |
859 Type tret = fparam.isLazyArray(); | |
860 if (tret) | |
861 { | |
862 if (ta.next.equals(arg.type)) | |
863 { | |
864 m = MATCHexact; | |
865 } | |
866 else | |
867 { | |
868 m = arg.implicitConvTo(tret); | |
869 if (m == MATCHnomatch) | |
870 { | |
871 if (tret.toBasetype().ty == Tvoid) | |
872 m = MATCHconvert; | |
873 } | |
874 } | |
875 } | |
876 else | |
877 { | |
878 m = arg.type.deduceType(paramscope, ta.next, parameters, dedtypes); | |
879 //m = arg.implicitConvTo(ta.next); | |
880 } | |
881 if (m == MATCHnomatch) | |
882 goto Lnomatch; | |
883 if (m < match) | |
884 match = m; | |
885 } | |
886 goto Lmatch; | |
887 } | |
888 case Tclass: | |
889 case Tident: | |
890 goto Lmatch; | |
891 | |
892 default: | |
893 goto Lnomatch; | |
894 } | |
895 } | |
896 | |
897 Lmatch: | |
898 | |
899 /* Fill in any missing arguments with their defaults. | |
900 */ | |
901 for (size_t i = nargsi; i < dedargs.dim; i++) | |
902 { | |
903 TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; | |
904 //printf("tp2[%d] = %s\n", i, tp2.ident.toChars()); | |
905 /* For T:T*, the dedargs is the T*, dedtypes is the T | |
906 * But for function templates, we really need them to match | |
907 */ | |
908 Object oarg = cast(Object)dedargs.data[i]; | |
909 Object oded = cast(Object)dedtypes.data[i]; | |
910 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded); | |
911 //if (oarg) printf("oarg: %s\n", oarg.toChars()); | |
912 //if (oded) printf("oded: %s\n", oded.toChars()); | |
913 if (!oarg) | |
914 { | |
915 if (oded) | |
916 { | |
917 if (tp2.specialization()) | |
918 { | |
919 /* The specialization can work as long as afterwards | |
920 * the oded == oarg | |
921 */ | |
922 Declaration sparam; | |
923 dedargs.data[i] = cast(void*)oded; | |
924 MATCH m2 = tp2.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam, 0); | |
925 //printf("m2 = %d\n", m2); | |
926 if (!m2) | |
927 goto Lnomatch; | |
928 if (m2 < match) | |
929 match = m2; // pick worst match | |
930 if (dedtypes.data[i] !is cast(void*)oded) | |
931 error("specialization not allowed for deduced parameter %s", tp2.ident.toChars()); | |
932 } | |
933 } | |
934 else | |
935 { | |
936 oded = tp2.defaultArg(loc, paramscope); | |
937 if (!oded) | |
938 goto Lnomatch; | |
939 } | |
940 declareParameter(paramscope, tp2, oded); | |
941 dedargs.data[i] = cast(void*)oded; | |
942 } | |
943 } | |
944 | |
945 version (DMDV2) { | |
946 if (constraint) | |
947 { /* Check to see if constraint is satisfied. | |
948 */ | |
949 Expression e = constraint.syntaxCopy(); | |
950 paramscope.flags |= SCOPE.SCOPEstaticif; | |
951 e = e.semantic(paramscope); | |
952 e = e.optimize(WANTvalue | WANTinterpret); | |
953 if (e.isBool(true)) { | |
954 ; | |
955 } else if (e.isBool(false)) | |
956 goto Lnomatch; | |
957 else | |
958 { | |
959 e.error("constraint %s is not constant or does not evaluate to a bool", e.toChars()); | |
960 } | |
961 } | |
962 } | |
963 | |
964 static if (false) { | |
965 for (i = 0; i < dedargs.dim; i++) | |
966 { | |
967 Type t = cast(Type)dedargs.data[i]; | |
968 printf("\tdedargs[%d] = %d, %s\n", i, t.dyncast(), t.toChars()); | |
969 } | |
970 } | |
971 | |
972 paramscope.pop(); | |
973 //printf("\tmatch %d\n", match); | |
974 return match; | |
975 | |
976 Lnomatch: | |
977 paramscope.pop(); | |
978 //printf("\tnomatch\n"); | |
979 return MATCHnomatch; | |
980 } | |
981 | |
982 /************************************************* | |
983 * Given function arguments, figure out which template function | |
984 * to expand, and return that function. | |
985 * If no match, give error message and return null. | |
986 * Input: | |
987 * sc instantiation scope | |
988 * loc instantiation location | |
989 * targsi initial list of template arguments | |
990 * ethis if !null, the 'this' pointer argument | |
991 * fargs arguments to function | |
992 * flags 1: do not issue error message on no match, just return null | |
993 */ | |
994 FuncDeclaration deduceFunctionTemplate(Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions fargs, int flags = 0) | |
995 { | |
996 MATCH m_best = MATCHnomatch; | |
997 TemplateDeclaration td_ambig = null; | |
998 TemplateDeclaration td_best = null; | |
999 Objects tdargs = new Objects(); | |
1000 TemplateInstance ti; | |
1001 FuncDeclaration fd; | |
1002 | |
1003 static if (false) { | |
1004 printf("TemplateDeclaration.deduceFunctionTemplate() %s\n", toChars()); | |
1005 printf(" targsi:\n"); | |
1006 if (targsi) | |
1007 { | |
1008 for (int i = 0; i < targsi.dim; i++) | |
1009 { | |
1010 Object arg = cast(Object)targsi.data[i]; | |
1011 printf("\t%s\n", arg.toChars()); | |
1012 } | |
1013 } | |
1014 printf(" fargs:\n"); | |
1015 for (int i = 0; i < fargs.dim; i++) | |
1016 { | |
1017 Expression arg = cast(Expression)fargs.data[i]; | |
1018 printf("\t%s %s\n", arg.type.toChars(), arg.toChars()); | |
1019 //printf("\tty = %d\n", arg.type.ty); | |
1020 } | |
1021 } | |
1022 | |
1023 for (TemplateDeclaration td = this; td; td = td.overnext) | |
1024 { | |
1025 if (!td.semanticRun) | |
1026 { | |
1027 error("forward reference to template %s", td.toChars()); | |
1028 goto Lerror; | |
1029 } | |
1030 if (!td.onemember || !td.onemember.toAlias().isFuncDeclaration()) | |
1031 { | |
1032 error("is not a function template"); | |
1033 goto Lerror; | |
1034 } | |
1035 | |
1036 MATCH m; | |
1037 scope Objects dedargs = new Objects(); | |
1038 | |
1039 m = td.deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, dedargs); | |
1040 //printf("deduceFunctionTemplateMatch = %d\n", m); | |
1041 if (!m) // if no match | |
1042 continue; | |
1043 | |
1044 if (m < m_best) | |
1045 goto Ltd_best; | |
1046 if (m > m_best) | |
1047 goto Ltd; | |
1048 | |
1049 { | |
1050 // Disambiguate by picking the most specialized TemplateDeclaration | |
1051 MATCH c1 = td.leastAsSpecialized(td_best); | |
1052 MATCH c2 = td_best.leastAsSpecialized(td); | |
1053 //printf("c1 = %d, c2 = %d\n", c1, c2); | |
1054 | |
1055 if (c1 > c2) | |
1056 goto Ltd; | |
1057 else if (c1 < c2) | |
1058 goto Ltd_best; | |
1059 else | |
1060 goto Lambig; | |
1061 } | |
1062 | |
1063 Lambig: // td_best and td are ambiguous | |
1064 td_ambig = td; | |
1065 continue; | |
1066 | |
1067 Ltd_best: // td_best is the best match so far | |
1068 td_ambig = null; | |
1069 continue; | |
1070 | |
1071 Ltd: // td is the new best match | |
1072 td_ambig = null; | |
1073 assert(cast(size_t)cast(void*)td.scope_ > 0x10000); | |
1074 td_best = td; | |
1075 m_best = m; | |
1076 tdargs.setDim(dedargs.dim); | |
1077 memcpy(tdargs.data, dedargs.data, tdargs.dim * (void*).sizeof); | |
1078 continue; | |
1079 } | |
1080 if (!td_best) | |
1081 { | |
1082 if (!(flags & 1)) | |
1083 error(loc, "does not match any function template declaration"); | |
1084 goto Lerror; | |
1085 } | |
1086 if (td_ambig) | |
1087 { | |
1088 error(loc, "matches more than one function template declaration:\n %s\nand:\n %s", | |
1089 td_best.toChars(), td_ambig.toChars()); | |
1090 } | |
1091 | |
1092 /* The best match is td_best with arguments tdargs. | |
1093 * Now instantiate the template. | |
1094 */ | |
1095 assert(cast(size_t)cast(void*)td_best.scope_ > 0x10000); | |
1096 ti = new TemplateInstance(loc, td_best, tdargs); | |
1097 ti.semantic(sc); | |
1098 fd = ti.toAlias().isFuncDeclaration(); | |
1099 if (!fd) | |
1100 goto Lerror; | |
1101 return fd; | |
1102 | |
1103 Lerror: | |
1104 /// version (DMDV2) { | |
1105 if (!(flags & 1)) | |
1106 /// } | |
1107 { | |
1108 HdrGenState hgs; | |
1109 | |
1110 scope OutBuffer bufa = new OutBuffer(); | |
1111 Objects args = targsi; | |
1112 if (args) | |
1113 { | |
1114 for (int i = 0; i < args.dim; i++) | |
1115 { | |
1116 if (i) | |
1117 bufa.writeByte(','); | |
1118 Object oarg = cast(Object)args.data[i]; | |
1119 ObjectToCBuffer(bufa, &hgs, oarg); | |
1120 } | |
1121 } | |
1122 | |
1123 scope OutBuffer buf = new OutBuffer(); | |
1124 argExpTypesToCBuffer(buf, fargs, &hgs); | |
1125 error(loc, "cannot deduce template function from argument types !(%s)(%s)", bufa.toChars(), buf.toChars()); | |
1126 } | |
1127 return null; | |
1128 } | |
1129 | |
1130 /************************************************** | |
1131 * Declare template parameter tp with value o, and install it in the scope sc. | |
1132 */ | |
1133 void declareParameter(Scope sc, TemplateParameter tp, Object o) | |
1134 { | |
1135 //printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o); | |
1136 | |
1137 Type targ = isType(o); | |
1138 Expression ea = isExpression(o); | |
1139 Dsymbol sa = isDsymbol(o); | |
1140 Tuple va = isTuple(o); | |
1141 | |
1142 Dsymbol s; | |
1143 | |
1144 // See if tp.ident already exists with a matching definition | |
1145 Dsymbol scopesym; | |
1146 s = sc.search(loc, tp.ident, &scopesym); | |
1147 if (s && scopesym == sc.scopesym) | |
1148 { | |
1149 TupleDeclaration td = s.isTupleDeclaration(); | |
1150 if (va && td) | |
1151 { | |
1152 Tuple tup = new Tuple(); | |
1153 assert(false); // < not implemented | |
1154 ///tup.objects = *td.objects; | |
1155 if (match(va, tup, this, sc)) | |
1156 { | |
1157 return; | |
1158 } | |
1159 } | |
1160 } | |
1161 | |
1162 if (targ) | |
1163 { | |
1164 //printf("type %s\n", targ.toChars()); | |
1165 s = new AliasDeclaration(Loc(0), tp.ident, targ); | |
1166 } | |
1167 else if (sa) | |
1168 { | |
1169 //printf("Alias %s %s;\n", sa.ident.toChars(), tp.ident.toChars()); | |
1170 s = new AliasDeclaration(Loc(0), tp.ident, sa); | |
1171 } | |
1172 else if (ea) | |
1173 { | |
1174 // tdtypes.data[i] always matches ea here | |
1175 Initializer init = new ExpInitializer(loc, ea); | |
1176 TemplateValueParameter tvp = tp.isTemplateValueParameter(); | |
1177 | |
1178 Type t = tvp ? tvp.valType : null; | |
1179 | |
1180 VarDeclaration v = new VarDeclaration(loc, t, tp.ident, init); | |
1181 v.storage_class = STCmanifest; | |
1182 s = v; | |
1183 } | |
1184 else if (va) | |
1185 { | |
1186 //printf("\ttuple\n"); | |
1187 s = new TupleDeclaration(loc, tp.ident, va.objects); | |
1188 } | |
1189 else | |
1190 { | |
1191 debug writefln(o.toString()); | |
1192 assert(0); | |
1193 } | |
1194 | |
1195 if (!sc.insert(s)) | |
1196 error("declaration %s is already defined", tp.ident.toChars()); | |
1197 | |
1198 s.semantic(sc); | |
1199 } | |
1200 | |
1201 TemplateDeclaration isTemplateDeclaration() { return this; } | |
1202 | |
1203 TemplateTupleParameter isVariadic() | |
1204 { | |
1205 return .isVariadic(parameters); | |
1206 } | |
1207 | |
1208 bool isOverloadable() | |
1209 { | |
1210 assert(false); | |
1211 } | |
1212 } |