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