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