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
|
|
42 Initializer syntaxCopy()
|
|
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
|
|
73 Initializer semantic(Scope sc, Type t)
|
|
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
|
|
128 Type inferType(Scope sc)
|
|
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.
|
|
161 */
|
|
162 Expression toExpression()
|
|
163 {
|
|
164 Expression e;
|
|
165
|
|
166 //printf("ArrayInitializer.toExpression(), dim = %d\n", dim);
|
|
167 //static int i; if (++i == 2) halt();
|
|
168
|
|
169 size_t edim;
|
|
170 Type t = null;
|
|
171 if (type)
|
|
172 {
|
|
173 t = type.toBasetype();
|
|
174 switch (t.ty)
|
|
175 {
|
|
176 case Tsarray:
|
|
177 edim = cast(uint)(cast(TypeSArray)t).dim.toInteger();
|
|
178 break;
|
|
179
|
|
180 case Tpointer:
|
|
181 case Tarray:
|
|
182 edim = dim;
|
|
183 break;
|
|
184
|
|
185 default:
|
|
186 assert(0);
|
|
187 }
|
|
188 }
|
|
189 else
|
|
190 {
|
|
191 edim = value.dim;
|
|
192 for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
|
193 {
|
|
194 if (index.data[i])
|
|
195 j = cast(uint)(cast(Expression)index.data[i]).toInteger();
|
|
196 if (j >= edim)
|
|
197 edim = j + 1;
|
|
198 }
|
|
199 }
|
|
200
|
|
201 Expressions elements = new Expressions();
|
|
202 elements.setDim(edim);
|
|
203 for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
|
204 {
|
|
205 if (index.data[i])
|
|
206 j = cast(uint)(cast(Expression)index.data[i]).toInteger();
|
|
207 assert(j < edim);
|
|
208 Initializer iz = cast(Initializer)value.data[i];
|
|
209 if (!iz)
|
|
210 goto Lno;
|
|
211 Expression ex = iz.toExpression();
|
|
212 if (!ex)
|
|
213 {
|
|
214 goto Lno;
|
|
215 }
|
|
216 elements.data[j] = cast(void*)ex;
|
|
217 }
|
|
218
|
|
219 /* Fill in any missing elements with the default initializer
|
|
220 */
|
|
221 {
|
|
222 Expression init = null;
|
|
223 for (size_t i = 0; i < edim; i++)
|
|
224 {
|
|
225 if (!elements.data[i])
|
|
226 {
|
|
227 if (!type)
|
|
228 goto Lno;
|
|
229 if (!init)
|
|
230 init = (cast(TypeNext)t).next.defaultInit(Loc(0));
|
|
231 elements.data[i] = cast(void*)init;
|
|
232 }
|
|
233 }
|
|
234
|
|
235 Expression e2 = new ArrayLiteralExp(loc, elements);
|
|
236 e2.type = type;
|
|
237 return e2;
|
|
238 }
|
|
239
|
|
240 Lno:
|
|
241 delete elements;
|
|
242 error(loc, "array initializers as expressions are not allowed");
|
|
243 return new ErrorExp();
|
|
244 }
|
|
245
|
|
246 Initializer toAssocArrayInitializer()
|
|
247 {
|
|
248 assert(false);
|
|
249 }
|
|
250
|
|
251 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
|
252 {
|
|
253 assert(false);
|
|
254 }
|
|
255
|
|
256 dt_t* toDt()
|
|
257 {
|
|
258 //printf("ArrayInitializer.toDt('%s')\n", toChars());
|
|
259 Type tb = type.toBasetype();
|
|
260 Type tn = tb.nextOf().toBasetype();
|
|
261
|
|
262 scope Array dts = new Array();
|
|
263 uint size;
|
|
264 uint length;
|
|
265 uint i;
|
|
266 dt_t* dt;
|
|
267 dt_t* d;
|
|
268 dt_t** pdtend;
|
|
269
|
|
270 //printf("\tdim = %d\n", dim);
|
|
271 dts.setDim(dim);
|
|
272 dts.zero();
|
|
273
|
|
274 size = cast(uint)tn.size();
|
|
275
|
|
276 length = 0;
|
|
277 for (i = 0; i < index.dim; i++)
|
|
278 {
|
|
279 Expression idx;
|
|
280 Initializer val;
|
|
281
|
|
282 idx = cast(Expression)index.data[i];
|
|
283 if (idx)
|
|
284 length = cast(uint)idx.toInteger();
|
|
285 //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);
|
|
286
|
|
287 assert(length < dim);
|
|
288 val = cast(Initializer)value.data[i];
|
|
289 dt = val.toDt();
|
|
290 if (dts.data[length])
|
|
291 error(loc, "duplicate initializations for index %d", length);
|
|
292 dts.data[length] = cast(void*)dt;
|
|
293 length++;
|
|
294 }
|
|
295
|
|
296 Expression edefault = tb.nextOf().defaultInit(Loc(0));
|
|
297
|
|
298 uint n = 1;
|
|
299 for (Type tbn = tn; tbn.ty == Tsarray; tbn = tbn.nextOf().toBasetype())
|
|
300 {
|
|
301 TypeSArray tsa = cast(TypeSArray)tbn;
|
|
302 n *= tsa.dim.toInteger();
|
|
303 }
|
|
304
|
|
305 d = null;
|
|
306 pdtend = &d;
|
|
307 for (i = 0; i < dim; i++)
|
|
308 {
|
|
309 dt = cast(dt_t*)dts.data[i];
|
|
310 if (dt)
|
|
311 pdtend = dtcat(pdtend, dt);
|
|
312 else
|
|
313 {
|
|
314 for (int j = 0; j < n; j++)
|
|
315 pdtend = edefault.toDt(pdtend);
|
|
316 }
|
|
317 }
|
|
318 switch (tb.ty)
|
|
319 {
|
|
320 case Tsarray:
|
|
321 {
|
|
322 uint tadim;
|
|
323 TypeSArray ta = cast(TypeSArray)tb;
|
|
324
|
|
325 tadim = cast(uint)ta.dim.toInteger();
|
|
326 if (dim < tadim)
|
|
327 {
|
|
328 if (edefault.isBool(false))
|
|
329 // pad out end of array
|
|
330 pdtend = dtnzeros(pdtend, size * (tadim - dim));
|
|
331 else
|
|
332 {
|
|
333 for (i = dim; i < tadim; i++)
|
|
334 {
|
|
335 for (int j = 0; j < n; j++)
|
|
336 pdtend = edefault.toDt(pdtend);
|
|
337 }
|
|
338 }
|
|
339 }
|
|
340 else if (dim > tadim)
|
|
341 {
|
|
342 debug writef("1: ");
|
|
343 error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
|
|
344 }
|
|
345 break;
|
|
346 }
|
|
347
|
|
348 case Tpointer:
|
|
349 case Tarray:
|
|
350 // Create symbol, and then refer to it
|
|
351 Symbol* s = static_sym();
|
|
352 s.Sdt = d;
|
|
353 outdata(s);
|
|
354
|
|
355 d = null;
|
|
356 if (tb.ty == Tarray)
|
|
357 dtdword(&d, dim);
|
|
358 dtxoff(&d, s, 0, TYnptr);
|
|
359 break;
|
|
360
|
|
361 default:
|
|
362 assert(0);
|
|
363 }
|
|
364 return d;
|
|
365 }
|
|
366
|
|
367 dt_t* toDtBit() // for bit arrays
|
|
368 {
|
|
369 assert(false);
|
|
370 }
|
|
371
|
|
372 ArrayInitializer isArrayInitializer() { return this; }
|
|
373 } |