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