Mercurial > projects > ddmd
annotate dmd/ArrayLiteralExp.d @ 123:9e39c7de8438
Make dmd test suite compile
author | korDen |
---|---|
date | Fri, 03 Sep 2010 20:46:58 +0400 |
parents | e28b18c23469 |
children | 60bb0fe4563e |
rev | line source |
---|---|
72 | 1 module dmd.ArrayLiteralExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.backend.elem; | |
6 import dmd.InterState; | |
7 import dmd.MATCH; | |
8 import dmd.Type; | |
9 import dmd.OutBuffer; | |
10 import dmd.Loc; | |
0 | 11 import dmd.WANT; |
72 | 12 import dmd.Scope; |
13 import dmd.InlineCostState; | |
14 import dmd.IRState; | |
15 import dmd.InlineDoState; | |
16 import dmd.HdrGenState; | |
17 import dmd.backend.dt_t; | |
18 import dmd.InlineScanState; | |
123 | 19 import dmd.GlobalExpressions; |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
20 import dmd.Array; |
72 | 21 import dmd.ArrayTypes; |
0 | 22 import dmd.TOK; |
23 import dmd.IntegerExp; | |
24 import dmd.TypeSArray; | |
25 import dmd.TY; | |
26 import dmd.StringExp; | |
27 | |
28 import dmd.expression.Util; | |
29 import dmd.backend.Util; | |
30 import dmd.backend.RTLSYM; | |
72 | 31 import dmd.backend.OPER; |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
63
diff
changeset
|
32 import dmd.backend.Symbol; |
0 | 33 import dmd.backend.TYM; |
72 | 34 import dmd.backend.mTY; |
35 import dmd.codegen.Util; | |
36 | |
0 | 37 class ArrayLiteralExp : Expression |
38 { | |
39 Expressions elements; | |
40 | |
41 this(Loc loc, Expressions elements) | |
72 | 42 { |
0 | 43 super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof); |
44 this.elements = elements; | |
45 } | |
46 | |
47 this(Loc loc, Expression e) | |
48 { | |
49 super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof); | |
50 elements = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
51 elements.push(e); |
0 | 52 } |
53 | |
72 | 54 override Expression syntaxCopy() |
0 | 55 { |
56 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); | |
57 } | |
58 | |
72 | 59 override Expression semantic(Scope sc) |
0 | 60 { |
61 Expression e; | |
62 Type t0 = null; | |
63 | |
64 version (LOGSEMANTIC) { | |
65 printf("ArrayLiteralExp.semantic('%s')\n", toChars()); | |
66 } | |
67 if (type) | |
68 return this; | |
69 | |
70 // Run semantic() on each element | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
71 foreach (ref Expression e; elements) |
0 | 72 { |
73 e = e.semantic(sc); | |
74 assert(e.type); | |
75 } | |
76 | |
77 expandTuples(elements); | |
78 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
79 foreach (size_t i, Expression e; elements) |
0 | 80 { |
81 if (!e.type) | |
82 error("%s has no value", e.toChars()); | |
83 | |
84 e = resolveProperties(sc, e); | |
85 | |
86 ubyte committed = 1; | |
87 if (e.op == TOKstring) | |
88 committed = (cast(StringExp)e).committed; | |
89 | |
90 if (!t0) | |
91 { | |
92 t0 = e.type; | |
93 // Convert any static arrays to dynamic arrays | |
94 if (t0.ty == Tsarray) | |
95 { | |
96 t0 = (cast(TypeSArray)t0).next.arrayOf(); | |
97 e = e.implicitCastTo(sc, t0); | |
98 } | |
99 } | |
100 else | |
101 e = e.implicitCastTo(sc, t0); | |
102 | |
103 if (!committed && e.op == TOKstring) | |
104 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
105 auto se = cast(StringExp)e; |
0 | 106 se.committed = 0; |
107 } | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
108 elements[i] = e; |
0 | 109 } |
110 | |
111 if (!t0) | |
112 t0 = Type.tvoid; | |
113 type = new TypeSArray(t0, new IntegerExp(elements.dim)); | |
114 type = type.semantic(loc, sc); | |
115 return this; | |
116 } | |
117 | |
72 | 118 override bool isBool(bool result) |
0 | 119 { |
120 size_t dim = elements ? elements.dim : 0; | |
121 return result ? (dim != 0) : (dim == 0); | |
122 } | |
123 | |
72 | 124 override elem* toElem(IRState* irs) |
0 | 125 { |
126 elem* e; | |
127 size_t dim; | |
128 | |
129 //printf("ArrayLiteralExp.toElem() %s\n", toChars()); | |
130 if (elements) | |
131 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
132 scope args = new Array(); // ddmd was Expressions |
0 | 133 dim = elements.dim; |
134 args.setDim(dim + 1); // +1 for number of args parameter | |
135 e = el_long(TYint, dim); | |
136 args.data[dim] = cast(void*)e; | |
137 for (size_t i = 0; i < dim; i++) | |
138 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
139 auto el = elements[i]; |
0 | 140 elem* ep = el.toElem(irs); |
141 | |
142 if (tybasic(ep.Ety) == TYstruct || tybasic(ep.Ety) == TYarray) | |
143 { | |
144 ep = el_una(OPstrpar, TYstruct, ep); | |
145 ep.Enumbytes = cast(uint)el.type.size(); | |
146 } | |
147 args.data[dim - (i + 1)] = cast(void *)ep; | |
148 } | |
149 | |
150 /* Because the number of parameters can get very large, produce | |
151 * a balanced binary tree so we don't blow up the stack in | |
152 * the subsequent tree walking code. | |
153 */ | |
154 e = el_params(args.data, dim + 1); | |
155 } | |
156 else | |
157 { | |
158 dim = 0; | |
159 e = el_long(TYint, 0); | |
160 } | |
161 Type tb = type.toBasetype(); | |
162 static if (true) { | |
163 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
164 | |
165 // call _d_arrayliteralT(ti, dim, ...) | |
166 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e); | |
167 } else { | |
168 e = el_param(e, el_long(TYint, tb.next.size())); | |
169 | |
170 // call _d_arrayliteral(size, dim, ...) | |
171 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e); | |
172 } | |
173 if (tb.ty == Tarray) | |
174 { | |
175 e = el_pair(TYullong, el_long(TYint, dim), e); | |
176 } | |
177 else if (tb.ty == Tpointer) | |
178 { | |
179 } | |
180 else | |
181 { | |
182 e = el_una(OPind,TYstruct,e); | |
183 e.Enumbytes = cast(uint)type.size(); | |
184 } | |
185 | |
186 el_setLoc(e,loc); | |
187 return e; | |
188 } | |
189 | |
72 | 190 override bool checkSideEffect(int flag) |
0 | 191 { |
192 bool f = false; | |
193 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
194 foreach (e; elements) |
0 | 195 { |
196 f |= e.checkSideEffect(2); | |
197 } | |
198 if (flag == 0 && f == false) | |
199 Expression.checkSideEffect(0); | |
200 | |
201 return f; | |
202 } | |
203 | |
72 | 204 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 205 { |
206 buf.writeByte('['); | |
207 argsToCBuffer(buf, elements, hgs); | |
208 buf.writeByte(']'); | |
209 } | |
210 | |
72 | 211 override void toMangleBuffer(OutBuffer buf) |
0 | 212 { |
213 size_t dim = elements ? elements.dim : 0; | |
214 buf.printf("A%u", dim); | |
215 for (size_t i = 0; i < dim; i++) | |
216 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
217 auto e = elements[i]; |
0 | 218 e.toMangleBuffer(buf); |
219 } | |
220 } | |
221 | |
72 | 222 override void scanForNestedRef(Scope sc) |
0 | 223 { |
224 assert(false); | |
225 } | |
226 | |
72 | 227 override Expression optimize(int result) |
0 | 228 { |
229 if (elements) | |
230 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
231 foreach (ref Expression e; elements) |
0 | 232 { |
233 e = e.optimize(WANTvalue | (result & WANTinterpret)); | |
234 } | |
235 } | |
236 | |
237 return this; | |
238 } | |
239 | |
72 | 240 override Expression interpret(InterState istate) |
0 | 241 { |
123 | 242 Expressions expsx = null; |
243 | |
244 version (LOG) { | |
245 printf("ArrayLiteralExp.interpret() %.*s\n", toChars()); | |
246 } | |
247 if (elements) | |
248 { | |
249 foreach (size_t i, Expression e; elements) | |
250 { | |
251 Expression ex; | |
252 | |
253 ex = e.interpret(istate); | |
254 if (ex is EXP_CANT_INTERPRET) | |
255 { | |
256 delete expsx; | |
257 return EXP_CANT_INTERPRET; | |
258 } | |
259 | |
260 /* If any changes, do Copy On Write | |
261 */ | |
262 if (ex != e) | |
263 { | |
264 if (!expsx) | |
265 { | |
266 expsx = new Expressions(); | |
267 expsx.setDim(elements.dim); | |
268 for (size_t j = 0; j < elements.dim; j++) | |
269 { | |
270 expsx[j] = elements[j]; | |
271 } | |
272 } | |
273 expsx[i] = ex; | |
274 } | |
275 } | |
276 } | |
277 if (elements && expsx) | |
278 { | |
279 expandTuples(expsx); | |
280 if (expsx.dim != elements.dim) | |
281 { | |
282 delete expsx; | |
283 return EXP_CANT_INTERPRET; | |
284 } | |
285 | |
286 ArrayLiteralExp ae = new ArrayLiteralExp(loc, expsx); | |
287 ae.type = type; | |
288 | |
289 return ae; | |
290 } | |
291 return this; | |
0 | 292 } |
293 | |
72 | 294 override MATCH implicitConvTo(Type t) |
0 | 295 { |
296 MATCH result = MATCHexact; | |
297 | |
298 static if (false) { | |
299 printf("ArrayLiteralExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
300 toChars(), type.toChars(), t.toChars()); | |
301 } | |
302 Type typeb = type.toBasetype(); | |
303 Type tb = t.toBasetype(); | |
304 if ((tb.ty == Tarray || tb.ty == Tsarray) && | |
305 (typeb.ty == Tarray || typeb.ty == Tsarray)) | |
306 { | |
307 if (tb.ty == Tsarray) | |
308 { | |
309 TypeSArray tsa = cast(TypeSArray)tb; | |
310 if (elements.dim != tsa.dim.toInteger()) | |
311 result = MATCHnomatch; | |
312 } | |
313 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
314 foreach (e; elements) |
0 | 315 { |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
316 auto m = cast(MATCH)e.implicitConvTo(tb.nextOf()); |
0 | 317 if (m < result) |
318 result = m; // remember worst match | |
319 if (result == MATCHnomatch) | |
320 break; // no need to check for worse | |
321 } | |
322 return result; | |
323 } | |
324 else | |
325 return Expression.implicitConvTo(t); | |
326 } | |
327 | |
72 | 328 override Expression castTo(Scope sc, Type t) |
0 | 329 { |
330 static if (false) { | |
331 printf("ArrayLiteralExp.castTo(this=%s, type=%s, => %s)\n", | |
332 toChars(), type.toChars(), t.toChars()); | |
333 } | |
334 if (type == t) | |
335 return this; | |
336 ArrayLiteralExp e = this; | |
337 Type typeb = type.toBasetype(); | |
338 Type tb = t.toBasetype(); | |
339 if ((tb.ty == Tarray || tb.ty == Tsarray) && | |
340 (typeb.ty == Tarray || typeb.ty == Tsarray) && | |
341 // Not trying to convert non-void[] to void[] | |
342 !(tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)) | |
343 { | |
344 if (tb.ty == Tsarray) | |
345 { | |
346 TypeSArray tsa = cast(TypeSArray)tb; | |
347 if (elements.dim != tsa.dim.toInteger()) | |
348 goto L1; | |
349 } | |
350 | |
351 e = cast(ArrayLiteralExp)copy(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
352 e.elements = elements.copy(); |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
353 foreach (size_t i, Expression ex; elements) |
0 | 354 { |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
355 e.elements[i] = ex.castTo(sc, tb.nextOf()); |
0 | 356 } |
357 e.type = t; | |
358 return e; | |
359 } | |
360 if (tb.ty == Tpointer && typeb.ty == Tsarray) | |
361 { | |
362 Type tp = typeb.nextOf().pointerTo(); | |
363 if (!tp.equals(e.type)) | |
364 { | |
365 e = cast(ArrayLiteralExp)copy(); | |
366 e.type = tp; | |
367 } | |
368 } | |
369 L1: | |
370 return e.Expression.castTo(sc, t); | |
371 } | |
372 | |
72 | 373 override dt_t** toDt(dt_t** pdt) |
0 | 374 { |
72 | 375 //printf("ArrayLiteralExp.toDt() '%s', type = %s\n", toChars(), type.toChars()); |
376 | |
377 dt_t *d; | |
378 dt_t **pdtend; | |
379 | |
380 d = null; | |
381 pdtend = &d; | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
382 foreach (e; elements) |
72 | 383 { |
384 pdtend = e.toDt(pdtend); | |
385 } | |
386 Type t = type.toBasetype(); | |
387 | |
388 switch (t.ty) | |
389 { | |
390 case Tsarray: | |
391 pdt = dtcat(pdt, d); | |
392 break; | |
393 | |
394 case Tpointer: | |
395 case Tarray: | |
396 if (t.ty == Tarray) | |
397 dtdword(pdt, elements.dim); | |
398 if (d) | |
399 { | |
400 // Create symbol, and then refer to it | |
401 Symbol* s; | |
402 s = static_sym(); | |
403 s.Sdt = d; | |
404 outdata(s); | |
405 | |
406 dtxoff(pdt, s, 0, TYnptr); | |
407 } | |
408 else | |
409 dtdword(pdt, 0); | |
410 | |
411 break; | |
412 | |
413 default: | |
414 assert(0); | |
415 } | |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
63
diff
changeset
|
416 return pdt; |
0 | 417 } |
418 | |
419 version (DMDV2) { | |
72 | 420 override bool canThrow() |
0 | 421 { |
422 return 1; // because it can fail allocating memory | |
423 } | |
424 } | |
72 | 425 override int inlineCost(InlineCostState* ics) |
0 | 426 { |
427 return 1 + arrayInlineCost(ics, elements); | |
428 } | |
429 | |
72 | 430 override Expression doInline(InlineDoState ids) |
0 | 431 { |
432 ArrayLiteralExp ce = cast(ArrayLiteralExp)copy(); | |
433 ce.elements = arrayExpressiondoInline(elements, ids); | |
434 return ce; | |
435 } | |
436 | |
72 | 437 override Expression inlineScan(InlineScanState* iss) |
0 | 438 { |
439 Expression e = this; | |
440 | |
441 //printf("ArrayLiteralExp.inlineScan()\n"); | |
442 arrayInlineScan(iss, elements); | |
443 | |
444 return e; | |
445 } | |
446 } | |
447 |