Mercurial > projects > ddmd
annotate dmd/expression/Util.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | 60bb0fe4563e |
children | ea6325d0edd9 |
rev | line source |
---|---|
0 | 1 module dmd.expression.Util; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Expression; |
5 import dmd.Loc; | |
53 | 6 import dmd.RealExp; |
0 | 7 import dmd.Scope; |
8 import dmd.FuncExp; | |
9 import dmd.DelegateExp; | |
10 import dmd.LINK; | |
11 import dmd.NullExp; | |
12 import dmd.SymOffExp; | |
13 import dmd.ExpInitializer; | |
14 import dmd.Lexer; | |
15 import dmd.TypeSArray; | |
16 import dmd.TypeArray; | |
17 import dmd.VarDeclaration; | |
18 import dmd.VoidInitializer; | |
19 import dmd.DeclarationExp; | |
20 import dmd.VarExp; | |
21 import dmd.NewExp; | |
22 import dmd.STC; | |
23 import dmd.WANT; | |
24 import dmd.IndexExp; | |
25 import dmd.AssignExp; | |
26 import dmd.CommaExp; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
27 import dmd.CondExp; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
28 import dmd.Parameter; |
0 | 29 import dmd.DefaultInitExp; |
30 import dmd.Identifier; | |
31 import dmd.Dsymbol; | |
32 import dmd.Global; | |
33 import dmd.ScopeDsymbol; | |
34 import dmd.DotIdExp; | |
35 import dmd.DotVarExp; | |
36 import dmd.CallExp; | |
37 import dmd.TY; | |
38 import dmd.MATCH; | |
53 | 39 import dmd.BUILTIN; |
0 | 40 import dmd.TypeFunction; |
41 import dmd.declaration.Match; | |
42 import dmd.ArrayTypes; | |
43 import dmd.Declaration; | |
44 import dmd.FuncAliasDeclaration; | |
45 import dmd.AliasDeclaration; | |
46 import dmd.FuncDeclaration; | |
47 import dmd.TemplateDeclaration; | |
48 import dmd.AggregateDeclaration; | |
49 import dmd.IntegerExp; | |
50 import dmd.Type; | |
51 import dmd.TOK; | |
52 import dmd.TypeExp; | |
53 import dmd.TypeTuple; | |
54 import dmd.TupleExp; | |
55 import dmd.OutBuffer; | |
56 import dmd.HdrGenState; | |
57 import dmd.ClassDeclaration; | |
58 import dmd.TypeClass; | |
59 import dmd.StructDeclaration; | |
60 import dmd.TypeStruct; | |
61 import dmd.MOD; | |
62 import dmd.PROT; | |
63 import dmd.PREC; | |
64 import dmd.Util; | |
65 import dmd.TypeAArray; | |
66 import dmd.Id; | |
114 | 67 import dmd.PtrExp; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
68 import dmd.ErrorExp; |
0 | 69 |
70 import std.stdio : writef; | |
71 | |
129 | 72 import core.stdc.math; |
73 import core.stdc.string; | |
0 | 74 |
75 /*********************************** | |
76 * Utility to build a function call out of this reference and argument. | |
77 */ | |
78 Expression build_overload(Loc loc, Scope sc, Expression ethis, Expression earg, Identifier id) | |
79 { | |
80 Expression e; | |
81 | |
82 //printf("build_overload(id = '%s')\n", id.toChars()); | |
83 //earg.print(); | |
84 //earg.type.print(); | |
85 e = new DotIdExp(loc, ethis, id); | |
86 | |
87 if (earg) | |
88 e = new CallExp(loc, e, earg); | |
89 else | |
90 e = new CallExp(loc, e); | |
91 | |
92 e = e.semantic(sc); | |
93 return e; | |
94 } | |
95 | |
96 /*************************************** | |
97 * Search for function funcid in aggregate ad. | |
98 */ | |
99 | |
100 Dsymbol search_function(ScopeDsymbol ad, Identifier funcid) | |
101 { | |
102 Dsymbol s; | |
103 FuncDeclaration fd; | |
104 TemplateDeclaration td; | |
105 | |
106 s = ad.search(Loc(0), funcid, 0); | |
107 if (s) | |
108 { | |
109 Dsymbol s2; | |
110 | |
111 //printf("search_function: s = '%s'\n", s.kind()); | |
112 s2 = s.toAlias(); | |
113 //printf("search_function: s2 = '%s'\n", s2.kind()); | |
114 fd = s2.isFuncDeclaration(); | |
115 if (fd && fd.type.ty == TY.Tfunction) | |
116 return fd; | |
117 | |
118 td = s2.isTemplateDeclaration(); | |
119 if (td) | |
120 return td; | |
121 } | |
122 | |
123 return null; | |
124 } | |
125 | |
126 /******************************************** | |
127 * Find function in overload list that exactly matches t. | |
128 */ | |
129 | |
130 /*************************************************** | |
131 * Visit each overloaded function in turn, and call | |
132 * dg(param, f) on it. | |
133 * Exit when no more, or dg(param, f) returns 1. | |
134 * Returns: | |
135 * 0 continue | |
136 * 1 done | |
137 */ | |
138 | |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
139 int overloadApply(FuncDeclaration fstart, int delegate(void*, FuncDeclaration) dg, void* param) |
0 | 140 { |
141 FuncDeclaration f; | |
142 Declaration d; | |
143 Declaration next; | |
144 | |
145 for (d = fstart; d; d = next) | |
146 { | |
147 FuncAliasDeclaration fa = d.isFuncAliasDeclaration(); | |
148 | |
149 if (fa) | |
150 { | |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
151 if (overloadApply(fa.funcalias, dg, param)) |
0 | 152 return 1; |
153 next = fa.overnext; | |
154 } | |
155 else | |
156 { | |
157 AliasDeclaration a = d.isAliasDeclaration(); | |
158 | |
159 if (a) | |
160 { | |
161 Dsymbol s = a.toAlias(); | |
162 next = s.isDeclaration(); | |
163 if (next is a) | |
164 break; | |
165 if (next is fstart) | |
166 break; | |
167 } | |
168 else | |
169 { | |
170 f = d.isFuncDeclaration(); | |
171 if (f is null) | |
172 { | |
173 d.error("is aliased to a function"); | |
174 break; // BUG: should print error message? | |
175 } | |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
176 if (dg(param, f)) |
0 | 177 return 1; |
178 | |
179 next = f.overnext; | |
180 } | |
181 } | |
182 } | |
183 return 0; | |
184 } | |
185 | |
186 /******************************************** | |
187 * Decide which function matches the arguments best. | |
188 */ | |
189 | |
190 struct Param2 | |
191 { | |
192 Match* m; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
193 version(DMDV2) { |
0 | 194 Expression ethis; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
195 int property; // 0: unintialized |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
196 // 1: seen @property |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
197 // 2: not @property |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
198 } |
0 | 199 Expressions arguments; |
200 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
201 int fp2(void* param, FuncDeclaration f) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
202 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
203 auto p = cast(Param2*)param; |
0 | 204 MATCH match; |
205 | |
206 if (f != m.lastf) // skip duplicates | |
207 { | |
208 m.anyf = f; | |
209 TypeFunction tf = cast(TypeFunction)f.type; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
210 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
211 int property = (tf.isproperty) ? 1 : 2; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
212 if (p.property == 0) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
213 p.property = property; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
214 else if (p.property != property) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
215 error(f.loc, "cannot overload both property and non-property functions"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
216 |
0 | 217 match = tf.callMatch(f.needThis() ? ethis : null, arguments); |
98 | 218 //printf("test: match = %d\n", match); |
0 | 219 if (match != MATCH.MATCHnomatch) |
220 { | |
221 if (match > m.last) | |
222 goto LfIsBetter; | |
223 | |
224 if (match < m.last) | |
225 goto LlastIsBetter; | |
226 | |
227 /* See if one of the matches overrides the other. | |
228 */ | |
229 if (m.lastf.overrides(f)) | |
230 goto LlastIsBetter; | |
231 else if (f.overrides(m.lastf)) | |
232 goto LfIsBetter; | |
233 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
234 version(DMDV2) { |
0 | 235 /* Try to disambiguate using template-style partial ordering rules. |
236 * In essence, if f() and g() are ambiguous, if f() can call g(), | |
237 * but g() cannot call f(), then pick f(). | |
238 * This is because f() is "more specialized." | |
239 */ | |
240 { | |
241 MATCH c1 = f.leastAsSpecialized(m.lastf); | |
242 MATCH c2 = m.lastf.leastAsSpecialized(f); | |
243 //printf("c1 = %d, c2 = %d\n", c1, c2); | |
244 if (c1 > c2) | |
245 goto LfIsBetter; | |
246 if (c1 < c2) | |
247 goto LlastIsBetter; | |
248 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
249 } |
0 | 250 |
251 Lambiguous: | |
252 m.nextf = f; | |
253 m.count++; | |
254 return 0; | |
255 | |
256 LfIsBetter: | |
257 m.last = match; | |
258 m.lastf = f; | |
259 m.count = 1; | |
260 return 0; | |
261 | |
262 LlastIsBetter: | |
263 return 0; | |
264 } | |
265 } | |
266 return 0; | |
267 } | |
268 } | |
269 | |
270 struct Param1 | |
271 { | |
272 Type t; // type to match | |
273 FuncDeclaration f; // return value | |
274 | |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
275 int fp1(void*, FuncDeclaration f) |
0 | 276 { |
277 if (t.equals(f.type)) | |
278 { | |
279 this.f = f; | |
280 return 1; | |
281 } | |
282 | |
283 version (DMDV2) { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
284 /* Allow covariant matches, as long as the return type |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
285 * is just a const conversion. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
286 * This allows things like pure functions to match with an impure function type. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
287 */ |
0 | 288 if (t.ty == Tfunction) |
289 { | |
290 TypeFunction tf = cast(TypeFunction)f.type; | |
291 if (tf.covariant(t) == 1 && | |
292 tf.nextOf().implicitConvTo(t.nextOf()) >= MATCHconst) | |
293 { | |
294 this.f = f; | |
295 return 1; | |
296 } | |
297 } | |
298 } | |
299 return 0; | |
300 } | |
301 } | |
302 | |
303 void overloadResolveX(Match* m, FuncDeclaration fstart, Expression ethis, Expressions arguments) | |
304 { | |
305 Param2 p; | |
306 p.m = m; | |
307 p.ethis = ethis; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
308 p.property = 0; |
0 | 309 p.arguments = arguments; |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
310 overloadApply(fstart, &p.fp2, &p); |
0 | 311 } |
312 | |
313 void templateResolve(Match* m, TemplateDeclaration td, Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions arguments) | |
314 { | |
315 FuncDeclaration fd; | |
316 | |
317 assert(td); | |
318 fd = td.deduceFunctionTemplate(sc, loc, targsi, ethis, arguments); | |
319 if (!fd) | |
320 return; | |
321 m.anyf = fd; | |
322 if (m.last >= MATCH.MATCHexact) | |
323 { | |
324 m.nextf = fd; | |
325 m.count++; | |
326 } | |
327 else | |
328 { | |
329 m.last = MATCH.MATCHexact; | |
330 m.lastf = fd; | |
331 m.count = 1; | |
332 } | |
333 } | |
334 | |
335 /****************************** | |
336 * Perform semantic() on an array of Expressions. | |
337 */ | |
338 | |
339 void arrayExpressionSemantic(Expressions exps, Scope sc) | |
340 { | |
341 if (exps) | |
342 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
343 foreach (ref Expression e; exps) |
0 | 344 { |
345 e = e.semantic(sc); | |
346 } | |
347 } | |
348 } | |
349 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
350 Expressions arrayExpressionToCommonType(Scope sc, Expressions exps, Type *pt) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
351 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
352 //version(DMDV1) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
353 // /* The first element sets the type |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
354 // */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
355 // Type *t0 = NULL; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
356 // for (size_t i = 0; i < exps->dim; i++) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
357 // { Expression *e = (Expression *)exps->data[i]; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
358 // |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
359 // if (!e->type) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
360 // { error("%s has no value", e->toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
361 // e = new ErrorExp(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
362 // } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
363 // e = resolveProperties(sc, e); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
364 // |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
365 // if (!t0) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
366 // t0 = e->type; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
367 // else |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
368 // e = e->implicitCastTo(sc, t0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
369 // exps->data[i] = (void *)e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
370 // } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
371 // |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
372 // if (!t0) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
373 // t0 = Type::tvoid; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
374 // if (pt) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
375 // *pt = t0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
376 // |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
377 // // Eventually, we want to make this copy-on-write |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
378 // return exps; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
379 //} |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
380 version(DMDV2) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
381 /* The type is determined by applying ?: to each pair. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
382 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
383 /* Still have a problem with: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
384 * ubyte[][] = [ cast(ubyte[])"hello", [1]]; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
385 * which works if the array literal is initialized top down with the ubyte[][] |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
386 * type, but fails with this function doing bottom up typing. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
387 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
388 //printf("arrayExpressionToCommonType()\n"); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
389 scope integerexp = new IntegerExp(0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
390 scope condexp = new CondExp(Loc(0), integerexp, null, null); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
391 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
392 Type t0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
393 Expression e0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
394 int j0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
395 foreach (size_t i, Expression e; exps) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
396 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
397 e = resolveProperties(sc, e); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
398 if (!e.type) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
399 { error("%s has no value", e.toChars()); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
400 e = new ErrorExp(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
401 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
402 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
403 if (t0) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
404 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
405 if (t0 != e.type) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
406 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
407 /* This applies ?: to merge the types. It's backwards; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
408 * ?: should call this function to merge types. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
409 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
410 condexp.type = null; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
411 condexp.e1 = e0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
412 condexp.e2 = e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
413 condexp.semantic(sc); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
414 exps[j0] = condexp.e1; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
415 e = condexp.e2; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
416 j0 = i; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
417 e0 = e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
418 t0 = e0.type; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
419 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
420 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
421 else |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
422 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
423 j0 = i; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
424 e0 = e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
425 t0 = e.type; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
426 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
427 exps[i] = e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
428 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
429 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
430 if (t0) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
431 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
432 foreach (ref Expression e; exps) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
433 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
434 e = e.implicitCastTo(sc, t0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
435 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
436 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
437 else |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
438 t0 = Type.tvoid; // [] is typed as void[] |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
439 if (pt) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
440 *pt = t0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
441 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
442 // Eventually, we want to make this copy-on-write |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
443 return exps; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
444 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
445 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
446 |
0 | 447 /**************************************** |
448 * Preprocess arguments to function. | |
449 */ | |
450 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
451 void preFunctionParameters(Loc loc, Scope sc, Expressions exps) |
0 | 452 { |
453 if (exps) | |
454 { | |
455 expandTuples(exps); | |
57 | 456 |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
457 foreach (size_t i, ref Expression arg; exps) |
0 | 458 { |
459 if (!arg.type) | |
460 { | |
461 debug { | |
57 | 462 if (!global.gag) { |
0 | 463 writef("1: \n"); |
57 | 464 } |
0 | 465 } |
466 arg.error("%s is not an expression", arg.toChars()); | |
467 arg = new IntegerExp(arg.loc, 0, Type.tint32); | |
468 } | |
469 | |
470 arg = resolveProperties(sc, arg); | |
471 | |
472 //arg.rvalue(); | |
473 static if (false) { | |
474 if (arg.type.ty == TY.Tfunction) | |
475 { | |
476 arg = new AddrExp(arg.loc, arg); | |
477 arg = arg.semantic(sc); | |
478 } | |
479 } | |
480 } | |
481 } | |
482 } | |
483 | |
484 /************************************************************* | |
485 * Given var, we need to get the | |
486 * right 'this' pointer if var is in an outer class, but our | |
487 * existing 'this' pointer is in an inner class. | |
488 * Input: | |
489 * e1 existing 'this' | |
490 * ad struct or class we need the correct 'this' for | |
491 * var the specific member of ad we're accessing | |
492 */ | |
493 | |
494 Expression getRightThis(Loc loc, Scope sc, AggregateDeclaration ad, Expression e1, Declaration var) | |
495 { | |
496 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars()); | |
497 L1: | |
498 Type t = e1.type.toBasetype(); | |
499 //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars()); | |
500 | |
501 /* If e1 is not the 'this' pointer for ad | |
502 */ | |
503 if (ad && !(t.ty == TY.Tpointer && t.nextOf().ty == TY.Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) && !(t.ty == TY.Tstruct && (cast(TypeStruct)t).sym == ad)) | |
504 { | |
505 ClassDeclaration cd = ad.isClassDeclaration(); | |
506 ClassDeclaration tcd = t.isClassHandle(); | |
507 | |
508 /* e1 is the right this if ad is a base class of e1 | |
509 */ | |
510 if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null))) | |
511 { | |
512 /* Only classes can be inner classes with an 'outer' | |
513 * member pointing to the enclosing class instance | |
514 */ | |
515 if (tcd && tcd.isNested()) | |
516 { | |
517 /* e1 is the 'this' pointer for an inner class: tcd. | |
518 * Rewrite it as the 'this' pointer for the outer class. | |
519 */ | |
520 | |
521 e1 = new DotVarExp(loc, e1, tcd.vthis); | |
522 e1.type = tcd.vthis.type; | |
523 // Do not call checkNestedRef() | |
524 //e1 = e1.semantic(sc); | |
525 | |
526 // Skip up over nested functions, and get the enclosing | |
527 // class type. | |
528 int n = 0; | |
529 Dsymbol s; | |
530 for (s = tcd.toParent(); s && s.isFuncDeclaration(); s = s.toParent()) | |
531 { | |
532 FuncDeclaration f = s.isFuncDeclaration(); | |
533 if (f.vthis) | |
534 { | |
535 //printf("rewriting e1 to %s's this\n", f.toChars()); | |
536 n++; | |
537 e1 = new VarExp(loc, f.vthis); | |
538 } | |
539 } | |
540 if (s && s.isClassDeclaration()) | |
541 { | |
542 e1.type = s.isClassDeclaration().type; | |
543 if (n > 1) | |
544 e1 = e1.semantic(sc); | |
545 } | |
546 else | |
547 e1 = e1.semantic(sc); | |
548 goto L1; | |
549 } | |
550 /* Can't find a path from e1 to ad | |
551 */ | |
552 e1.error("this for %s needs to be type %s not type %s", var.toChars(), ad.toChars(), t.toChars()); | |
553 } | |
554 } | |
555 return e1; | |
556 } | |
557 | |
558 /******************************************* | |
559 * Given a symbol that could be either a FuncDeclaration or | |
560 * a function template, resolve it to a function symbol. | |
561 * sc instantiation scope | |
562 * loc instantiation location | |
563 * targsi initial list of template arguments | |
564 * ethis if !null, the 'this' pointer argument | |
565 * fargs arguments to function | |
566 * flags 1: do not issue error message on no match, just return null | |
567 */ | |
568 | |
569 FuncDeclaration resolveFuncCall(Scope sc, Loc loc, Dsymbol s, | |
570 Objects tiargs, | |
571 Expression ethis, | |
572 Expressions arguments, | |
573 int flags) | |
574 { | |
575 if (!s) | |
576 return null; // no match | |
577 FuncDeclaration f = s.isFuncDeclaration(); | |
578 if (f) | |
579 f = f.overloadResolve(loc, ethis, arguments); | |
580 else | |
581 { | |
582 TemplateDeclaration td = s.isTemplateDeclaration(); | |
583 assert(td); | |
584 f = td.deduceFunctionTemplate(sc, loc, tiargs, null, arguments, flags); | |
585 } | |
586 return f; | |
587 } | |
588 | |
589 /**************************************** | |
590 * Now that we know the exact type of the function we're calling, | |
591 * the arguments[] need to be adjusted: | |
592 * 1. implicitly convert argument to the corresponding parameter type | |
593 * 2. add default arguments for any missing arguments | |
594 * 3. do default promotions on arguments corresponding to ... | |
595 * 4. add hidden _arguments[] argument | |
596 * 5. call copy constructor for struct value arguments | |
135 | 597 * Returns: |
598 * return type from function | |
0 | 599 */ |
600 | |
135 | 601 Type functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) |
0 | 602 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
603 //printf("functionParameters()\n"); |
0 | 604 assert(arguments); |
605 size_t nargs = arguments ? arguments.dim : 0; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
606 size_t nparams = Parameter.dim(tf.parameters); |
0 | 607 |
608 if (nargs > nparams && tf.varargs == 0) | |
609 error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars()); | |
610 | |
135 | 611 uint n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) |
0 | 612 |
135 | 613 uint wildmatch = 0; |
614 | |
0 | 615 int done = 0; |
616 for (size_t i = 0; i < n; i++) | |
617 { | |
618 Expression arg; | |
619 | |
620 if (i < nargs) | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
621 arg = arguments[i]; |
0 | 622 else |
623 arg = null; | |
624 | |
625 Type tb; | |
626 | |
627 if (i < nparams) | |
628 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
629 auto p = Parameter.getNth(tf.parameters, i); |
0 | 630 |
631 if (!arg) | |
632 { | |
633 if (!p.defaultArg) | |
634 { | |
635 if (tf.varargs == 2 && i + 1 == nparams) | |
636 goto L2; | |
637 | |
638 error(loc, "expected %d function arguments, not %d", nparams, nargs); | |
135 | 639 return tf.next; |
0 | 640 } |
641 arg = p.defaultArg; | |
642 arg = arg.copy(); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
643 version (DMDV2) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
644 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
645 arg = arg.resolveLoc(loc, sc); // __FILE__ and __LINE__ |
0 | 646 } |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
647 arguments.push(arg); |
0 | 648 nargs++; |
649 } | |
650 | |
651 if (tf.varargs == 2 && i + 1 == nparams) | |
652 { | |
653 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars()); | |
654 if (arg.implicitConvTo(p.type)) | |
655 { | |
656 if (nargs != nparams) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
657 { |
0 | 658 error(loc, "expected %zu function arguments, not %zu", nparams, nargs); |
135 | 659 return tf.next; |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
660 } |
0 | 661 goto L1; |
662 } | |
663 L2: | |
664 tb = p.type.toBasetype(); /// | |
665 Type tret = p.isLazyArray(); | |
666 switch (tb.ty) | |
667 { | |
668 case TY.Tsarray: | |
669 case TY.Tarray: | |
670 { // Create a static array variable v of type arg.type | |
671 version (IN_GCC) { | |
672 /* GCC 4.0 does not like zero length arrays used like | |
673 this; pass a null array value instead. Could also | |
674 just make a one-element array. */ | |
675 if (nargs - i == 0) | |
676 { | |
677 arg = new NullExp(loc); | |
678 break; | |
679 } | |
680 } | |
681 Identifier id = Lexer.uniqueId("__arrayArg"); | |
682 Type t = new TypeSArray((cast(TypeArray)tb).next, new IntegerExp(nargs - i)); | |
683 t = t.semantic(loc, sc); | |
684 VarDeclaration v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); | |
135 | 685 v.storage_class |= STCctfe; |
0 | 686 v.semantic(sc); |
687 v.parent = sc.parent; | |
688 //sc.insert(v); | |
689 | |
690 Expression c = new DeclarationExp(Loc(0), v); | |
691 c.type = v.type; | |
692 | |
693 for (size_t u = i; u < nargs; u++) | |
694 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
695 auto a = arguments[u]; |
0 | 696 if (tret && !(cast(TypeArray)tb).next.equals(a.type)) |
697 a = a.toDelegate(sc, tret); | |
698 | |
699 Expression e = new VarExp(loc, v); | |
700 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
701 auto ae = new AssignExp(loc, e, a); |
0 | 702 |
703 version (DMDV2) { | |
704 ae.op = TOK.TOKconstruct; | |
705 } | |
706 | |
707 if (c) | |
708 c = new CommaExp(loc, c, ae); | |
709 else | |
710 c = ae; | |
711 } | |
712 | |
713 arg = new VarExp(loc, v); | |
714 if (c) | |
715 arg = new CommaExp(loc, c, arg); | |
716 break; | |
717 } | |
718 | |
719 case TY.Tclass: | |
720 { /* Set arg to be: | |
721 * new Tclass(arg0, arg1, ..., argn) | |
722 */ | |
723 Expressions args = new Expressions(); | |
724 args.setDim(nargs - i); | |
725 for (size_t u = i; u < nargs; u++) | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
726 args[u - i] = arguments[u]; |
0 | 727 arg = new NewExp(loc, null, null, p.type, args); |
728 break; | |
729 } | |
730 | |
731 default: | |
732 if (!arg) | |
733 { | |
734 error(loc, "not enough arguments"); | |
135 | 735 return tf.next; |
0 | 736 } |
737 break; | |
738 } | |
739 | |
740 arg = arg.semantic(sc); | |
741 //printf("\targ = '%s'\n", arg.toChars()); | |
742 arguments.setDim(i + 1); | |
743 done = 1; | |
744 } | |
745 | |
746 L1: | |
747 if (!(p.storageClass & STC.STClazy && p.type.ty == TY.Tvoid)) | |
748 { | |
749 if (p.type != arg.type) | |
750 { | |
751 //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars()); | |
109 | 752 if (arg.op == TOKtype) |
753 arg.error("cannot pass type %s as function argument", arg.toChars()); | |
135 | 754 if (p.type.isWild() && tf.next.isWild()) |
755 { | |
756 Type t = p.type; | |
757 MATCH m = arg.implicitConvTo(t); | |
758 if (m == MATCH.MATCHnomatch) | |
759 { | |
760 t = t.constOf(); | |
761 m = arg.implicitConvTo(t); | |
762 if (m == MATCHnomatch) | |
763 { | |
764 t = t.sharedConstOf(); | |
765 m = arg.implicitConvTo(t); | |
766 } | |
767 wildmatch |= p.type.wildMatch(arg.type); | |
768 } | |
769 arg = arg.implicitCastTo(sc, t); | |
770 } | |
771 else | |
772 arg = arg.implicitCastTo(sc, p.type); | |
0 | 773 arg = arg.optimize(WANT.WANTvalue); |
774 } | |
775 } | |
776 if (p.storageClass & STC.STCref) | |
777 { | |
778 arg = arg.toLvalue(sc, arg); | |
779 } | |
780 else if (p.storageClass & STC.STCout) | |
781 { | |
782 arg = arg.modifiableLvalue(sc, arg); | |
783 } | |
784 | |
109 | 785 tb = arg.type.toBasetype(); |
786 version(SARRAYVALUE) {} else | |
787 { | |
0 | 788 // Convert static arrays to pointers |
789 if (tb.ty == TY.Tsarray) | |
790 { | |
791 arg = arg.checkToPointer(); | |
792 } | |
109 | 793 } |
0 | 794 version (DMDV2) { |
795 if (tb.ty == TY.Tstruct && !(p.storageClass & (STC.STCref | STC.STCout))) | |
796 { | |
797 arg = callCpCtor(loc, sc, arg); | |
798 } | |
799 } | |
800 | |
801 // Convert lazy argument to a delegate | |
802 if (p.storageClass & STC.STClazy) | |
803 { | |
804 arg = arg.toDelegate(sc, p.type); | |
805 } | |
806 version (DMDV2) { | |
807 /* Look for arguments that cannot 'escape' from the called | |
808 * function. | |
809 */ | |
810 if (!tf.parameterEscapes(p)) | |
811 { | |
812 /* Function literals can only appear once, so if this | |
813 * appearance was scoped, there cannot be any others. | |
814 */ | |
815 if (arg.op == TOK.TOKfunction) | |
816 { | |
817 FuncExp fe = cast(FuncExp)arg; | |
818 fe.fd.tookAddressOf = 0; | |
819 } | |
820 | |
821 /* For passing a delegate to a scoped parameter, | |
822 * this doesn't count as taking the address of it. | |
823 * We only worry about 'escaping' references to the function. | |
824 */ | |
825 else if (arg.op == TOK.TOKdelegate) | |
826 { | |
827 DelegateExp de = cast(DelegateExp)arg; | |
828 if (de.e1.op == TOK.TOKvar) | |
829 { | |
830 VarExp ve = cast(VarExp)de.e1; | |
831 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
832 if (f) | |
833 { | |
834 f.tookAddressOf--; | |
835 //printf("tookAddressOf = %d\n", f.tookAddressOf); | |
836 } | |
837 } | |
838 } | |
839 } | |
840 } | |
841 } | |
842 else | |
843 { | |
844 // If not D linkage, do promotions | |
845 if (tf.linkage != LINK.LINKd) | |
846 { | |
847 // Promote bytes, words, etc., to ints | |
848 arg = arg.integralPromotions(sc); | |
849 | |
850 // Promote floats to doubles | |
851 switch (arg.type.ty) | |
852 { | |
853 case TY.Tfloat32: | |
854 arg = arg.castTo(sc, Type.tfloat64); | |
855 break; | |
856 | |
857 case TY.Timaginary32: | |
858 arg = arg.castTo(sc, Type.timaginary64); | |
859 break; | |
860 default: | |
861 break; | |
862 } | |
863 } | |
864 | |
865 // Convert static arrays to dynamic arrays | |
866 tb = arg.type.toBasetype(); | |
867 if (tb.ty == TY.Tsarray) | |
868 { | |
869 TypeSArray ts = cast(TypeSArray)tb; | |
870 Type ta = ts.next.arrayOf(); | |
871 if (ts.size(arg.loc) == 0) | |
135 | 872 arg = new NullExp(arg.loc, ta); |
0 | 873 else |
874 arg = arg.castTo(sc, ta); | |
875 } | |
876 version (DMDV2) { | |
73 | 877 if (tb.ty == Tstruct) |
0 | 878 { |
879 arg = callCpCtor(loc, sc, arg); | |
880 } | |
73 | 881 } |
0 | 882 |
73 | 883 // Give error for overloaded function addresses |
884 if (arg.op == TOKsymoff) | |
885 { | |
886 SymOffExp se = cast(SymOffExp)arg; | |
887 version (DMDV2) { | |
888 bool aux = (se.hasOverloads != 0); | |
889 } else { | |
890 bool aux = true; | |
0 | 891 } |
73 | 892 if (aux && !se.var.isFuncDeclaration().isUnique()) |
893 arg.error("function %s is overloaded", arg.toChars()); | |
894 } | |
895 | |
896 arg.rvalue(); | |
897 } | |
898 | |
0 | 899 arg = arg.optimize(WANT.WANTvalue); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
900 arguments[i] = arg; |
0 | 901 if (done) |
902 break; | |
903 } | |
904 | |
905 // If D linkage and variadic, add _arguments[] as first argument | |
906 if (tf.linkage == LINK.LINKd && tf.varargs == 1) | |
907 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
908 assert(arguments.dim >= nparams); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
909 auto e = createTypeInfoArray(sc, &arguments[nparams], arguments.dim - nparams); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
910 arguments.insert(0, e); |
0 | 911 } |
135 | 912 |
913 Type tret = tf.next; | |
914 if (wildmatch) | |
915 { /* Adjust function return type based on wildmatch | |
916 */ | |
917 //printf("wildmatch = x%x\n", wildmatch); | |
918 assert(tret.isWild()); | |
919 if (wildmatch & MOD.MODconst || wildmatch & (wildmatch - 1)) | |
920 tret = tret.constOf(); | |
921 else if (wildmatch & MOD.MODimmutable) | |
922 tret = tret.invariantOf(); | |
923 else | |
924 { | |
925 assert(wildmatch & MOD.MODmutable); | |
926 tret = tret.mutableOf(); | |
927 } | |
928 } | |
929 return tret; | |
0 | 930 } |
931 | |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
932 /****************************** |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
933 * Perform canThrow() on an array of Expressions. |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
934 */ |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
935 |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
936 version (DMDV2) { |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
937 bool arrayExpressionCanThrow(Expressions exps) |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
938 { |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
939 if (exps) |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
940 { |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
941 foreach (e; exps) |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
942 { |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
943 if (e && e.canThrow()) |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
944 return true; |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
945 } |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
946 } |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
947 return false; |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
948 } |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
949 } |
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
950 |
0 | 951 /**************************************** |
952 * Expand tuples. | |
953 */ | |
954 | |
955 void expandTuples(Expressions exps) | |
956 { | |
957 //printf("expandTuples()\n"); | |
958 if (exps) | |
959 { | |
960 for (size_t i = 0; i < exps.dim; i++) | |
961 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
962 auto arg = exps[i]; |
0 | 963 if (!arg) |
964 continue; | |
965 | |
966 // Look for tuple with 0 members | |
967 if (arg.op == TOK.TOKtype) | |
57 | 968 { |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
969 auto e = cast(TypeExp)arg; |
0 | 970 if (e.type.toBasetype().ty == TY.Ttuple) |
971 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
972 auto tt = cast(TypeTuple)e.type.toBasetype(); |
0 | 973 |
974 if (!tt.arguments || tt.arguments.dim == 0) | |
975 { | |
976 exps.remove(i); | |
977 if (i == exps.dim) | |
978 return; | |
979 i--; | |
980 continue; | |
981 } | |
982 } | |
983 } | |
984 | |
985 // Inline expand all the tuples | |
986 while (arg.op == TOK.TOKtuple) | |
987 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
988 auto te = cast(TupleExp)arg; |
0 | 989 |
990 exps.remove(i); // remove arg | |
57 | 991 exps.insert(i, te.exps); // replace with tuple contents |
0 | 992 |
993 if (i == exps.dim) | |
994 return; // empty tuple, no more arguments | |
995 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
996 arg = exps[i]; |
0 | 997 } |
998 } | |
999 } | |
1000 } | |
1001 | |
1002 /************************************************** | |
1003 * Write out argument types to buf. | |
1004 */ | |
1005 | |
1006 void argExpTypesToCBuffer(OutBuffer buf, Expressions arguments, HdrGenState* hgs) | |
1007 { | |
1008 if (arguments) | |
1009 { | |
1010 scope OutBuffer argbuf = new OutBuffer(); | |
1011 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
1012 foreach (size_t i, Expression arg; arguments) |
0 | 1013 { |
1014 if (i) | |
1015 buf.writeByte(','); | |
1016 | |
1017 argbuf.reset(); | |
1018 arg.type.toCBuffer2(argbuf, hgs, MOD.MODundefined); | |
1019 buf.write(argbuf); | |
1020 } | |
1021 } | |
1022 } | |
1023 | |
1024 /**************************************** | |
1025 * Determine if scope sc has package level access to s. | |
1026 */ | |
1027 | |
1028 bool hasPackageAccess(Scope sc, Dsymbol s) | |
1029 { | |
1030 version (LOG) { | |
1031 printf("hasPackageAccess(s = '%s', sc = '%p')\n", s.toChars(), sc); | |
1032 } | |
1033 | |
1034 for (; s; s = s.parent) | |
1035 { | |
1036 if (s.isPackage() && !s.isModule()) | |
1037 break; | |
1038 } | |
1039 version (LOG) { | |
1040 if (s) | |
1041 printf("\tthis is in package '%s'\n", s.toChars()); | |
1042 } | |
1043 | |
1044 if (s && s == sc.module_.parent) | |
1045 { | |
1046 version (LOG) { | |
1047 printf("\ts is in same package as sc\n"); | |
1048 } | |
1049 return true; | |
1050 } | |
1051 | |
1052 | |
1053 version (LOG) { | |
1054 printf("\tno package access\n"); | |
1055 } | |
1056 | |
1057 return false; | |
1058 } | |
1059 | |
1060 /********************************************* | |
1061 * Call copy constructor for struct value argument. | |
1062 */ | |
1063 version (DMDV2) { | |
1064 Expression callCpCtor(Loc loc, Scope sc, Expression e) | |
1065 { | |
1066 Type tb = e.type.toBasetype(); | |
1067 assert(tb.ty == Tstruct); | |
1068 StructDeclaration sd = (cast(TypeStruct)tb).sym; | |
1069 if (sd.cpctor) | |
1070 { | |
1071 /* Create a variable tmp, and replace the argument e with: | |
1072 * (tmp = e),tmp | |
1073 * and let AssignExp() handle the construction. | |
1074 * This is not the most efficent, ideally tmp would be constructed | |
1075 * directly onto the stack. | |
1076 */ | |
1077 Identifier idtmp = Lexer.uniqueId("__tmp"); | |
1078 VarDeclaration tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(Loc(0), e)); | |
1079 Expression ae = new DeclarationExp(loc, tmp); | |
1080 e = new CommaExp(loc, ae, new VarExp(loc, tmp)); | |
1081 e = e.semantic(sc); | |
1082 } | |
1083 return e; | |
1084 } | |
1085 } | |
1086 | |
1087 /*************************************** | |
1088 * Create a static array of TypeInfo references | |
1089 * corresponding to an array of Expression's. | |
1090 * Used to supply hidden _arguments[] value for variadic D functions. | |
1091 */ | |
1092 | |
1093 Expression createTypeInfoArray(Scope sc, Expression* exps, int dim) | |
1094 { | |
79 | 1095 static if (true) |
1096 { | |
57 | 1097 /* Get the corresponding TypeInfo_Tuple and |
1098 * point at its elements[]. | |
1099 */ | |
1100 | |
1101 /* Create the TypeTuple corresponding to the types of args[] | |
1102 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1103 auto args = new Parameters; |
57 | 1104 args.setDim(dim); |
1105 for (size_t i = 0; i < dim; i++) | |
1106 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1107 auto arg = new Parameter(STCin, exps[i].type, null, null); |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1108 args[i] = arg; |
57 | 1109 } |
1110 TypeTuple tup = new TypeTuple(args); | |
1111 Expression e = tup.getTypeInfo(sc); | |
1112 e = e.optimize(WANTvalue); | |
1113 assert(e.op == TOKsymoff); // should be SymOffExp | |
1114 | |
79 | 1115 version (BREAKABI) |
1116 { | |
57 | 1117 /* |
1118 * Should just pass a reference to TypeInfo_Tuple instead, | |
1119 * but that would require existing code to be recompiled. | |
1120 * Source compatibility can be maintained by computing _arguments[] | |
1121 * at the start of the called function by offseting into the | |
1122 * TypeInfo_Tuple reference. | |
1123 */ | |
1124 | |
79 | 1125 } |
1126 else | |
1127 { | |
57 | 1128 // Advance to elements[] member of TypeInfo_Tuple |
1129 SymOffExp se = cast(SymOffExp)e; | |
1130 se.offset += PTRSIZE + PTRSIZE; | |
1131 | |
1132 // Set type to TypeInfo[]* | |
1133 se.type = Type.typeinfo.type.arrayOf().pointerTo(); | |
1134 | |
1135 // Indirect to get the _arguments[] value | |
1136 e = new PtrExp(Loc(0), se); | |
1137 e.type = se.type.next; | |
1138 } | |
1139 return e; | |
79 | 1140 } // of static if (true) |
1141 else | |
1142 { | |
57 | 1143 /* Improvements: |
1144 * 1) create an array literal instead, | |
1145 * as it would eliminate the extra dereference of loading the | |
1146 * static variable. | |
1147 */ | |
1148 | |
1149 ArrayInitializer ai = new ArrayInitializer(Loc(0)); | |
1150 VarDeclaration v; | |
1151 Type t; | |
1152 Expression e; | |
1153 scope OutBuffer buf = new OutBuffer(); | |
1154 Identifier id; | |
1155 string name; | |
1156 | |
1157 // Generate identifier for _arguments[] | |
1158 buf.writestring("_arguments_"); | |
1159 for (int i = 0; i < dim; i++) | |
1160 { | |
1161 t = exps[i].type; | |
1162 t.toDecoBuffer(buf); | |
1163 } | |
1164 buf.writeByte(0); | |
1165 id = Lexer.idPool(buf.extractString()); | |
1166 | |
1167 Module m = sc.module_; | |
1168 Dsymbol s = m.symtab.lookup(id); | |
1169 | |
1170 if (s && s.parent == m) | |
1171 { | |
1172 // Use existing one | |
1173 v = s.isVarDeclaration(); | |
1174 assert(v); | |
1175 } | |
1176 else | |
1177 { | |
1178 // Generate new one | |
1179 | |
1180 for (int i = 0; i < dim; i++) | |
1181 { | |
1182 t = exps[i].type; | |
1183 e = t.getTypeInfo(sc); | |
1184 ai.addInit(new IntegerExp(i), new ExpInitializer(0, e)); | |
1185 } | |
1186 | |
1187 t = Type.typeinfo.type.arrayOf(); | |
1188 ai.type = t; | |
1189 v = new VarDeclaration(0, t, id, ai); | |
1190 m.members.push(v); | |
79 | 1191 m.symtabInsert(v); |
57 | 1192 sc = sc.push(); |
1193 sc.linkage = LINKc; | |
1194 sc.stc = STCstatic | STCcomdat; | |
1195 ai.semantic(sc, t); | |
1196 v.semantic(sc); | |
1197 v.parent = m; | |
1198 sc = sc.pop(); | |
1199 } | |
1200 e = new VarExp(0, v); | |
1201 e = e.semantic(sc); | |
1202 return e; | |
1203 } | |
0 | 1204 } |
1205 | |
1206 /************************************** | |
1207 * Evaluate builtin function. | |
1208 * Return result: null if cannot evaluate it. | |
1209 */ | |
1210 | |
53 | 1211 extern(C) extern real sinl(real); |
1212 extern(C) extern real cosl(real); | |
1213 extern(C) extern real tanl(real); | |
1214 extern(C) extern real sqrtl(real); | |
1215 extern(C) extern real fabsl(real); | |
1216 | |
0 | 1217 Expression eval_builtin(BUILTIN builtin, Expressions arguments) |
1218 { | |
53 | 1219 assert(arguments && arguments.dim); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
1220 auto arg0 = arguments[0]; |
53 | 1221 Expression e = null; |
1222 switch (builtin) | |
1223 { | |
1224 case BUILTINsin: | |
1225 if (arg0.op == TOKfloat64) | |
1226 e = new RealExp(Loc(0), sinl(arg0.toReal()), arg0.type); | |
1227 break; | |
1228 | |
1229 case BUILTINcos: | |
1230 if (arg0.op == TOKfloat64) | |
1231 e = new RealExp(Loc(0), cosl(arg0.toReal()), arg0.type); | |
1232 break; | |
1233 | |
1234 case BUILTINtan: | |
1235 if (arg0.op == TOKfloat64) | |
1236 e = new RealExp(Loc(0), tanl(arg0.toReal()), arg0.type); | |
1237 break; | |
1238 | |
1239 case BUILTINsqrt: | |
1240 if (arg0.op == TOKfloat64) | |
1241 e = new RealExp(Loc(0), sqrtl(arg0.toReal()), arg0.type); | |
1242 break; | |
1243 | |
1244 case BUILTINfabs: | |
1245 if (arg0.op == TOKfloat64) | |
1246 e = new RealExp(Loc(0), fabsl(arg0.toReal()), arg0.type); | |
1247 break; | |
1248 } | |
1249 return e; | |
0 | 1250 } |
1251 | |
1252 Expression fromConstInitializer(int result, Expression e1) | |
1253 { | |
1254 //printf("fromConstInitializer(result = %x, %s)\n", result, e1.toChars()); | |
1255 //static int xx; if (xx++ == 10) assert(0); | |
1256 Expression e = e1; | |
1257 if (e1.op == TOK.TOKvar) | |
1258 { | |
1259 VarExp ve = cast(VarExp)e1; | |
1260 VarDeclaration v = ve.var.isVarDeclaration(); | |
1261 e = expandVar(result, v); | |
1262 if (e) | |
1263 { | |
1264 if (e.type != e1.type) | |
1265 { | |
1266 // Type 'paint' operation | |
1267 e = e.copy(); | |
1268 e.type = e1.type; | |
1269 } | |
79 | 1270 e.loc = e1.loc; |
0 | 1271 } |
1272 else | |
1273 { | |
1274 e = e1; | |
1275 } | |
1276 } | |
1277 return e; | |
1278 } | |
1279 | |
1280 /************************************* | |
1281 * If variable has a const initializer, | |
1282 * return that initializer. | |
1283 */ | |
1284 | |
1285 Expression expandVar(int result, VarDeclaration v) | |
1286 { | |
1287 //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v.toChars() : "null"); | |
1288 | |
1289 Expression e = null; | |
1290 if (!v) | |
1291 return e; | |
1292 | |
135 | 1293 if (v.isConst() || v.isImmutable() || v.storage_class & STC.STCmanifest) |
0 | 1294 { |
1295 if (!v.type) | |
1296 { | |
1297 //error("ICE"); | |
1298 return e; | |
1299 } | |
1300 | |
1301 Type tb = v.type.toBasetype(); | |
1302 if (result & WANT.WANTinterpret || v.storage_class & STC.STCmanifest || (tb.ty != TY.Tsarray && tb.ty != TY.Tstruct)) | |
1303 { | |
1304 if (v.init) | |
1305 { | |
1306 if (v.inuse) | |
1307 { | |
1308 if (v.storage_class & STC.STCmanifest) | |
1309 v.error("recursive initialization of constant"); | |
1310 goto L1; | |
1311 } | |
1312 Expression ei = v.init.toExpression(); | |
1313 if (!ei) | |
1314 goto L1; | |
1315 if (ei.op == TOK.TOKconstruct || ei.op == TOK.TOKblit) | |
1316 { | |
1317 AssignExp ae = cast(AssignExp)ei; | |
1318 ei = ae.e2; | |
1319 if (ei.isConst() != 1 && ei.op != TOK.TOKstring) | |
1320 goto L1; | |
1321 if (ei.type != v.type) | |
1322 goto L1; | |
1323 } | |
1324 if (v.scope_) | |
1325 { | |
1326 v.inuse++; | |
1327 e = ei.syntaxCopy(); | |
1328 e = e.semantic(v.scope_); | |
1329 e = e.implicitCastTo(v.scope_, v.type); | |
1330 // enabling this line causes test22 in test suite to fail | |
1331 //ei.type = e.type; | |
1332 v.scope_ = null; | |
1333 v.inuse--; | |
1334 } | |
1335 else if (!ei.type) | |
1336 { | |
1337 goto L1; | |
1338 } | |
1339 else | |
1340 // Should remove the copy() operation by | |
1341 // making all mods to expressions copy-on-write | |
1342 e = ei.copy(); | |
1343 } | |
1344 else | |
1345 { | |
1346 static if (true) { | |
1347 goto L1; | |
1348 } else { | |
1349 // BUG: what if const is initialized in constructor? | |
1350 e = v.type.defaultInit(); | |
1351 e.loc = e1.loc; | |
1352 } | |
1353 } | |
1354 if (e.type != v.type) | |
1355 { | |
1356 e = e.castTo(null, v.type); | |
1357 } | |
1358 v.inuse++; | |
1359 e = e.optimize(result); | |
1360 v.inuse--; | |
1361 } | |
1362 } | |
1363 L1: | |
1364 //if (e) printf("\te = %s, e.type = %s\n", e.toChars(), e.type.toChars()); | |
1365 return e; | |
1366 } | |
1367 | |
1368 /**************************************** | |
1369 * Check access to d for expression e.d | |
1370 */ | |
1371 | |
1372 void accessCheck(Loc loc, Scope sc, Expression e, Declaration d) | |
1373 { | |
1374 version (LOG) { | |
1375 if (e) | |
1376 { | |
1377 printf("accessCheck(%s . %s)\n", e.toChars(), d.toChars()); | |
1378 printf("\te.type = %s\n", e.type.toChars()); | |
1379 } | |
1380 else | |
1381 { | |
1382 //printf("accessCheck(%s)\n", d.toChars()); | |
1383 } | |
1384 } | |
1385 if (!e) | |
1386 { | |
1387 if (d.prot() == PROT.PROTprivate && d.getModule() != sc.module_ || | |
1388 d.prot() == PROT.PROTpackage && !hasPackageAccess(sc, d)) | |
1389 | |
1390 error(loc, "%s %s.%s is not accessible from %s", | |
1391 d.kind(), d.getModule().toChars(), d.toChars(), sc.module_.toChars()); | |
1392 } | |
1393 else if (e.type.ty == TY.Tclass) | |
1394 { | |
1395 // Do access check | |
1396 ClassDeclaration cd; | |
1397 | |
1398 cd = cast(ClassDeclaration)((cast(TypeClass)e.type).sym); | |
1399 static if (true) { | |
1400 if (e.op == TOK.TOKsuper) | |
1401 { | |
1402 ClassDeclaration cd2 = sc.func.toParent().isClassDeclaration(); | |
1403 if (cd2) | |
1404 cd = cd2; | |
1405 } | |
1406 } | |
1407 cd.accessCheck(loc, sc, d); | |
1408 } | |
1409 else if (e.type.ty == TY.Tstruct) | |
1410 { | |
1411 // Do access check | |
1412 StructDeclaration cd = cast(StructDeclaration)((cast(TypeStruct)e.type).sym); | |
1413 cd.accessCheck(loc, sc, d); | |
1414 } | |
1415 } | |
1416 | |
1417 /***************************************** | |
1418 * Given array of arguments and an aggregate type, | |
1419 * if any of the argument types are missing, attempt to infer | |
1420 * them from the aggregate type. | |
1421 */ | |
1422 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1423 void inferApplyArgTypes(TOK op, Parameters arguments, Expression aggr) |
0 | 1424 { |
1425 if (!arguments || !arguments.dim) | |
1426 return; | |
1427 | |
1428 /* Return if no arguments need types. | |
1429 */ | |
1430 for (size_t u = 0; 1; u++) | |
1431 { | |
1432 if (u == arguments.dim) | |
1433 return; | |
1434 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1435 auto arg = arguments[u]; |
0 | 1436 if (!arg.type) |
1437 break; | |
1438 } | |
1439 | |
135 | 1440 Dsymbol s; |
0 | 1441 AggregateDeclaration ad; |
1442 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1443 auto arg = arguments[0]; |
0 | 1444 Type taggr = aggr.type; |
1445 if (!taggr) | |
1446 return; | |
1447 Type tab = taggr.toBasetype(); | |
1448 switch (tab.ty) | |
1449 { | |
1450 case TY.Tarray: | |
1451 case TY.Tsarray: | |
1452 case TY.Ttuple: | |
1453 if (arguments.dim == 2) | |
1454 { | |
1455 if (!arg.type) | |
1456 arg.type = Type.tsize_t; // key type | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1457 arg = arguments[1]; |
0 | 1458 } |
1459 if (!arg.type && tab.ty != TY.Ttuple) | |
1460 arg.type = tab.nextOf(); // value type | |
1461 break; | |
1462 | |
1463 case TY.Taarray: | |
1464 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1465 auto taa = cast(TypeAArray)tab; |
0 | 1466 |
1467 if (arguments.dim == 2) | |
1468 { | |
1469 if (!arg.type) | |
1470 arg.type = taa.index; // key type | |
126
1765f3ef917d
ClassDeclarations, Arguments -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
1471 arg = arguments[1]; |
0 | 1472 } |
1473 if (!arg.type) | |
1474 arg.type = taa.next; // value type | |
1475 break; | |
1476 } | |
1477 | |
1478 case TY.Tclass: | |
1479 ad = (cast(TypeClass)tab).sym; | |
1480 goto Laggr; | |
1481 | |
1482 case TY.Tstruct: | |
1483 ad = (cast(TypeStruct)tab).sym; | |
1484 goto Laggr; | |
1485 | |
1486 Laggr: | |
135 | 1487 s = search_function(ad, (op == TOKforeach_reverse) ? Id.applyReverse : Id.apply); |
1488 if (s) | |
1489 goto Lapply; // prefer opApply | |
1490 | |
0 | 1491 if (arguments.dim == 1) |
1492 { | |
1493 if (!arg.type) | |
1494 { | |
1495 /* Look for a head() or rear() overload | |
1496 */ | |
1497 Identifier id = (op == TOK.TOKforeach) ? Id.Fhead : Id.Ftoe; | |
135 | 1498 Dsymbol s1 = search_function(ad, id); |
1499 FuncDeclaration fd = s1 ? s1.isFuncDeclaration() : null; | |
0 | 1500 if (!fd) |
1501 { | |
135 | 1502 if (s1 && s1.isTemplateDeclaration()) |
0 | 1503 break; |
1504 goto Lapply; | |
1505 } | |
1506 arg.type = fd.type.nextOf(); | |
1507 } | |
1508 break; | |
1509 } | |
1510 | |
1511 Lapply: | |
1512 { /* Look for an | |
1513 * int opApply(int delegate(ref Type [, ...]) dg); | |
1514 * overload | |
1515 */ | |
1516 if (s) | |
1517 { | |
1518 FuncDeclaration fd = s.isFuncDeclaration(); | |
1519 if (fd) | |
1520 { | |
1521 inferApplyArgTypesX(fd, arguments); | |
1522 break; | |
1523 } | |
1524 static if (false) { | |
1525 TemplateDeclaration td = s.isTemplateDeclaration(); | |
1526 if (td) | |
1527 { | |
1528 inferApplyArgTypesZ(td, arguments); | |
1529 break; | |
1530 } | |
1531 } | |
1532 } | |
1533 break; | |
1534 } | |
1535 | |
1536 case TY.Tdelegate: | |
1537 { | |
1538 if (0 && aggr.op == TOK.TOKdelegate) | |
1539 { | |
1540 DelegateExp de = cast(DelegateExp)aggr; | |
1541 | |
1542 FuncDeclaration fd = de.func.isFuncDeclaration(); | |
1543 if (fd) | |
1544 inferApplyArgTypesX(fd, arguments); | |
1545 } | |
1546 else | |
1547 { | |
1548 inferApplyArgTypesY(cast(TypeFunction)tab.nextOf(), arguments); | |
1549 } | |
1550 break; | |
1551 } | |
1552 | |
1553 default: | |
1554 break; // ignore error, caught later | |
1555 } | |
1556 } | |
1557 | |
1558 struct Param3 | |
1559 { | |
1560 /******************************** | |
1561 * Recursive helper function, | |
1562 * analogous to func.overloadResolveX(). | |
1563 */ | |
1564 | |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
1565 int fp3(void*, FuncDeclaration f) |
0 | 1566 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1567 auto tf = cast(TypeFunction)f.type; |
0 | 1568 if (inferApplyArgTypesY(tf, arguments) == 1) |
1569 return 0; | |
1570 | |
1571 if (arguments.dim == 0) | |
1572 return 1; | |
1573 | |
1574 return 0; | |
1575 } | |
1576 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1577 Parameters arguments; |
0 | 1578 } |
1579 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1580 void inferApplyArgTypesX(FuncDeclaration fstart, Parameters arguments) |
0 | 1581 { |
1582 Param3 p3; | |
1583 p3.arguments = arguments; | |
17
ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents:
16
diff
changeset
|
1584 overloadApply(fstart, &p3.fp3, cast(void*)arguments); |
0 | 1585 } |
1586 | |
1587 /****************************** | |
1588 * Infer arguments from type of function. | |
1589 * Returns: | |
1590 * 0 match for this function | |
1591 * 1 no match for this function | |
1592 */ | |
1593 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1594 int inferApplyArgTypesY(TypeFunction tf, Parameters arguments) |
0 | 1595 { |
1596 size_t nparams; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1597 Parameter p; |
0 | 1598 |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1599 if (Parameter.dim(tf.parameters) != 1) |
0 | 1600 goto Lnomatch; |
1601 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1602 p = Parameter.getNth(tf.parameters, 0); |
0 | 1603 if (p.type.ty != TY.Tdelegate) |
1604 goto Lnomatch; | |
1605 | |
1606 tf = cast(TypeFunction)p.type.nextOf(); | |
1607 assert(tf.ty == TY.Tfunction); | |
1608 | |
1609 /* We now have tf, the type of the delegate. Match it against | |
1610 * the arguments, filling in missing argument types. | |
1611 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1612 nparams = Parameter.dim(tf.parameters); |
0 | 1613 if (nparams == 0 || tf.varargs) |
1614 goto Lnomatch; // not enough parameters | |
1615 if (arguments.dim != nparams) | |
1616 goto Lnomatch; // not enough parameters | |
1617 | |
1618 for (size_t u = 0; u < nparams; u++) | |
1619 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1620 auto arg = arguments[u]; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1621 auto param = Parameter.getNth(tf.parameters, u); |
0 | 1622 if (arg.type) |
1623 { | |
1624 if (!arg.type.equals(param.type)) | |
1625 { | |
1626 /* Cannot resolve argument types. Indicate an | |
1627 * error by setting the number of arguments to 0. | |
1628 */ | |
1629 arguments.dim = 0; | |
1630 goto Lmatch; | |
1631 } | |
1632 continue; | |
1633 } | |
1634 arg.type = param.type; | |
1635 } | |
1636 | |
1637 Lmatch: | |
1638 return 0; | |
1639 | |
1640 Lnomatch: | |
1641 return 1; | |
1642 } | |
1643 | |
1644 /************************************************** | |
1645 * Write expression out to buf, but wrap it | |
1646 * in ( ) if its precedence is less than pr. | |
1647 */ | |
1648 | |
1649 void expToCBuffer(OutBuffer buf, HdrGenState* hgs, Expression e, PREC pr) | |
1650 { | |
1651 //if (precedence[e.op] == 0) e.dump(0); | |
1652 if (precedence[e.op] < pr || | |
1653 /* Despite precedence, we don't allow a<b<c expressions. | |
1654 * They must be parenthesized. | |
1655 */ | |
1656 (pr == PREC.PREC_rel && precedence[e.op] == pr)) | |
1657 { | |
1658 buf.writeByte('('); | |
1659 e.toCBuffer(buf, hgs); | |
1660 buf.writeByte(')'); | |
1661 } | |
1662 else | |
1663 e.toCBuffer(buf, hgs); | |
1664 } | |
1665 | |
1666 /************************************************** | |
1667 * Write out argument list to buf. | |
1668 */ | |
1669 | |
1670 void argsToCBuffer(OutBuffer buf, Expressions arguments, HdrGenState* hgs) | |
1671 { | |
1672 if (arguments) | |
1673 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
1674 foreach (size_t i, Expression arg; arguments) |
0 | 1675 { |
1676 if (arg) | |
1677 { | |
1678 if (i) | |
1679 buf.writeByte(','); | |
1680 expToCBuffer(buf, hgs, arg, PREC.PREC_assign); | |
1681 } | |
1682 } | |
1683 } | |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
1684 } |
53 | 1685 |
1686 ulong getMask(ulong v) | |
1687 { | |
1688 ulong u = 0; | |
1689 if (v >= 0x80) | |
1690 u = 0xFF; | |
1691 while (u < v) | |
1692 u = (u << 1) | 1; | |
1693 return u; | |
64 | 1694 } |
1695 | |
1696 /****************************** | |
1697 * Perform scanForNestedRef() on an array of Expressions. | |
1698 */ | |
1699 | |
1700 void arrayExpressionScanForNestedRef(Scope sc, Expressions a) | |
1701 { | |
1702 //printf("arrayExpressionScanForNestedRef(%p)\n", a); | |
1703 if (a) | |
1704 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
1705 foreach (e; a) |
64 | 1706 { |
1707 if (e) | |
1708 { | |
1709 e.scanForNestedRef(sc); | |
1710 } | |
1711 } | |
1712 } | |
129 | 1713 } |
1714 | |
1715 void realToMangleBuffer(OutBuffer buf, real value) | |
1716 { | |
1717 /* Rely on %A to get portable mangling. | |
1718 * Must munge result to get only identifier characters. | |
1719 * | |
1720 * Possible values from %A => mangled result | |
1721 * NAN => NAN | |
1722 * -INF => NINF | |
1723 * INF => INF | |
1724 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 | |
1725 * 0X1.9P+2 => 19P2 | |
1726 */ | |
1727 | |
1728 if (isnan(value)) | |
1729 buf.writestring("NAN"); // no -NAN bugs | |
1730 else | |
1731 { | |
1732 char buffer[32]; | |
1733 int n = sprintf(buffer.ptr, "%LA", value); | |
1734 assert(n > 0 && n < buffer.sizeof); | |
1735 for (int i = 0; i < n; i++) | |
1736 { char c = buffer[i]; | |
1737 | |
1738 switch (c) | |
1739 { | |
1740 case '-': | |
1741 buf.writeByte('N'); | |
1742 break; | |
1743 | |
1744 case '+': | |
1745 case 'X': | |
1746 case '.': | |
1747 break; | |
1748 | |
1749 case '0': | |
1750 if (i < 2) | |
1751 break; // skip leading 0X | |
1752 default: | |
1753 buf.writeByte(c); | |
1754 break; | |
1755 } | |
1756 } | |
1757 } | |
1758 } | |
1759 | |
1760 /******************************** | |
1761 * Test to see if two reals are the same. | |
1762 * Regard NaN's as equivalent. | |
1763 * Regard +0 and -0 as different. | |
1764 */ | |
1765 | |
1766 int RealEquals(real x1, real x2) | |
1767 { | |
1768 return (isnan(x1) && isnan(x2)) || | |
1769 /* In some cases, the REALPAD bytes get garbage in them, | |
1770 * so be sure and ignore them. | |
1771 */ | |
1772 memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
1773 } |