Mercurial > projects > ddmd
annotate dmd/AddrExp.d @ 77:ad4792a1cfd6
more D-ification container accessing
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Sun, 29 Aug 2010 14:36:55 +0100 |
parents | 2e2a5c3f943a |
children | be2ab491772e |
rev | line source |
---|---|
72 | 1 module dmd.AddrExp; |
2 | |
3 import dmd.Expression; | |
4 import dmd.UnaExp; | |
5 import dmd.MATCH; | |
6 import dmd.Type; | |
7 import dmd.Loc; | |
8 import dmd.Scope; | |
0 | 9 import dmd.IRState; |
10 import dmd.ErrorExp; | |
11 import dmd.DotVarExp; | |
12 import dmd.FuncDeclaration; | |
13 import dmd.DelegateExp; | |
14 import dmd.VarExp; | |
15 import dmd.VarDeclaration; | |
72 | 16 import dmd.ThisExp; |
0 | 17 import dmd.TOK; |
18 import dmd.WANT; | |
19 import dmd.CommaExp; | |
20 import dmd.STC; | |
21 import dmd.PtrExp; | |
22 import dmd.SymOffExp; | |
23 import dmd.IndexExp; | |
24 import dmd.OverExp; | |
25 import dmd.Dsymbol; | |
26 import dmd.ScopeDsymbol; | |
27 import dmd.TY; | |
72 | 28 import dmd.TypeSArray; |
29 | |
0 | 30 import dmd.backend.elem; |
31 import dmd.backend.Util; | |
72 | 32 import dmd.codegen.Util; |
33 | |
0 | 34 class AddrExp : UnaExp |
35 { | |
36 this(Loc loc, Expression e) | |
37 { | |
38 super(loc, TOK.TOKaddress, AddrExp.sizeof, e); | |
39 } | |
40 | |
72 | 41 override Expression semantic(Scope sc) |
0 | 42 { |
43 version (LOGSEMANTIC) { | |
44 printf("AddrExp.semantic('%s')\n", toChars()); | |
45 } | |
46 if (!type) | |
47 { | |
48 UnaExp.semantic(sc); | |
49 e1 = e1.toLvalue(sc, null); | |
50 if (!e1.type) | |
51 { | |
52 error("cannot take address of %s", e1.toChars()); | |
53 return new ErrorExp(); | |
54 } | |
55 if (!e1.type.deco) | |
56 { | |
57 /* No deco means semantic() was not run on the type. | |
58 * We have to run semantic() on the symbol to get the right type: | |
59 * auto x = &bar; | |
60 * pure: int bar() { return 1;} | |
61 * otherwise the 'pure' is missing from the type assigned to x. | |
62 */ | |
63 | |
64 error("forward reference to %s", e1.toChars()); | |
65 return new ErrorExp(); | |
66 } | |
67 | |
68 //printf("test3 deco = %p\n", e1.type.deco); | |
69 type = e1.type.pointerTo(); | |
70 | |
71 // See if this should really be a delegate | |
72 if (e1.op == TOKdotvar) | |
73 { | |
74 DotVarExp dve = cast(DotVarExp)e1; | |
75 FuncDeclaration f = dve.var.isFuncDeclaration(); | |
76 | |
77 if (f) | |
78 { | |
79 if (!dve.hasOverloads) | |
80 f.tookAddressOf++; | |
81 Expression e = new DelegateExp(loc, dve.e1, f, dve.hasOverloads); | |
82 e = e.semantic(sc); | |
83 return e; | |
84 } | |
85 } | |
86 else if (e1.op == TOKvar) | |
87 { | |
88 VarExp ve = cast(VarExp)e1; | |
89 | |
90 VarDeclaration v = ve.var.isVarDeclaration(); | |
91 if (v && !v.canTakeAddressOf()) | |
92 error("cannot take address of %s", e1.toChars()); | |
93 | |
94 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
95 | |
96 if (f) | |
97 { | |
98 if (!ve.hasOverloads || | |
99 /* Because nested functions cannot be overloaded, | |
100 * mark here that we took its address because castTo() | |
101 * may not be called with an exact match. | |
102 */ | |
103 f.toParent2().isFuncDeclaration()) | |
104 f.tookAddressOf++; | |
105 | |
106 if (f.isNested()) | |
107 { | |
108 Expression e = new DelegateExp(loc, e1, f, ve.hasOverloads); | |
109 e = e.semantic(sc); | |
110 return e; | |
111 } | |
112 if (f.needThis() && hasThis(sc)) | |
113 { | |
114 /* Should probably supply 'this' after overload resolution, | |
115 * not before. | |
116 */ | |
117 Expression ethis = new ThisExp(loc); | |
118 Expression e = new DelegateExp(loc, ethis, f, ve.hasOverloads); | |
119 e = e.semantic(sc); | |
120 return e; | |
121 } | |
122 } | |
123 } | |
124 return optimize(WANTvalue); | |
125 } | |
126 return this; | |
127 } | |
128 | |
72 | 129 override elem* toElem(IRState* irs) |
0 | 130 { |
131 elem* e; | |
132 | |
133 //printf("AddrExp.toElem('%s')\n", toChars()); | |
134 | |
135 e = e1.toElem(irs); | |
136 e = addressElem(e, e1.type); | |
137 L2: | |
138 e.Ety = type.totym(); | |
139 el_setLoc(e,loc); | |
140 return e; | |
141 } | |
142 | |
72 | 143 override MATCH implicitConvTo(Type t) |
0 | 144 { |
145 static if (false) { | |
146 printf("AddrExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
147 toChars(), type.toChars(), t.toChars()); | |
148 } | |
149 MATCH result; | |
150 | |
151 result = type.implicitConvTo(t); | |
152 //printf("\tresult = %d\n", result); | |
153 | |
154 if (result == MATCHnomatch) | |
155 { | |
156 // Look for pointers to functions where the functions are overloaded. | |
157 | |
158 t = t.toBasetype(); | |
159 | |
160 if (e1.op == TOKoverloadset && | |
161 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction) | |
162 { | |
163 OverExp eo = cast(OverExp)e1; | |
164 FuncDeclaration f = null; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
165 foreach(Dsymbol s; eo.vars.a) |
0 | 166 { |
167 FuncDeclaration f2 = s.isFuncDeclaration(); | |
168 assert(f2); | |
169 if (f2.overloadExactMatch(t.nextOf())) | |
170 { | |
171 if (f) | |
172 /* Error if match in more than one overload set, | |
173 * even if one is a 'better' match than the other. | |
174 */ | |
175 ScopeDsymbol.multiplyDefined(loc, f, f2); | |
176 else | |
177 f = f2; | |
178 result = MATCHexact; | |
179 } | |
180 } | |
181 } | |
182 | |
183 if (type.ty == Tpointer && type.nextOf().ty == Tfunction && | |
184 t.ty == Tpointer && t.nextOf().ty == Tfunction && | |
185 e1.op == TOKvar) | |
186 { | |
187 /* I don't think this can ever happen - | |
188 * it should have been | |
189 * converted to a SymOffExp. | |
190 */ | |
191 assert(0); | |
192 VarExp ve = cast(VarExp)e1; | |
193 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
194 if (f && f.overloadExactMatch(t.nextOf())) | |
195 result = MATCHexact; | |
196 } | |
197 } | |
198 | |
199 //printf("\tresult = %d\n", result); | |
200 return result; | |
201 } | |
202 | |
72 | 203 override Expression castTo(Scope sc, Type t) |
0 | 204 { |
205 Type tb; | |
206 | |
207 static if (false) { | |
208 printf("AddrExp.castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars()); | |
209 } | |
210 Expression e = this; | |
211 | |
212 tb = t.toBasetype(); | |
213 type = type.toBasetype(); | |
214 if (tb != type) | |
215 { | |
216 // Look for pointers to functions where the functions are overloaded. | |
217 | |
218 if (e1.op == TOKoverloadset && | |
219 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction) | |
220 { | |
221 OverExp eo = cast(OverExp)e1; | |
222 FuncDeclaration f = null; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
223 foreach(Dsymbol s; eo.vars.a) |
0 | 224 { |
225 FuncDeclaration f2 = s.isFuncDeclaration(); | |
226 assert(f2); | |
227 if (f2.overloadExactMatch(t.nextOf())) | |
228 { | |
229 if (f) | |
230 /* Error if match in more than one overload set, | |
231 * even if one is a 'better' match than the other. | |
232 */ | |
233 ScopeDsymbol.multiplyDefined(loc, f, f2); | |
234 else | |
235 f = f2; | |
236 } | |
237 } | |
238 if (f) | |
239 { | |
240 f.tookAddressOf++; | |
241 SymOffExp se = new SymOffExp(loc, f, 0, 0); | |
242 se.semantic(sc); | |
243 // Let SymOffExp.castTo() do the heavy lifting | |
244 return se.castTo(sc, t); | |
245 } | |
246 } | |
247 | |
248 | |
249 if (type.ty == Tpointer && type.nextOf().ty == Tfunction && | |
250 tb.ty == Tpointer && tb.nextOf().ty == Tfunction && | |
251 e1.op == TOKvar) | |
252 { | |
253 VarExp ve = cast(VarExp)e1; | |
254 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
255 if (f) | |
256 { | |
257 assert(0); // should be SymOffExp instead | |
258 f = f.overloadExactMatch(tb.nextOf()); | |
259 if (f) | |
260 { | |
261 e = new VarExp(loc, f); | |
262 e.type = f.type; | |
263 e = new AddrExp(loc, e); | |
264 e.type = t; | |
265 return e; | |
266 } | |
267 } | |
268 } | |
269 e = Expression.castTo(sc, t); | |
270 } | |
271 e.type = t; | |
272 return e; | |
273 } | |
274 | |
72 | 275 override Expression optimize(int result) |
0 | 276 { |
277 Expression e; | |
278 | |
279 //printf("AddrExp.optimize(result = %d) %s\n", result, toChars()); | |
280 | |
281 /* Rewrite &(a,b) as (a,&b) | |
282 */ | |
283 if (e1.op == TOKcomma) | |
284 { | |
285 CommaExp ce = cast(CommaExp)e1; | |
286 AddrExp ae = new AddrExp(loc, ce.e2); | |
287 ae.type = type; | |
288 e = new CommaExp(ce.loc, ce.e1, ae); | |
289 e.type = type; | |
290 return e.optimize(result); | |
291 } | |
292 | |
293 if (e1.op == TOKvar) | |
294 { | |
295 VarExp ve = cast(VarExp)e1; | |
296 if (ve.var.storage_class & STCmanifest) | |
297 e1 = e1.optimize(result); | |
298 } | |
299 else | |
300 e1 = e1.optimize(result); | |
301 | |
302 // Convert &*ex to ex | |
303 if (e1.op == TOKstar) | |
304 { | |
305 Expression ex; | |
306 | |
307 ex = (cast(PtrExp)e1).e1; | |
308 if (type.equals(ex.type)) | |
309 e = ex; | |
310 else | |
311 { | |
312 e = ex.copy(); | |
313 e.type = type; | |
314 } | |
315 return e; | |
316 } | |
317 if (e1.op == TOKvar) | |
318 { | |
319 VarExp ve = cast(VarExp)e1; | |
320 if (!ve.var.isOut() && !ve.var.isRef() && | |
321 !ve.var.isImportedSymbol()) | |
322 { | |
323 SymOffExp se = new SymOffExp(loc, ve.var, 0, ve.hasOverloads); | |
324 se.type = type; | |
325 return se; | |
326 } | |
327 } | |
328 if (e1.op == TOKindex) | |
329 { | |
330 // Convert &array[n] to &array+n | |
331 IndexExp ae = cast(IndexExp)e1; | |
332 | |
333 if (ae.e2.op == TOKint64 && ae.e1.op == TOKvar) | |
334 { | |
335 long index = ae.e2.toInteger(); | |
336 VarExp ve = cast(VarExp)ae.e1; | |
337 if (ve.type.ty == Tsarray | |
338 && !ve.var.isImportedSymbol()) | |
339 { | |
340 TypeSArray ts = cast(TypeSArray)ve.type; | |
341 long dim = ts.dim.toInteger(); | |
342 if (index < 0 || index >= dim) | |
343 error("array index %jd is out of bounds [0..%jd]", index, dim); | |
344 e = new SymOffExp(loc, ve.var, cast(uint)(index * ts.nextOf().size())); | |
345 e.type = type; | |
346 return e; | |
347 } | |
348 } | |
349 } | |
350 return this; | |
351 } | |
352 } | |
353 |