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