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