Mercurial > projects > ddmd
annotate dmd/DotIdExp.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 | 9d194c848e3a |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.DotIdExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Identifier; | |
6 import dmd.IntegerExp; | |
7 import dmd.Type; | |
8 import dmd.TY; | |
9 import dmd.ScopeExp; | |
10 import dmd.StringExp; | |
11 import dmd.PtrExp; | |
12 import dmd.TypePointer; | |
13 import dmd.Dsymbol; | |
14 import dmd.EnumMember; | |
15 import dmd.VarDeclaration; | |
16 import dmd.ThisExp; | |
17 import dmd.DotVarExp; | |
18 import dmd.VarExp; | |
19 import dmd.CommaExp; | |
20 import dmd.FuncDeclaration; | |
21 import dmd.OverloadSet; | |
22 import dmd.OverExp; | |
23 import dmd.TypeExp; | |
24 import dmd.TupleDeclaration; | |
25 import dmd.ScopeDsymbol; | |
26 import dmd.Import; | |
27 import dmd.Id; | |
28 import dmd.TupleExp; | |
29 import dmd.ArrayTypes; | |
30 import dmd.UnaExp; | |
31 import dmd.OutBuffer; | |
32 import dmd.Loc; | |
33 import dmd.Scope; | |
34 import dmd.TOK; | |
35 import dmd.HdrGenState; | |
36 import dmd.ClassDeclaration; | |
37 import dmd.StructDeclaration; | |
38 import dmd.AggregateDeclaration; | |
39 import dmd.DotExp; | |
40 import dmd.Global; | |
41 import dmd.IdentifierExp; | |
42 import dmd.CallExp; | |
43 import dmd.PREC; | |
44 | |
45 import dmd.expression.Util; | |
46 | |
0 | 47 class DotIdExp : UnaExp |
48 { | |
49 Identifier ident; | |
50 | |
51 this(Loc loc, Expression e, Identifier ident) | |
52 { | |
178 | 53 register(); |
72 | 54 super(loc, TOK.TOKdot, DotIdExp.sizeof, e); |
0 | 55 this.ident = ident; |
56 } | |
57 | |
72 | 58 override Expression semantic(Scope sc) |
0 | 59 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
60 // Indicate we didn't come from CallExp::semantic() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
61 return semantic(sc, 0); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
62 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
63 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
64 Expression semantic(Scope sc, int flag) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
65 { |
72 | 66 Expression e; |
67 Expression eleft; | |
68 Expression eright; | |
69 | |
70 version (LOGSEMANTIC) { | |
71 printf("DotIdExp.semantic(this = %p, '%s')\n", this, toChars()); | |
72 //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op)); | |
73 } | |
74 | |
75 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } | |
76 | |
77 static if (false) { | |
78 /* Don't do semantic analysis if we'll be converting | |
79 * it to a string. | |
80 */ | |
81 if (ident == Id.stringof) | |
82 { | |
83 char *s = e1.toChars(); | |
84 e = new StringExp(loc, s, strlen(s), 'c'); | |
85 e = e.semantic(sc); | |
86 return e; | |
87 } | |
88 } | |
89 | |
90 /* Special case: rewrite this.id and super.id | |
91 * to be classtype.id and baseclasstype.id | |
92 * if we have no this pointer. | |
93 */ | |
94 if ((e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper) && !hasThis(sc)) | |
95 { | |
96 ClassDeclaration cd; | |
97 StructDeclaration sd; | |
98 AggregateDeclaration ad; | |
99 | |
100 ad = sc.getStructClassScope(); | |
101 if (ad) | |
102 { | |
103 cd = ad.isClassDeclaration(); | |
104 if (cd) | |
105 { | |
106 if (e1.op == TOK.TOKthis) | |
107 { | |
108 e = typeDotIdExp(loc, cd.type, ident); | |
109 return e.semantic(sc); | |
110 } | |
111 else if (cd.baseClass && e1.op == TOK.TOKsuper) | |
112 { | |
113 e = typeDotIdExp(loc, cd.baseClass.type, ident); | |
114 return e.semantic(sc); | |
115 } | |
116 } | |
117 else | |
118 { | |
119 sd = ad.isStructDeclaration(); | |
120 if (sd) | |
121 { | |
122 if (e1.op == TOK.TOKthis) | |
123 { | |
124 e = typeDotIdExp(loc, sd.type, ident); | |
125 return e.semantic(sc); | |
126 } | |
127 } | |
128 } | |
129 } | |
130 } | |
131 | |
132 UnaExp.semantic(sc); | |
133 | |
134 if (e1.op == TOK.TOKdotexp) | |
135 { | |
136 DotExp de = cast(DotExp)e1; | |
137 eleft = de.e1; | |
138 eright = de.e2; | |
139 } | |
140 else | |
141 { | |
142 e1 = resolveProperties(sc, e1); | |
143 eleft = null; | |
144 eright = e1; | |
145 } | |
146 | |
147 version (DMDV2) { | |
148 if (e1.op == TOK.TOKtuple && ident == Id.offsetof) | |
149 { | |
150 /* 'distribute' the .offsetof to each of the tuple elements. | |
151 */ | |
152 TupleExp te = cast(TupleExp)e1; | |
153 Expressions exps = new Expressions(); | |
154 exps.setDim(te.exps.dim); | |
155 for (int i = 0; i < exps.dim; i++) | |
156 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
157 auto ee = te.exps[i]; |
72 | 158 ee = ee.semantic(sc); |
136 | 159 ee = new DotIdExp(ee.loc, ee, Id.offsetof); |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
160 exps[i] = ee; |
72 | 161 } |
162 e = new TupleExp(loc, exps); | |
163 e = e.semantic(sc); | |
164 return e; | |
165 } | |
166 } | |
167 | |
168 if (e1.op == TOK.TOKtuple && ident == Id.length) | |
169 { | |
170 TupleExp te = cast(TupleExp)e1; | |
171 e = new IntegerExp(loc, te.exps.dim, Type.tsize_t); | |
172 return e; | |
173 } | |
174 | |
175 if (e1.op == TOK.TOKdottd) | |
176 { | |
177 error("template %s does not have property %s", e1.toChars(), ident.toChars()); | |
178 return e1; | |
179 } | |
180 | |
181 if (!e1.type) | |
182 { | |
183 error("expression %s does not have property %s", e1.toChars(), ident.toChars()); | |
184 return e1; | |
185 } | |
186 | |
187 Type t1b = e1.type.toBasetype(); | |
188 | |
189 if (eright.op == TOK.TOKimport) // also used for template alias's | |
190 { | |
191 ScopeExp ie = cast(ScopeExp)eright; | |
192 | |
193 /* Disable access to another module's private imports. | |
194 * The check for 'is sds our current module' is because | |
195 * the current module should have access to its own imports. | |
196 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
197 Dsymbol s = ie.sds.search(loc, ident, //0); |
72 | 198 (ie.sds.isModule() && ie.sds != sc.module_) ? 1 : 0); |
199 if (s) | |
200 { | |
201 s = s.toAlias(); | |
202 checkDeprecated(sc, s); | |
203 | |
204 EnumMember em = s.isEnumMember(); | |
205 if (em) | |
206 { | |
207 e = em.value; | |
208 e = e.semantic(sc); | |
209 return e; | |
210 } | |
211 | |
212 VarDeclaration v = s.isVarDeclaration(); | |
213 if (v) | |
214 { | |
215 //printf("DotIdExp. Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars()); | |
216 if (v.inuse) | |
217 { | |
218 error("circular reference to '%s'", v.toChars()); | |
219 type = Type.tint32; | |
220 return this; | |
221 } | |
222 type = v.type; | |
223 if (v.needThis()) | |
224 { | |
225 if (!eleft) | |
226 eleft = new ThisExp(loc); | |
227 e = new DotVarExp(loc, eleft, v); | |
228 e = e.semantic(sc); | |
229 } | |
230 else | |
231 { | |
232 e = new VarExp(loc, v); | |
233 if (eleft) | |
234 { | |
235 e = new CommaExp(loc, eleft, e); | |
236 e.type = v.type; | |
237 } | |
238 } | |
239 return e.deref(); | |
240 } | |
241 | |
242 FuncDeclaration f = s.isFuncDeclaration(); | |
243 if (f) | |
244 { | |
245 //printf("it's a function\n"); | |
246 if (f.needThis()) | |
247 { | |
248 if (!eleft) | |
249 eleft = new ThisExp(loc); | |
250 e = new DotVarExp(loc, eleft, f); | |
251 e = e.semantic(sc); | |
252 } | |
253 else | |
254 { | |
255 e = new VarExp(loc, f, 1); | |
256 if (eleft) | |
257 { e = new CommaExp(loc, eleft, e); | |
258 e.type = f.type; | |
259 } | |
260 } | |
261 return e; | |
262 } | |
263 version (DMDV2) { | |
264 OverloadSet o = s.isOverloadSet(); | |
265 if (o) | |
266 { | |
267 //printf("'%s' is an overload set\n", o.toChars()); | |
268 return new OverExp(o); | |
269 } | |
270 } | |
271 | |
272 Type t = s.getType(); | |
273 if (t) | |
274 { | |
275 return new TypeExp(loc, t); | |
276 } | |
277 | |
278 TupleDeclaration tup = s.isTupleDeclaration(); | |
279 if (tup) | |
280 { | |
281 if (eleft) | |
282 error("cannot have e.tuple"); | |
283 e = new TupleExp(loc, tup); | |
284 e = e.semantic(sc); | |
285 return e; | |
286 } | |
287 | |
288 ScopeDsymbol sds = s.isScopeDsymbol(); | |
289 if (sds) | |
290 { | |
291 //printf("it's a ScopeDsymbol\n"); | |
292 e = new ScopeExp(loc, sds); | |
293 e = e.semantic(sc); | |
294 if (eleft) | |
295 e = new DotExp(loc, eleft, e); | |
296 return e; | |
297 } | |
298 | |
299 Import imp = s.isImport(); | |
300 if (imp) | |
301 { | |
302 ScopeExp iee = new ScopeExp(loc, imp.pkg); | |
303 return iee.semantic(sc); | |
304 } | |
305 | |
306 // BUG: handle other cases like in IdentifierExp.semantic() | |
307 version (DEBUG) { | |
308 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind()); | |
309 } | |
310 assert(0); | |
311 } | |
312 else if (ident is Id.stringof_) | |
313 { | |
314 string ss = ie.toChars(); | |
315 e = new StringExp(loc, ss, 'c'); | |
316 e = e.semantic(sc); | |
317 return e; | |
318 } | |
319 error("undefined identifier %s", toChars()); | |
320 type = Type.tvoid; | |
321 return this; | |
322 } | |
323 else if (t1b.ty == TY.Tpointer && | |
324 ident !is Id.init_ && ident !is Id.__sizeof && | |
325 ident !is Id.alignof_ && ident !is Id.offsetof && | |
326 ident !is Id.mangleof_ && ident !is Id.stringof_) | |
327 { /* Rewrite: | |
328 * p.ident | |
329 * as: | |
330 * (*p).ident | |
331 */ | |
332 e = new PtrExp(loc, e1); | |
333 e.type = (cast(TypePointer)t1b).next; | |
334 return e.type.dotExp(sc, e, ident); | |
335 } | |
336 ///version (DMDV2) { | |
337 else if (t1b.ty == TY.Tarray || | |
338 t1b.ty == TY.Tsarray || | |
339 t1b.ty == TY.Taarray) | |
340 { | |
341 /* If ident is not a valid property, rewrite: | |
342 * e1.ident | |
343 * as: | |
344 * .ident(e1) | |
345 */ | |
346 uint errors = global.errors; | |
347 global.gag++; | |
109 | 348 Type t1 = e1.type; |
72 | 349 e = e1.type.dotExp(sc, e1, ident); |
350 global.gag--; | |
351 if (errors != global.errors) // if failed to find the property | |
352 { | |
353 global.errors = errors; | |
109 | 354 e1.type = t1; // kludge to restore type |
72 | 355 e = new DotIdExp(loc, new IdentifierExp(loc, Id.empty), ident); |
356 e = new CallExp(loc, e, e1); | |
357 } | |
358 e = e.semantic(sc); | |
359 return e; | |
360 } | |
361 ///} | |
362 else | |
363 { | |
364 e = e1.type.dotExp(sc, e1, ident); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
365 if (!(flag && e.op == TOK.TOKdotti)) // let CallExp::semantic() handle this |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
366 e = e.semantic(sc); |
72 | 367 return e; |
0 | 368 } |
369 } | |
370 | |
72 | 371 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 372 { |
72 | 373 //printf("DotIdExp.toCBuffer()\n"); |
374 expToCBuffer(buf, hgs, e1, PREC.PREC_primary); | |
375 buf.writeByte('.'); | |
0 | 376 buf.writestring(ident.toChars()); |
377 } | |
378 | |
72 | 379 override void dump(int i) |
0 | 380 { |
381 assert(false); | |
382 } | |
383 } | |
384 |