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