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