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