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