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