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