Mercurial > projects > ddmd
annotate dmd/AssocArrayLiteralExp.d @ 109:ceda59b4d255
expression.c changes, now only ddoc should be left
author | Trass3r |
---|---|
date | Tue, 31 Aug 2010 22:08:52 +0200 |
parents | 6da99741178e |
children | e28b18c23469 |
rev | line source |
---|---|
72 | 1 module dmd.AssocArrayLiteralExp; |
2 | |
3 import dmd.Expression; | |
4 import dmd.GlobalExpressions; | |
5 import dmd.WANT; | |
6 import dmd.expression.Equal; | |
7 import dmd.backend.elem; | |
8 import dmd.InterState; | |
9 import dmd.MATCH; | |
10 import dmd.Type; | |
11 import dmd.TypeAArray; | |
12 import dmd.OutBuffer; | |
13 import dmd.Loc; | |
14 import dmd.Scope; | |
15 import dmd.InlineCostState; | |
16 import dmd.IRState; | |
17 import dmd.TY; | |
18 import dmd.InlineDoState; | |
19 import dmd.HdrGenState; | |
20 import dmd.InlineScanState; | |
21 import dmd.ArrayTypes; | |
22 import dmd.TOK; | |
23 import dmd.PREC; | |
24 import dmd.expression.Util; | |
25 import dmd.backend.Util; | |
26 import dmd.backend.TYM; | |
27 import dmd.backend.mTY; | |
28 import dmd.backend.OPER; | |
29 import dmd.backend.RTLSYM; | |
30 | |
31 class AssocArrayLiteralExp : Expression | |
32 { | |
33 Expressions keys; | |
34 Expressions values; | |
35 | |
36 this(Loc loc, Expressions keys, Expressions values) | |
37 { | |
38 super(loc, TOK.TOKassocarrayliteral, this.sizeof); | |
39 assert(keys.dim == values.dim); | |
40 this.keys = keys; | |
41 this.values = values; | |
42 } | |
43 | |
44 override Expression syntaxCopy() | |
45 { | |
46 return new AssocArrayLiteralExp(loc, | |
47 arraySyntaxCopy(keys), arraySyntaxCopy(values)); | |
48 } | |
49 | |
50 override Expression semantic(Scope sc) | |
51 { | |
52 Expression e; | |
53 Type tkey = null; | |
54 Type tvalue = null; | |
55 | |
56 version (LOGSEMANTIC) { | |
57 printf("AssocArrayLiteralExp.semantic('%s')\n", toChars()); | |
58 } | |
59 | |
109 | 60 if (type) |
61 return this; | |
62 | |
72 | 63 // Run semantic() on each element |
64 for (size_t i = 0; i < keys.dim; i++) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
65 { auto key = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
66 auto value = values[i]; |
72 | 67 |
68 key = key.semantic(sc); | |
69 value = value.semantic(sc); | |
70 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
71 keys[i] = key; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
72 values[i] = value; |
72 | 73 } |
74 expandTuples(keys); | |
75 expandTuples(values); | |
76 if (keys.dim != values.dim) | |
77 { | |
78 error("number of keys is %u, must match number of values %u", keys.dim, values.dim); | |
79 keys.setDim(0); | |
80 values.setDim(0); | |
81 } | |
82 for (size_t i = 0; i < keys.dim; i++) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
83 { auto key = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
84 auto value = values[i]; |
72 | 85 |
86 if (!key.type) | |
87 error("%s has no value", key.toChars()); | |
88 if (!value.type) | |
89 error("%s has no value", value.toChars()); | |
90 key = resolveProperties(sc, key); | |
91 value = resolveProperties(sc, value); | |
92 | |
93 if (!tkey) | |
94 tkey = key.type; | |
95 else | |
96 key = key.implicitCastTo(sc, tkey); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
97 keys[i] = key; |
72 | 98 |
99 if (!tvalue) | |
100 tvalue = value.type; | |
101 else | |
102 value = value.implicitCastTo(sc, tvalue); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
103 values[i] = value; |
72 | 104 } |
105 | |
106 if (!tkey) | |
107 tkey = Type.tvoid; | |
108 if (!tvalue) | |
109 tvalue = Type.tvoid; | |
110 type = new TypeAArray(tvalue, tkey); | |
111 type = type.semantic(loc, sc); | |
112 return this; | |
113 } | |
114 | |
115 override bool isBool(bool result) | |
116 { | |
117 size_t dim = keys.dim; | |
118 return result ? (dim != 0) : (dim == 0); | |
119 } | |
120 | |
121 override elem* toElem(IRState* irs) | |
122 { | |
123 elem* e; | |
124 size_t dim; | |
125 | |
126 //printf("AssocArrayLiteralExp.toElem() %s\n", toChars()); | |
127 dim = keys.dim; | |
128 e = el_long(TYint, dim); | |
129 for (size_t i = 0; i < dim; i++) | |
130 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
131 auto el = keys[i]; |
72 | 132 |
133 for (int j = 0; j < 2; j++) | |
134 { | |
135 elem* ep = el.toElem(irs); | |
136 | |
137 if (tybasic(ep.Ety) == TYstruct || tybasic(ep.Ety) == TYarray) | |
138 { | |
139 ep = el_una(OPstrpar, TYstruct, ep); | |
140 ep.Enumbytes = cast(uint)el.type.size(); | |
141 } | |
142 //printf("[%d] %s\n", i, el.toChars()); | |
143 //elem_print(ep); | |
144 e = el_param(ep, e); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
145 el = values[i]; |
72 | 146 } |
147 } | |
148 | |
149 Type t = type.toBasetype().mutableOf(); | |
150 assert(t.ty == Taarray); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
151 auto ta = cast(TypeAArray)t; |
72 | 152 |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
90
diff
changeset
|
153 static if(false) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
90
diff
changeset
|
154 { |
72 | 155 /* Unfortunately, the hash function for Aa (array of chars) is custom and |
156 * different from Axa and Aya, which get the generic hash function. | |
157 * So, rewrite the type of the AArray so that if it's key type | |
158 * is an array of const or invariant, make it an array of mutable. | |
159 */ | |
160 Type tkey = ta.index.toBasetype(); | |
161 if (tkey.ty == Tarray) | |
162 { | |
163 tkey = tkey.nextOf().mutableOf().arrayOf(); | |
164 tkey = tkey.semantic(Loc(0), null); | |
165 ta = new TypeAArray(ta.nextOf(), tkey); | |
166 ta = cast(TypeAArray)ta.merge(); | |
167 } | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
90
diff
changeset
|
168 } |
72 | 169 |
170 e = el_param(e, ta.getTypeInfo(null).toElem(irs)); | |
171 | |
172 // call _d_assocarrayliteralT(ti, dim, ...) | |
173 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e); | |
174 | |
175 el_setLoc(e,loc); | |
176 return e; | |
177 } | |
178 | |
179 override bool checkSideEffect(int flag) | |
180 { | |
181 bool f = false; | |
182 | |
183 for (size_t i = 0; i < keys.dim; i++) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
184 { auto key = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
185 auto value = values[i]; |
72 | 186 |
187 f |= key.checkSideEffect(2); | |
188 f |= value.checkSideEffect(2); | |
189 } | |
190 if (flag == 0 && f == 0) | |
191 Expression.checkSideEffect(0); | |
192 return f; | |
193 } | |
194 | |
195 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
196 { | |
197 buf.writeByte('['); | |
198 for (size_t i = 0; i < keys.dim; i++) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
199 { auto key = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
200 auto value = values[i]; |
72 | 201 |
202 if (i) | |
203 buf.writeByte(','); | |
204 expToCBuffer(buf, hgs, key, PREC.PREC_assign); | |
205 buf.writeByte(':'); | |
206 expToCBuffer(buf, hgs, value, PREC.PREC_assign); | |
207 } | |
208 buf.writeByte(']'); | |
209 } | |
210 | |
211 override void toMangleBuffer(OutBuffer buf) | |
212 { | |
213 size_t dim = keys.dim; | |
214 buf.printf("A%u", dim); | |
215 for (size_t i = 0; i < dim; i++) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
216 { auto key = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
217 auto value = values[i]; |
72 | 218 |
219 key.toMangleBuffer(buf); | |
220 value.toMangleBuffer(buf); | |
221 } | |
222 } | |
223 | |
224 override void scanForNestedRef(Scope sc) | |
225 { | |
226 assert(false); | |
227 } | |
228 | |
229 override Expression optimize(int result) | |
230 { | |
231 assert(keys.dim == values.dim); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
232 foreach (size_t i, Expression e; keys) |
72 | 233 { |
234 e = e.optimize(WANTvalue | (result & WANTinterpret)); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
235 keys[i] = e; |
72 | 236 |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
237 e = values[i]; |
72 | 238 e = e.optimize(WANTvalue | (result & WANTinterpret)); |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
239 values[i] = e; |
72 | 240 } |
241 return this; | |
242 } | |
243 | |
244 override Expression interpret(InterState istate) | |
245 { | |
246 Expressions keysx = keys; | |
247 Expressions valuesx = values; | |
248 | |
249 version (LOG) { | |
250 printf("AssocArrayLiteralExp.interpret() %s\n", toChars()); | |
251 } | |
252 for (size_t i = 0; i < keys.dim; i++) | |
253 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
254 auto ekey = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
255 auto evalue = values[i]; |
72 | 256 Expression ex; |
257 | |
258 ex = ekey.interpret(istate); | |
259 if (ex is EXP_CANT_INTERPRET) | |
260 goto Lerr; | |
261 | |
262 /* If any changes, do Copy On Write | |
263 */ | |
264 if (ex != ekey) | |
265 { | |
266 if (keysx == keys) | |
267 keysx = cast(Expressions)keys.copy(); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
268 keysx[i] = ex; |
72 | 269 } |
270 | |
271 ex = evalue.interpret(istate); | |
272 if (ex is EXP_CANT_INTERPRET) | |
273 goto Lerr; | |
274 | |
275 /* If any changes, do Copy On Write | |
276 */ | |
277 if (ex != evalue) | |
278 { | |
279 if (valuesx == values) | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
280 valuesx = values.copy(); |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
281 valuesx[i] = ex; |
72 | 282 } |
283 } | |
284 | |
285 if (keysx != keys) | |
286 expandTuples(keysx); | |
287 if (valuesx != values) | |
288 expandTuples(valuesx); | |
289 if (keysx.dim != valuesx.dim) | |
290 goto Lerr; | |
291 | |
292 /* Remove duplicate keys | |
293 */ | |
294 for (size_t i = 1; i < keysx.dim; i++) | |
295 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
296 auto ekey = keysx[i - 1]; |
72 | 297 |
298 for (size_t j = i; j < keysx.dim; j++) | |
299 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
300 auto ekey2 = keysx[j]; |
72 | 301 Expression ex = Equal(TOKequal, Type.tbool, ekey, ekey2); |
302 if (ex is EXP_CANT_INTERPRET) | |
303 goto Lerr; | |
304 if (ex.isBool(true)) // if a match | |
305 { | |
306 // Remove ekey | |
307 if (keysx == keys) | |
308 keysx = cast(Expressions)keys.copy(); | |
309 if (valuesx == values) | |
310 valuesx = cast(Expressions)values.copy(); | |
311 keysx.remove(i - 1); | |
312 valuesx.remove(i - 1); | |
313 i -= 1; // redo the i'th iteration | |
314 break; | |
315 } | |
316 } | |
317 } | |
318 | |
319 if (keysx != keys || valuesx != values) | |
320 { | |
321 AssocArrayLiteralExp ae; | |
322 ae = new AssocArrayLiteralExp(loc, keysx, valuesx); | |
323 ae.type = type; | |
324 return ae; | |
325 } | |
326 return this; | |
327 | |
328 Lerr: | |
329 if (keysx != keys) | |
330 delete keysx; | |
331 if (valuesx != values) | |
332 delete values; | |
333 return EXP_CANT_INTERPRET; | |
334 } | |
335 | |
336 override MATCH implicitConvTo(Type t) | |
337 { | |
338 MATCH result = MATCHexact; | |
339 | |
340 Type typeb = type.toBasetype(); | |
341 Type tb = t.toBasetype(); | |
342 if (tb.ty == Taarray && typeb.ty == Taarray) | |
343 { | |
344 for (size_t i = 0; i < keys.dim; i++) | |
345 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
346 auto e = keys[i]; |
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
347 auto m = cast(MATCH)e.implicitConvTo((cast(TypeAArray)tb).index); |
72 | 348 if (m < result) |
349 result = m; // remember worst match | |
350 if (result == MATCHnomatch) | |
351 break; // no need to check for worse | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
352 e = values[i]; |
72 | 353 m = cast(MATCH)e.implicitConvTo(tb.nextOf()); |
354 if (m < result) | |
355 result = m; // remember worst match | |
356 if (result == MATCHnomatch) | |
357 break; // no need to check for worse | |
358 } | |
359 return result; | |
360 } | |
361 else | |
362 return Expression.implicitConvTo(t); | |
363 } | |
364 | |
365 override Expression castTo(Scope sc, Type t) | |
366 { | |
367 if (type == t) | |
368 return this; | |
369 AssocArrayLiteralExp e = this; | |
370 Type typeb = type.toBasetype(); | |
371 Type tb = t.toBasetype(); | |
372 if (tb.ty == Taarray && typeb.ty == Taarray && tb.nextOf().toBasetype().ty != Tvoid) | |
373 { | |
374 e = cast(AssocArrayLiteralExp)copy(); | |
375 e.keys = cast(Expressions)keys.copy(); | |
376 e.values = cast(Expressions)values.copy(); | |
377 assert(keys.dim == values.dim); | |
378 for (size_t i = 0; i < keys.dim; i++) | |
379 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
380 auto ex = values[i]; |
72 | 381 ex = ex.castTo(sc, tb.nextOf()); |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
382 e.values[i] = ex; |
72 | 383 |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
384 ex = keys[i]; |
72 | 385 ex = ex.castTo(sc, (cast(TypeAArray)tb).index); |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
386 e.keys[i] = ex; |
72 | 387 } |
388 e.type = t; | |
389 return e; | |
390 } | |
391 L1: | |
392 return e.Expression.castTo(sc, t); | |
393 } | |
394 | |
395 override bool canThrow() | |
396 { | |
397 return true; | |
398 } | |
399 | |
400 override int inlineCost(InlineCostState* ics) | |
401 { | |
402 assert(false); | |
403 } | |
404 | |
405 override Expression doInline(InlineDoState ids) | |
406 { | |
407 assert(false); | |
408 } | |
409 | |
410 override Expression inlineScan(InlineScanState* iss) | |
411 { | |
412 assert(false); | |
413 } | |
414 } |