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