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