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