Mercurial > projects > ddmd
annotate dmd/VarExp.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 | 52188e7e3fb5 |
rev | line source |
---|---|
72 | 1 module dmd.VarExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Declaration; | |
6 import dmd.InterState; | |
7 import dmd.OutBuffer; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
10 import dmd.InlineCostState; | |
11 import dmd.FuncLiteralDeclaration; | |
12 import dmd.VarDeclaration; | |
13 import dmd.Dsymbol; | |
14 import dmd.FuncDeclaration; | |
15 import dmd.InlineDoState; | |
16 import dmd.HdrGenState; | |
17 import dmd.TOK; | |
18 import dmd.TY; | |
19 import dmd.STC; | |
148 | 20 import dmd.SymbolDeclaration; |
72 | 21 import dmd.SymbolExp; |
22 import dmd.Type; | |
23 import dmd.interpret.Util; | |
148 | 24 import dmd.backend.Util; |
72 | 25 import dmd.backend.dt_t; |
26 import dmd.expression.Util; | |
27 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
28 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
|
29 |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
30 //! Variable |
0 | 31 class VarExp : SymbolExp |
32 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
33 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
|
34 |
73 | 35 this(Loc loc, Declaration var, bool hasOverloads = false) |
0 | 36 { |
178 | 37 register(); |
72 | 38 super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads); |
39 | |
40 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars()); | |
41 //if (strcmp(var.ident.toChars(), "func") == 0) halt(); | |
0 | 42 this.type = var.type; |
43 } | |
44 | |
72 | 45 override bool equals(Object o) |
0 | 46 { |
156 | 47 VarExp ne; |
48 | |
49 if ( this == o || | |
50 ((cast(Expression)o).op == TOKvar && | |
51 ((ne = cast(VarExp)o), type.toHeadMutable().equals(ne.type.toHeadMutable())) && | |
52 var == ne.var)) | |
53 return true; | |
54 return false; | |
0 | 55 } |
56 | |
72 | 57 override Expression semantic(Scope sc) |
0 | 58 { |
72 | 59 FuncLiteralDeclaration fd; |
60 | |
61 version (LOGSEMANTIC) { | |
62 printf("VarExp.semantic(%s)\n", toChars()); | |
63 } | |
64 if (!type) | |
65 { | |
66 type = var.type; | |
67 static if (false) { | |
68 if (var.storage_class & STC.STClazy) | |
69 { | |
70 TypeFunction tf = new TypeFunction(null, type, 0, LINK.LINKd); | |
71 type = new TypeDelegate(tf); | |
72 type = type.semantic(loc, sc); | |
73 } | |
74 } | |
75 } | |
76 | |
77 /* Fix for 1161 doesn't work because it causes protection | |
78 * problems when instantiating imported templates passing private | |
79 * variables as alias template parameters. | |
80 */ | |
81 //accessCheck(loc, sc, null, var); | |
82 | |
83 VarDeclaration v = var.isVarDeclaration(); | |
84 if (v) | |
85 { | |
86 static if (false) { | |
135 | 87 if ((v.isConst() || v.isImmutable()) && type.toBasetype().ty != TY.Tsarray && v.init) |
72 | 88 { |
89 ExpInitializer ei = v.init.isExpInitializer(); | |
90 if (ei) | |
91 { | |
92 //ei.exp.implicitCastTo(sc, type).print(); | |
93 return ei.exp.implicitCastTo(sc, type); | |
94 } | |
95 } | |
96 } | |
97 v.checkNestedReference(sc, loc); | |
98 version (DMDV2) { | |
99 static if (true) { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
100 if (sc.func && !sc.intypeof) |
72 | 101 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
102 /* Given: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
103 * void f() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
104 * { int fx; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
105 * pure void g() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
106 * { int gx; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
107 * void h() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
108 * { int hx; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
109 * void i() { } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
110 * } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
111 * } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
112 * } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
113 * i() can modify hx and gx but not fx |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
114 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
115 |
72 | 116 /* Determine if sc.func is pure or if any function that |
117 * encloses it is also pure. | |
118 */ | |
119 bool hasPureParent = false; | |
120 for (FuncDeclaration outerfunc = sc.func; outerfunc;) | |
121 { | |
122 if (outerfunc.isPure()) | |
123 { | |
124 hasPureParent = true; | |
125 break; | |
126 } | |
127 Dsymbol parent = outerfunc.toParent2(); | |
128 if (!parent) | |
129 break; | |
130 outerfunc = parent.isFuncDeclaration(); | |
131 } | |
132 | |
133 /* If ANY of its enclosing functions are pure, | |
134 * it cannot do anything impure. | |
135 * If it is pure, it cannot access any mutable variables other | |
136 * than those inside itself | |
137 */ | |
135 | 138 if (hasPureParent && v.isDataseg() && !v.isImmutable()) |
72 | 139 { |
140 error("pure function '%s' cannot access mutable static data '%s'", | |
141 sc.func.toChars(), v.toChars()); | |
142 } | |
135 | 143 else if (sc.func.isPure() && sc.parent != v.parent && !v.isImmutable() && !(v.storage_class & STC.STCmanifest)) |
72 | 144 { |
145 error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars()); | |
146 if (v.isEnumDeclaration()) | |
147 error("enum"); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
148 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
149 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
150 /* Do not allow safe functions to access __gshared data |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
151 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
152 if (sc.func.isSafe() && v.storage_class & STCgshared) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
153 error("safe function '%s' cannot access __gshared data '%s'", |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
154 sc.func.toChars(), v.toChars()); |
72 | 155 } |
156 } else { | |
157 if (sc.func && sc.func.isPure() && !sc.intypeof) | |
158 { | |
135 | 159 if (v.isDataseg() && !v.isImmutable()) |
72 | 160 error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars()); |
161 } | |
162 } | |
163 } | |
164 } | |
165 else | |
166 { | |
167 static if (false) { | |
168 if ((fd = var.isFuncLiteralDeclaration()) !is null) | |
169 { | |
170 Expression e = new FuncExp(loc, fd); | |
171 e.type = type; | |
172 return e; | |
173 } | |
174 } | |
175 } | |
176 | |
0 | 177 return this; |
178 } | |
179 | |
72 | 180 override Expression optimize(int result) |
0 | 181 { |
182 return fromConstInitializer(result, this); | |
183 } | |
184 | |
72 | 185 override Expression interpret(InterState istate) |
0 | 186 { |
72 | 187 version (LOG) { |
188 printf("VarExp.interpret() %.*s\n", toChars()); | |
189 } | |
63 | 190 return getVarExp(loc, istate, var); |
0 | 191 } |
192 | |
72 | 193 override void dump(int indent) |
0 | 194 { |
195 assert(false); | |
196 } | |
197 | |
72 | 198 override string toChars() |
0 | 199 { |
200 return var.toChars(); | |
201 } | |
202 | |
72 | 203 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 204 { |
205 buf.writestring(var.toChars()); | |
206 } | |
207 | |
72 | 208 override void checkEscape() |
0 | 209 { |
72 | 210 VarDeclaration v = var.isVarDeclaration(); |
211 if (v) | |
212 { | |
213 Type tb = v.type.toBasetype(); | |
214 // if reference type | |
215 if (tb.ty == TY.Tarray || tb.ty == TY.Tsarray || tb.ty == TY.Tclass) | |
216 { | |
217 if ((v.isAuto() || v.isScope()) && !v.noauto) | |
218 error("escaping reference to scope local %s", v.toChars()); | |
219 else if (v.storage_class & STC.STCvariadic) | |
220 error("escaping reference to variadic parameter %s", v.toChars()); | |
221 } | |
0 | 222 } |
223 } | |
135 | 224 |
225 override void checkEscapeRef() | |
226 { | |
227 VarDeclaration v = var.isVarDeclaration(); | |
228 if (v) | |
229 { | |
230 if (!v.isDataseg() && !(v.storage_class & (STCref | STCout))) | |
231 error("escaping reference to local variable %s", v.toChars()); | |
232 } | |
233 } | |
72 | 234 |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
235 version (DMDV2) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
236 { |
72 | 237 override int isLvalue() |
0 | 238 { |
72 | 239 if (var.storage_class & STClazy) |
240 return 0; | |
0 | 241 return 1; |
242 } | |
243 } | |
72 | 244 override Expression toLvalue(Scope sc, Expression e) |
0 | 245 { |
72 | 246 static if (false) { |
247 tym = tybasic(e1.ET.Tty); | |
248 if (!(tyscalar(tym) || | |
249 tym == TYM.TYstruct || | |
250 tym == TYM.TYarray && e.Eoper == TOK.TOKaddr)) | |
251 { | |
252 synerr(EM_lvalue); // lvalue expected | |
253 } | |
254 } | |
255 if (var.storage_class & STC.STClazy) | |
256 error("lazy variables cannot be lvalues"); | |
257 | |
0 | 258 return this; |
259 } | |
260 | |
72 | 261 override Expression modifiableLvalue(Scope sc, Expression e) |
0 | 262 { |
72 | 263 //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); |
109 | 264 //if (type && type.toBasetype().ty == TY.Tsarray) |
265 // error("cannot change reference to static array '%s'", var.toChars()); | |
72 | 266 |
267 var.checkModify(loc, sc, type); | |
268 | |
269 // See if this expression is a modifiable lvalue (i.e. not const) | |
0 | 270 return toLvalue(sc, e); |
271 } | |
272 | |
72 | 273 override dt_t** toDt(dt_t** pdt) |
0 | 274 { |
148 | 275 // writef("VarExp::toDt() %d\n", op); |
276 for (; *pdt; pdt = &((*pdt).DTnext)) | |
277 {} | |
278 | |
279 VarDeclaration v = var.isVarDeclaration(); | |
280 if (v && (v.isConst() || v.isImmutable()) && | |
281 type.toBasetype().ty != Tsarray && v.init) | |
282 { | |
283 if (v.inuse) | |
284 { | |
285 error("recursive reference %s", toChars()); | |
286 return pdt; | |
287 } | |
288 v.inuse++; | |
289 *pdt = v.init.toDt(); | |
290 v.inuse--; | |
291 return pdt; | |
292 } | |
293 SymbolDeclaration sd = var.isSymbolDeclaration(); | |
294 if (sd && sd.dsym) | |
295 { | |
296 sd.dsym.toDt(pdt); | |
297 return pdt; | |
298 } | |
299 debug writef("VarExp::toDt(), kind = %s\n", var.kind()); | |
300 | |
301 error("non-constant expression %s", toChars()); | |
302 pdt = dtnzeros(pdt, 1); | |
303 return pdt; | |
0 | 304 } |
305 | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
306 version(DMDV1) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
307 override elem* toElem(IRState* irs) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
308 { |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
309 assert(false); |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
310 } |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
311 |
72 | 312 override void scanForNestedRef(Scope sc) |
0 | 313 { |
72 | 314 //printf("VarExp.scanForNestedRef(%s)\n", toChars()); |
315 VarDeclaration v = var.isVarDeclaration(); | |
316 if (v) | |
64 | 317 v.checkNestedReference(sc, Loc(0)); |
0 | 318 } |
319 | |
72 | 320 override int inlineCost(InlineCostState* ics) |
0 | 321 { |
72 | 322 //printf("VarExp.inlineCost() %s\n", toChars()); |
0 | 323 return 1; |
324 } | |
325 | |
72 | 326 override Expression doInline(InlineDoState ids) |
0 | 327 { |
72 | 328 int i; |
329 | |
330 //printf("VarExp.doInline(%s)\n", toChars()); | |
331 for (i = 0; i < ids.from.dim; i++) | |
332 { | |
333 if (var == cast(Declaration)ids.from.data[i]) | |
334 { | |
335 VarExp ve = cast(VarExp)copy(); | |
336 | |
337 ve.var = cast(Declaration)ids.to.data[i]; | |
338 return ve; | |
339 } | |
340 } | |
0 | 341 return this; |
342 } | |
343 } | |
344 |