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