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