Mercurial > projects > ddmd
annotate dmd/StructInitializer.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 | af1bebfd96a4 |
children | b0d41ff5e0df |
rev | line source |
---|---|
0 | 1 module dmd.StructInitializer; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Initializer; |
2 | 5 import dmd.TOK; |
67 | 6 import dmd.TypeSArray; |
2 | 7 import dmd.FuncLiteralDeclaration; |
8 import dmd.TypeFunction; | |
56 | 9 import dmd.StructDeclaration; |
10 import dmd.StructLiteralExp; | |
0 | 11 import dmd.ArrayTypes; |
12 import dmd.Array; | |
13 import dmd.Loc; | |
14 import dmd.Type; | |
15 import dmd.Scope; | |
16 import dmd.Identifier; | |
2 | 17 import dmd.CompoundStatement; |
0 | 18 import dmd.AggregateDeclaration; |
19 import dmd.OutBuffer; | |
20 import dmd.HdrGenState; | |
21 import dmd.Expression; | |
2 | 22 import dmd.TypeStruct; |
23 import dmd.TY; | |
24 import dmd.VarDeclaration; | |
25 import dmd.Dsymbol; | |
26 import dmd.Util; | |
27 import dmd.ExpInitializer; | |
28 import dmd.FuncExp; | |
29 import dmd.LINK; | |
0 | 30 |
31 import dmd.backend.dt_t; | |
67 | 32 import dmd.backend.Util; |
0 | 33 |
34 class StructInitializer : Initializer | |
35 { | |
36 Identifiers field; // of Identifier *'s | |
37 Initializers value; // parallel array of Initializer *'s | |
38 | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
39 VarDeclarations vars; // parallel array of VarDeclaration *'s |
0 | 40 AggregateDeclaration ad; // which aggregate this is for |
41 | |
42 this(Loc loc) | |
43 { | |
178 | 44 register(); |
0 | 45 super(loc); |
2 | 46 ad = null; |
47 | |
48 field = new Identifiers(); | |
49 value = new Initializers(); | |
51 | 50 |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
51 vars = new VarDeclarations(); |
0 | 52 } |
53 | |
72 | 54 override Initializer syntaxCopy() |
0 | 55 { |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
56 auto ai = new StructInitializer(loc); |
2 | 57 |
58 assert(field.dim == value.dim); | |
59 ai.field.setDim(field.dim); | |
60 ai.value.setDim(value.dim); | |
61 for (int i = 0; i < field.dim; i++) | |
62 { | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
63 ai.field[i] = field[i]; |
2 | 64 |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
65 auto init = value[i]; |
2 | 66 init = init.syntaxCopy(); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
67 ai.value[i] = init; |
2 | 68 } |
69 | |
70 return ai; | |
0 | 71 } |
72 | |
73 void addInit(Identifier field, Initializer value) | |
74 { | |
2 | 75 //printf("StructInitializer.addInit(field = %p, value = %p)\n", field, value); |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
76 this.field.push(field); |
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
77 this.value.push(value); |
0 | 78 } |
79 | |
72 | 80 override Initializer semantic(Scope sc, Type t) |
0 | 81 { |
2 | 82 int errors = 0; |
83 | |
84 //printf("StructInitializer.semantic(t = %s) %s\n", t.toChars(), toChars()); | |
85 vars.setDim(field.dim); | |
86 t = t.toBasetype(); | |
87 if (t.ty == Tstruct) | |
88 { | |
89 uint fieldi = 0; | |
90 | |
135 | 91 auto ts = cast(TypeStruct)t; |
2 | 92 ad = ts.sym; |
135 | 93 if (ad.ctor) |
94 error("%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", | |
95 ad.kind(), ad.toChars(), ad.toChars()); | |
96 for (size_t i = 0; i < field.dim; i++) | |
2 | 97 { |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
98 Identifier id = field[i]; |
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
99 Initializer val = value[i]; |
2 | 100 Dsymbol s; |
101 VarDeclaration v; | |
102 | |
103 if (id is null) | |
104 { | |
105 if (fieldi >= ad.fields.dim) | |
106 { | |
107 error(loc, "too many initializers for %s", ad.toChars()); | |
108 field.remove(i); | |
109 i--; | |
110 continue; | |
111 } | |
112 else | |
113 { | |
79 | 114 s = ad.fields[fieldi]; |
2 | 115 } |
116 } | |
117 else | |
118 { | |
119 //s = ad.symtab.lookup(id); | |
120 s = ad.search(loc, id, 0); | |
121 if (!s) | |
122 { | |
123 error(loc, "'%s' is not a member of '%s'", id.toChars(), t.toChars()); | |
124 continue; | |
125 } | |
126 | |
127 // Find out which field index it is | |
128 for (fieldi = 0; 1; fieldi++) | |
129 { | |
130 if (fieldi >= ad.fields.dim) | |
131 { | |
132 s.error("is not a per-instance initializable field"); | |
133 break; | |
134 } | |
79 | 135 if (s == ad.fields[fieldi]) |
2 | 136 break; |
137 } | |
138 } | |
139 if (s && (v = s.isVarDeclaration()) !is null) | |
140 { | |
141 val = val.semantic(sc, v.type); | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
142 value[i] = val; |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
143 vars[i] = v; |
2 | 144 } |
145 else | |
146 { | |
147 error(loc, "%s is not a field of %s", id ? id.toChars() : s.toChars(), ad.toChars()); | |
148 errors = 1; | |
149 } | |
150 fieldi++; | |
151 } | |
152 } | |
153 else if (t.ty == Tdelegate && value.dim == 0) | |
154 { | |
155 /* Rewrite as empty delegate literal { } | |
156 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
128
diff
changeset
|
157 auto arguments = new Parameters; |
2 | 158 Type tf = new TypeFunction(arguments, null, 0, LINK.LINKd); |
159 FuncLiteralDeclaration fd = new FuncLiteralDeclaration(loc, Loc(0), tf, TOK.TOKdelegate, null); | |
160 fd.fbody = new CompoundStatement(loc, new Statements()); | |
161 fd.endloc = loc; | |
162 Expression e = new FuncExp(loc, fd); | |
163 ExpInitializer ie = new ExpInitializer(loc, e); | |
164 return ie.semantic(sc, t); | |
165 } | |
166 else | |
167 { | |
168 error(loc, "a struct is not a valid initializer for a %s", t.toChars()); | |
169 errors = 1; | |
170 } | |
171 if (errors) | |
172 { | |
173 field.setDim(0); | |
174 value.setDim(0); | |
175 vars.setDim(0); | |
176 } | |
177 return this; | |
0 | 178 } |
179 | |
56 | 180 /*************************************** |
181 * This works by transforming a struct initializer into | |
182 * a struct literal. In the future, the two should be the | |
183 * same thing. | |
184 */ | |
72 | 185 override Expression toExpression() |
0 | 186 { |
56 | 187 Expression e; |
188 | |
189 //printf("StructInitializer.toExpression() %s\n", toChars()); | |
190 if (!ad) // if fwd referenced | |
191 { | |
192 return null; | |
193 } | |
194 StructDeclaration sd = ad.isStructDeclaration(); | |
195 if (!sd) | |
196 return null; | |
197 Expressions elements = new Expressions(); | |
198 for (size_t i = 0; i < value.dim; i++) | |
199 { | |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
200 if (field[i]) |
56 | 201 goto Lno; |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
202 Initializer iz = value[i]; |
56 | 203 if (!iz) |
204 goto Lno; | |
205 Expression ex = iz.toExpression(); | |
206 if (!ex) | |
207 goto Lno; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
208 elements.push(ex); |
56 | 209 } |
210 e = new StructLiteralExp(loc, sd, elements); | |
211 e.type = sd.type; | |
212 return e; | |
213 | |
214 Lno: | |
215 delete elements; | |
216 //error(loc, "struct initializers as expressions are not allowed"); | |
217 return null; | |
0 | 218 } |
219 | |
72 | 220 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 221 { |
222 assert(false); | |
223 } | |
224 | |
72 | 225 override dt_t* toDt() |
0 | 226 { |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
227 scope dts = new Vector!(dt_t*); |
67 | 228 uint i; |
229 uint j; | |
230 dt_t* dt; | |
231 dt_t* d; | |
232 dt_t** pdtend; | |
233 uint offset; | |
234 | |
235 //printf("StructInitializer.toDt('%s')\n", toChars()); | |
236 dts.setDim(ad.fields.dim); | |
237 dts.zero(); | |
238 | |
239 for (i = 0; i < vars.dim; i++) | |
240 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
241 VarDeclaration v = vars[i]; |
127
9ee9b55452cb
Identifiers, Initializers -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
242 Initializer val = value[i]; |
67 | 243 |
244 //printf("vars[%d] = %s\n", i, v.toChars()); | |
245 | |
246 for (j = 0; 1; j++) | |
247 { | |
248 assert(j < dts.dim); | |
79 | 249 //printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad.fields[j]).toChars()); |
250 if (cast(VarDeclaration)ad.fields[j] == v) // TODO: check if 'is' needs to be used here | |
67 | 251 { |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
252 if (dts[j]) |
67 | 253 error(loc, "field %s of %s already initialized", v.toChars(), ad.toChars()); |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
254 dts[j] = val.toDt(); |
67 | 255 break; |
256 } | |
257 } | |
258 } | |
259 | |
260 dt = null; | |
261 pdtend = &dt; | |
262 offset = 0; | |
263 for (j = 0; j < dts.dim; j++) | |
264 { | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
265 VarDeclaration v = ad.fields[j]; |
67 | 266 |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
267 d = dts[j]; |
67 | 268 if (!d) |
269 { | |
270 // An instance specific initializer was not provided. | |
271 // Look to see if there's a default initializer from the | |
272 // struct definition | |
273 if (v.init) | |
274 { | |
275 d = v.init.toDt(); | |
276 } | |
277 else if (v.offset >= offset) | |
278 { | |
279 uint k; | |
280 uint offset2 = v.offset + cast(uint)v.type.size(); | |
281 // Make sure this field does not overlap any explicitly | |
282 // initialized field. | |
283 for (k = j + 1; 1; k++) | |
284 { | |
285 if (k == dts.dim) // didn't find any overlap | |
286 { | |
287 v.type.toDt(&d); | |
288 break; | |
289 } | |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
290 VarDeclaration v2 = ad.fields[k]; |
67 | 291 |
128
e6e542f37b94
Some more Array -> Vector conversions
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
127
diff
changeset
|
292 if (v2.offset < offset2 && dts[k]) |
67 | 293 break; // overlap |
294 } | |
295 } | |
296 } | |
297 if (d) | |
298 { | |
299 if (v.offset < offset) | |
300 error(loc, "duplicate union initialization for %s", v.toChars()); | |
301 else | |
302 { | |
303 uint sz = dt_size(d); | |
304 uint vsz = cast(uint)v.type.size(); | |
305 uint voffset = v.offset; | |
306 | |
307 uint dim = 1; | |
308 for (Type vt = v.type.toBasetype(); | |
309 vt.ty == Tsarray; | |
310 vt = vt.nextOf().toBasetype()) | |
311 { | |
312 TypeSArray tsa = cast(TypeSArray)vt; | |
313 dim *= tsa.dim.toInteger(); | |
314 } | |
315 assert(sz == vsz || sz * dim <= vsz); | |
316 | |
317 for (size_t k = 0; k < dim; k++) | |
318 { | |
319 if (offset < voffset) | |
320 pdtend = dtnzeros(pdtend, voffset - offset); | |
321 if (!d) | |
322 { | |
323 if (v.init) | |
324 d = v.init.toDt(); | |
325 else | |
326 v.type.toDt(&d); | |
327 } | |
328 pdtend = dtcat(pdtend, d); | |
329 d = null; | |
330 offset = voffset + sz; | |
331 voffset += vsz / dim; | |
332 if (sz == vsz) | |
333 break; | |
334 } | |
335 } | |
336 } | |
337 } | |
338 | |
339 if (offset < ad.structsize) | |
340 dtnzeros(pdtend, ad.structsize - offset); | |
341 | |
342 return dt; | |
0 | 343 } |
344 | |
72 | 345 override StructInitializer isStructInitializer() { return this; } |
346 } |