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