Mercurial > projects > ddmd
annotate dmd/ArrayInitializer.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | e6e542f37b94 |
children | 0c8cc2a10f99 |
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 if (idx) | |
102 { | |
103 idx = idx.semantic(sc); | |
104 idx = idx.optimize(WANTvalue | WANTinterpret); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
105 index[i] = idx; |
0 | 106 length = cast(uint)idx.toInteger(); |
107 } | |
108 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
109 Initializer val = value[i]; |
0 | 110 val = val.semantic(sc, t.nextOf()); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
111 value[i] = val; |
0 | 112 length++; |
113 if (length == 0) | |
114 error(loc, "array dimension overflow"); | |
115 if (length > dim) | |
116 dim = length; | |
117 } | |
118 uint amax = 0x80000000; | |
119 if (cast(uint) (dim * t.nextOf().size()) >= amax) | |
120 error(loc, "array dimension %u exceeds max of %ju", dim, amax / t.nextOf().size()); | |
121 | |
122 return this; | |
123 } | |
124 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
125 int isAssociativeArray() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
126 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
127 for (size_t i = 0; i < value.dim; i++) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
128 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
129 if (index[i]) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
130 return 1; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
131 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
132 return 0; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
133 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
134 |
72 | 135 override Type inferType(Scope sc) |
0 | 136 { |
137 //printf("ArrayInitializer.inferType() %s\n", toChars()); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
138 assert(0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
139 return null; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
140 static if (false) { |
0 | 141 type = Type.terror; |
142 for (size_t i = 0; i < value.dim; i++) | |
143 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
144 if (index[i]) |
79 | 145 goto Laa; |
0 | 146 } |
147 | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
148 foreach (size_t i, Initializer iz; value) |
0 | 149 { |
150 if (iz) | |
151 { | |
152 Type t = iz.inferType(sc); | |
153 if (i == 0) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
154 { /* BUG: This gets the type from the first element. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
155 * Fix to use all the elements to figure out the type. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
156 */ |
0 | 157 t = new TypeSArray(t, new IntegerExp(value.dim)); |
158 t = t.semantic(loc, sc); | |
159 type = t; | |
160 } | |
161 } | |
162 } | |
163 return type; | |
164 | |
79 | 165 Laa: |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
166 /* It's possibly an associative array initializer. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
167 * BUG: inferring type from first member. |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
168 */ |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
169 Initializer iz = value[0]; |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
170 Expression indexinit = index[0]; |
79 | 171 if (iz && indexinit) |
172 { | |
173 Type t = iz.inferType(sc); | |
174 indexinit = indexinit.semantic(sc); | |
175 Type indext = indexinit.type; | |
176 t = new TypeAArray(t, indext); | |
177 type = t.semantic(loc, sc); | |
178 } | |
179 else | |
180 error(loc, "cannot infer type from this array initializer"); | |
181 return type; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
182 } |
0 | 183 } |
184 | |
185 /******************************** | |
186 * If possible, convert array initializer to array literal. | |
73 | 187 * Otherwise return null. |
0 | 188 */ |
72 | 189 override Expression toExpression() |
0 | 190 { |
191 Expression e; | |
192 | |
193 //printf("ArrayInitializer.toExpression(), dim = %d\n", dim); | |
194 //static int i; if (++i == 2) halt(); | |
195 | |
196 size_t edim; | |
197 Type t = null; | |
198 if (type) | |
199 { | |
79 | 200 if (type == Type.terror) |
201 return new ErrorExp(); | |
202 | |
0 | 203 t = type.toBasetype(); |
204 switch (t.ty) | |
205 { | |
206 case Tsarray: | |
207 edim = cast(uint)(cast(TypeSArray)t).dim.toInteger(); | |
208 break; | |
209 | |
210 case Tpointer: | |
211 case Tarray: | |
212 edim = dim; | |
213 break; | |
214 | |
215 default: | |
216 assert(0); | |
217 } | |
218 } | |
219 else | |
220 { | |
221 edim = value.dim; | |
222 for (size_t i = 0, j = 0; i < value.dim; i++, j++) | |
223 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
224 if (index[i]) |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
225 j = cast(uint)(index[i].toInteger()); |
0 | 226 if (j >= edim) |
227 edim = j + 1; | |
228 } | |
229 } | |
230 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
231 auto elements = new Expressions(); |
0 | 232 elements.setDim(edim); |
233 for (size_t i = 0, j = 0; i < value.dim; i++, j++) | |
234 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
235 if (index[i]) |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
236 j = cast(uint)(index[i].toInteger()); |
0 | 237 assert(j < edim); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
238 Initializer iz = value[i]; |
0 | 239 if (!iz) |
240 goto Lno; | |
241 Expression ex = iz.toExpression(); | |
242 if (!ex) | |
243 { | |
244 goto Lno; | |
245 } | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
246 elements[j] = ex; |
0 | 247 } |
248 | |
249 /* Fill in any missing elements with the default initializer | |
250 */ | |
251 { | |
252 Expression init = null; | |
253 for (size_t i = 0; i < edim; i++) | |
254 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
255 if (!elements[i]) |
0 | 256 { |
257 if (!type) | |
258 goto Lno; | |
259 if (!init) | |
260 init = (cast(TypeNext)t).next.defaultInit(Loc(0)); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
261 elements[i] = init; |
0 | 262 } |
263 } | |
264 | |
265 Expression e2 = new ArrayLiteralExp(loc, elements); | |
266 e2.type = type; | |
267 return e2; | |
268 } | |
269 | |
270 Lno: | |
73 | 271 return null; |
0 | 272 } |
273 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
274 Expression toAssocArrayLiteral() |
0 | 275 { |
276 assert(false); | |
277 } | |
278 | |
72 | 279 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 280 { |
281 assert(false); | |
282 } | |
283 | |
72 | 284 override dt_t* toDt() |
0 | 285 { |
286 //printf("ArrayInitializer.toDt('%s')\n", toChars()); | |
287 Type tb = type.toBasetype(); | |
288 Type tn = tb.nextOf().toBasetype(); | |
289 | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
290 scope dts = new Vector!(dt_t*)(); |
0 | 291 uint size; |
292 uint length; | |
293 uint i; | |
294 dt_t* dt; | |
295 dt_t* d; | |
296 dt_t** pdtend; | |
297 | |
298 //printf("\tdim = %d\n", dim); | |
299 dts.setDim(dim); | |
300 dts.zero(); | |
301 | |
302 size = cast(uint)tn.size(); | |
303 | |
304 length = 0; | |
305 for (i = 0; i < index.dim; i++) | |
306 { | |
307 Expression idx; | |
308 Initializer val; | |
309 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
310 idx = index[i]; |
0 | 311 if (idx) |
312 length = cast(uint)idx.toInteger(); | |
313 //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); | |
314 | |
315 assert(length < dim); | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
316 val = value[i]; |
0 | 317 dt = val.toDt(); |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
318 if (dts[length]) |
0 | 319 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
|
320 dts[length] = dt; |
0 | 321 length++; |
322 } | |
323 | |
324 Expression edefault = tb.nextOf().defaultInit(Loc(0)); | |
325 | |
326 uint n = 1; | |
327 for (Type tbn = tn; tbn.ty == Tsarray; tbn = tbn.nextOf().toBasetype()) | |
328 { | |
329 TypeSArray tsa = cast(TypeSArray)tbn; | |
330 n *= tsa.dim.toInteger(); | |
331 } | |
332 | |
333 d = null; | |
334 pdtend = &d; | |
335 for (i = 0; i < dim; i++) | |
336 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
337 dt = dts[i]; |
0 | 338 if (dt) |
339 pdtend = dtcat(pdtend, dt); | |
340 else | |
341 { | |
342 for (int j = 0; j < n; j++) | |
343 pdtend = edefault.toDt(pdtend); | |
344 } | |
345 } | |
346 switch (tb.ty) | |
347 { | |
348 case Tsarray: | |
349 { | |
350 uint tadim; | |
351 TypeSArray ta = cast(TypeSArray)tb; | |
352 | |
353 tadim = cast(uint)ta.dim.toInteger(); | |
354 if (dim < tadim) | |
355 { | |
356 if (edefault.isBool(false)) | |
357 // pad out end of array | |
358 pdtend = dtnzeros(pdtend, size * (tadim - dim)); | |
359 else | |
360 { | |
361 for (i = dim; i < tadim; i++) | |
362 { | |
363 for (int j = 0; j < n; j++) | |
364 pdtend = edefault.toDt(pdtend); | |
365 } | |
366 } | |
367 } | |
368 else if (dim > tadim) | |
369 { | |
370 debug writef("1: "); | |
371 error(loc, "too many initializers, %d, for array[%d]", dim, tadim); | |
372 } | |
373 break; | |
374 } | |
375 | |
376 case Tpointer: | |
377 case Tarray: | |
378 // Create symbol, and then refer to it | |
379 Symbol* s = static_sym(); | |
380 s.Sdt = d; | |
381 outdata(s); | |
382 | |
383 d = null; | |
384 if (tb.ty == Tarray) | |
385 dtdword(&d, dim); | |
386 dtxoff(&d, s, 0, TYnptr); | |
387 break; | |
388 | |
389 default: | |
390 assert(0); | |
391 } | |
392 return d; | |
393 } | |
394 | |
395 dt_t* toDtBit() // for bit arrays | |
396 { | |
397 assert(false); | |
398 } | |
399 | |
72 | 400 override ArrayInitializer isArrayInitializer() { return this; } |
401 } |