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