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