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