Mercurial > projects > ddmd
annotate dmd/ArrayInitializer.d @ 128:e6e542f37b94
Some more Array -> Vector conversions
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Sat, 04 Sep 2010 01:33:05 +0100 |
parents | 9ee9b55452cb |
children | 60bb0fe4563e |
rev | line source |
---|---|
0 | 1 module dmd.ArrayInitializer; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.ArrayTypes; |
5 import dmd.Type; | |
79 | 6 import dmd.TypeAArray; |
0 | 7 import dmd.TypeNext; |
8 import dmd.Array; | |
9 import dmd.Loc; | |
10 import dmd.Initializer; | |
11 import dmd.WANT; | |
12 import dmd.Util; | |
13 import dmd.TY; | |
14 import dmd.TypeSArray; | |
15 import dmd.IntegerExp; | |
16 import dmd.Expression; | |
17 import dmd.ArrayLiteralExp; | |
18 import dmd.Scope; | |
19 import dmd.ErrorExp; | |
20 import dmd.OutBuffer; | |
21 import dmd.HdrGenState; | |
22 | |
23 import dmd.backend.dt_t; | |
24 import dmd.backend.Util; | |
25 import dmd.codegen.Util; | |
26 import dmd.backend.TYM; | |
27 import dmd.backend.Symbol; | |
28 | |
29 class ArrayInitializer : Initializer | |
30 { | |
31 Expressions index; // indices | |
32 Initializers value; // of Initializer *'s | |
33 uint dim = 0; // length of array being initialized | |
34 Type type = null; // type that array will be used to initialize | |
35 int sem = 0; // !=0 if semantic() is run | |
36 | |
37 this(Loc loc) | |
38 { | |
39 super(loc); | |
40 index = new Expressions(); | |
41 value = new Initializers(); | |
42 } | |
43 | |
72 | 44 override Initializer syntaxCopy() |
0 | 45 { |
46 //printf("ArrayInitializer.syntaxCopy()\n"); | |
47 | |
48 ArrayInitializer ai = new ArrayInitializer(loc); | |
49 | |
50 assert(index.dim == value.dim); | |
51 ai.index.setDim(index.dim); | |
52 ai.value.setDim(value.dim); | |
53 for (int i = 0; i < ai.value.dim; i++) | |
54 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
55 Expression e = index[i]; |
0 | 56 if (e) |
57 e = e.syntaxCopy(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
58 ai.index[i] = e; |
0 | 59 |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
60 auto init = value[i]; |
0 | 61 init = init.syntaxCopy(); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
62 ai.value[i] = init; |
0 | 63 } |
64 return ai; | |
65 } | |
66 | |
67 void addInit(Expression index, Initializer value) | |
68 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
69 this.index.push(index); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
70 this.value.push(value); |
0 | 71 dim = 0; |
72 type = null; | |
73 } | |
74 | |
72 | 75 override Initializer semantic(Scope sc, Type t) |
0 | 76 { |
77 uint length; | |
78 | |
79 //printf("ArrayInitializer.semantic(%s)\n", t.toChars()); | |
80 if (sem) // if semantic() already run | |
81 return this; | |
82 | |
83 sem = 1; | |
84 type = t; | |
85 t = t.toBasetype(); | |
86 switch (t.ty) | |
87 { | |
88 case Tpointer: | |
89 case Tsarray: | |
90 case Tarray: | |
91 break; | |
92 | |
93 default: | |
94 error(loc, "cannot use array to initialize %s", type.toChars()); | |
95 return this; | |
96 } | |
97 | |
98 length = 0; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
99 foreach (size_t i, Expression idx; index) |
0 | 100 { |
101 Initializer val; | |
102 | |
103 if (idx) | |
104 { | |
105 idx = idx.semantic(sc); | |
106 idx = idx.optimize(WANTvalue | WANTinterpret); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
107 index[i] = idx; |
0 | 108 length = cast(uint)idx.toInteger(); |
109 } | |
110 | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
111 val = value[i]; |
0 | 112 val = val.semantic(sc, t.nextOf()); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
113 value[i] = val; |
0 | 114 length++; |
115 if (length == 0) | |
116 error(loc, "array dimension overflow"); | |
117 if (length > dim) | |
118 dim = length; | |
119 } | |
120 uint amax = 0x80000000; | |
121 if (cast(uint) (dim * t.nextOf().size()) >= amax) | |
122 error(loc, "array dimension %u exceeds max of %ju", dim, amax / t.nextOf().size()); | |
123 | |
124 return this; | |
125 } | |
126 | |
72 | 127 override Type inferType(Scope sc) |
0 | 128 { |
129 //printf("ArrayInitializer.inferType() %s\n", toChars()); | |
130 type = Type.terror; | |
131 for (size_t i = 0; i < value.dim; i++) | |
132 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
133 if (index[i]) |
79 | 134 goto Laa; |
0 | 135 } |
136 | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
137 foreach (size_t i, Initializer iz; value) |
0 | 138 { |
139 if (iz) | |
140 { | |
141 Type t = iz.inferType(sc); | |
142 if (i == 0) | |
143 { | |
144 t = new TypeSArray(t, new IntegerExp(value.dim)); | |
145 t = t.semantic(loc, sc); | |
146 type = t; | |
147 } | |
148 } | |
149 } | |
150 return type; | |
151 | |
79 | 152 Laa: |
153 /* It's possibly an associative array initializer | |
154 */ | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
155 Initializer iz = value[0]; |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
156 Expression indexinit = index[0]; |
79 | 157 if (iz && indexinit) |
158 { | |
159 Type t = iz.inferType(sc); | |
160 indexinit = indexinit.semantic(sc); | |
161 Type indext = indexinit.type; | |
162 t = new TypeAArray(t, indext); | |
163 type = t.semantic(loc, sc); | |
164 } | |
165 else | |
166 error(loc, "cannot infer type from this array initializer"); | |
167 return type; | |
0 | 168 } |
169 | |
170 /******************************** | |
171 * If possible, convert array initializer to array literal. | |
73 | 172 * Otherwise return null. |
0 | 173 */ |
72 | 174 override Expression toExpression() |
0 | 175 { |
176 Expression e; | |
177 | |
178 //printf("ArrayInitializer.toExpression(), dim = %d\n", dim); | |
179 //static int i; if (++i == 2) halt(); | |
180 | |
181 size_t edim; | |
182 Type t = null; | |
183 if (type) | |
184 { | |
79 | 185 if (type == Type.terror) |
186 return new ErrorExp(); | |
187 | |
0 | 188 t = type.toBasetype(); |
189 switch (t.ty) | |
190 { | |
191 case Tsarray: | |
192 edim = cast(uint)(cast(TypeSArray)t).dim.toInteger(); | |
193 break; | |
194 | |
195 case Tpointer: | |
196 case Tarray: | |
197 edim = dim; | |
198 break; | |
199 | |
200 default: | |
201 assert(0); | |
202 } | |
203 } | |
204 else | |
205 { | |
206 edim = value.dim; | |
207 for (size_t i = 0, j = 0; i < value.dim; i++, j++) | |
208 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
209 if (index[i]) |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
210 j = cast(uint)(index[i].toInteger()); |
0 | 211 if (j >= edim) |
212 edim = j + 1; | |
213 } | |
214 } | |
215 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
216 auto elements = new Expressions(); |
0 | 217 elements.setDim(edim); |
218 for (size_t i = 0, j = 0; i < value.dim; i++, j++) | |
219 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
220 if (index[i]) |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
221 j = cast(uint)(index[i].toInteger()); |
0 | 222 assert(j < edim); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
223 Initializer iz = value[i]; |
0 | 224 if (!iz) |
225 goto Lno; | |
226 Expression ex = iz.toExpression(); | |
227 if (!ex) | |
228 { | |
229 goto Lno; | |
230 } | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
231 elements[j] = ex; |
0 | 232 } |
233 | |
234 /* Fill in any missing elements with the default initializer | |
235 */ | |
236 { | |
237 Expression init = null; | |
238 for (size_t i = 0; i < edim; i++) | |
239 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
240 if (!elements[i]) |
0 | 241 { |
242 if (!type) | |
243 goto Lno; | |
244 if (!init) | |
245 init = (cast(TypeNext)t).next.defaultInit(Loc(0)); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
246 elements[i] = init; |
0 | 247 } |
248 } | |
249 | |
250 Expression e2 = new ArrayLiteralExp(loc, elements); | |
251 e2.type = type; | |
252 return e2; | |
253 } | |
254 | |
255 Lno: | |
73 | 256 return null; |
0 | 257 } |
258 | |
259 Initializer toAssocArrayInitializer() | |
260 { | |
261 assert(false); | |
262 } | |
263 | |
72 | 264 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 265 { |
266 assert(false); | |
267 } | |
268 | |
72 | 269 override dt_t* toDt() |
0 | 270 { |
271 //printf("ArrayInitializer.toDt('%s')\n", toChars()); | |
272 Type tb = type.toBasetype(); | |
273 Type tn = tb.nextOf().toBasetype(); | |
274 | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
275 scope dts = new Vector!(dt_t*)(); |
0 | 276 uint size; |
277 uint length; | |
278 uint i; | |
279 dt_t* dt; | |
280 dt_t* d; | |
281 dt_t** pdtend; | |
282 | |
283 //printf("\tdim = %d\n", dim); | |
284 dts.setDim(dim); | |
285 dts.zero(); | |
286 | |
287 size = cast(uint)tn.size(); | |
288 | |
289 length = 0; | |
290 for (i = 0; i < index.dim; i++) | |
291 { | |
292 Expression idx; | |
293 Initializer val; | |
294 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
295 idx = index[i]; |
0 | 296 if (idx) |
297 length = cast(uint)idx.toInteger(); | |
298 //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); | |
299 | |
300 assert(length < dim); | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
301 val = value[i]; |
0 | 302 dt = val.toDt(); |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
303 if (dts[length]) |
0 | 304 error(loc, "duplicate initializations for index %d", length); |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
305 dts[length] = dt; |
0 | 306 length++; |
307 } | |
308 | |
309 Expression edefault = tb.nextOf().defaultInit(Loc(0)); | |
310 | |
311 uint n = 1; | |
312 for (Type tbn = tn; tbn.ty == Tsarray; tbn = tbn.nextOf().toBasetype()) | |
313 { | |
314 TypeSArray tsa = cast(TypeSArray)tbn; | |
315 n *= tsa.dim.toInteger(); | |
316 } | |
317 | |
318 d = null; | |
319 pdtend = &d; | |
320 for (i = 0; i < dim; i++) | |
321 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
322 dt = dts[i]; |
0 | 323 if (dt) |
324 pdtend = dtcat(pdtend, dt); | |
325 else | |
326 { | |
327 for (int j = 0; j < n; j++) | |
328 pdtend = edefault.toDt(pdtend); | |
329 } | |
330 } | |
331 switch (tb.ty) | |
332 { | |
333 case Tsarray: | |
334 { | |
335 uint tadim; | |
336 TypeSArray ta = cast(TypeSArray)tb; | |
337 | |
338 tadim = cast(uint)ta.dim.toInteger(); | |
339 if (dim < tadim) | |
340 { | |
341 if (edefault.isBool(false)) | |
342 // pad out end of array | |
343 pdtend = dtnzeros(pdtend, size * (tadim - dim)); | |
344 else | |
345 { | |
346 for (i = dim; i < tadim; i++) | |
347 { | |
348 for (int j = 0; j < n; j++) | |
349 pdtend = edefault.toDt(pdtend); | |
350 } | |
351 } | |
352 } | |
353 else if (dim > tadim) | |
354 { | |
355 debug writef("1: "); | |
356 error(loc, "too many initializers, %d, for array[%d]", dim, tadim); | |
357 } | |
358 break; | |
359 } | |
360 | |
361 case Tpointer: | |
362 case Tarray: | |
363 // Create symbol, and then refer to it | |
364 Symbol* s = static_sym(); | |
365 s.Sdt = d; | |
366 outdata(s); | |
367 | |
368 d = null; | |
369 if (tb.ty == Tarray) | |
370 dtdword(&d, dim); | |
371 dtxoff(&d, s, 0, TYnptr); | |
372 break; | |
373 | |
374 default: | |
375 assert(0); | |
376 } | |
377 return d; | |
378 } | |
379 | |
380 dt_t* toDtBit() // for bit arrays | |
381 { | |
382 assert(false); | |
383 } | |
384 | |
72 | 385 override ArrayInitializer isArrayInitializer() { return this; } |
386 } |