Mercurial > projects > ddmd
annotate dmd/DotVarExp.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 | af1bebfd96a4 |
children |
rev | line source |
---|---|
72 | 1 module dmd.DotVarExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Declaration; | |
6 import dmd.backend.elem; | |
7 import dmd.UnaExp; | |
8 import dmd.InterState; | |
9 import dmd.OutBuffer; | |
10 import dmd.Loc; | |
11 import dmd.Scope; | |
12 import dmd.IRState; | |
13 import dmd.HdrGenState; | |
14 import dmd.TOK; | |
15 import dmd.TupleDeclaration; | |
16 import dmd.ArrayTypes; | |
17 import dmd.DsymbolExp; | |
18 import dmd.TupleExp; | |
19 import dmd.Global; | |
20 import dmd.Type; | |
21 import dmd.Dsymbol; | |
22 import dmd.AggregateDeclaration; | |
23 import dmd.VarDeclaration; | |
24 import dmd.WANT; | |
25 import dmd.TY; | |
26 import dmd.ErrorExp; | |
27 import dmd.FuncDeclaration; | |
28 import dmd.STC; | |
29 import dmd.GlobalExpressions; | |
30 import dmd.VarExp; | |
31 import dmd.StructLiteralExp; | |
32 import dmd.PREC; | |
33 | |
34 import dmd.expression.Util; | |
35 import dmd.codegen.Util; | |
36 import dmd.backend.Util; | |
37 import dmd.backend.mTY; | |
38 import dmd.backend.OPER; | |
39 import dmd.backend.TYM; | |
40 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
135
diff
changeset
|
41 import dmd.DDMDExtensions; |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
135
diff
changeset
|
42 |
0 | 43 class DotVarExp : UnaExp |
44 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
135
diff
changeset
|
45 mixin insertMemberExtension!(typeof(this)); |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
135
diff
changeset
|
46 |
0 | 47 Declaration var; |
48 | |
73 | 49 bool hasOverloads; |
0 | 50 |
73 | 51 this(Loc loc, Expression e, Declaration var, bool hasOverloads = false) |
0 | 52 { |
72 | 53 super(loc, TOK.TOKdotvar, DotVarExp.sizeof, e); |
54 //printf("DotVarExp()\n"); | |
55 this.var = var; | |
56 this.hasOverloads = hasOverloads; | |
0 | 57 } |
58 | |
72 | 59 override Expression semantic(Scope sc) |
0 | 60 { |
72 | 61 version (LOGSEMANTIC) { |
62 printf("DotVarExp.semantic('%s')\n", toChars()); | |
63 } | |
64 if (!type) | |
65 { | |
66 var = var.toAlias().isDeclaration(); | |
67 | |
68 TupleDeclaration tup = var.isTupleDeclaration(); | |
69 if (tup) | |
70 { | |
71 /* Replace: | |
72 * e1.tuple(a, b, c) | |
73 * with: | |
74 * tuple(e1.a, e1.b, e1.c) | |
75 */ | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
96
diff
changeset
|
76 auto exps = new Expressions; |
72 | 77 |
78 exps.reserve(tup.objects.dim); | |
113
3482c73a991b
More cleanup for arrays
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
96
diff
changeset
|
79 foreach (o; tup.objects) |
72 | 80 { |
81 if (auto e = cast(Expression)o) | |
82 { | |
83 if (e.op != TOK.TOKdsymbol) | |
84 error("%s is not a member", e.toChars()); | |
85 else | |
86 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
87 auto ve = cast(DsymbolExp)e; |
72 | 88 e = new DotVarExp(loc, e1, ve.s.isDeclaration()); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
73
diff
changeset
|
89 exps.push(e); |
72 | 90 } |
91 } else { | |
92 error("%s is not an expression", o.toString()); | |
93 } | |
94 } | |
95 Expression e = new TupleExp(loc, exps); | |
96 e = e.semantic(sc); | |
97 return e; | |
98 } | |
99 | |
100 e1 = e1.semantic(sc); | |
101 type = var.type; | |
102 if (!type && global.errors) | |
103 { | |
104 // var is goofed up, just return 0 | |
105 return new ErrorExp(); | |
106 } | |
107 assert(type); | |
108 | |
109 if (!var.isFuncDeclaration()) // for functions, do checks after overload resolution | |
110 { | |
111 Type t1 = e1.type; | |
112 if (t1.ty == TY.Tpointer) | |
113 t1 = t1.nextOf(); | |
114 | |
115 type = type.addMod(t1.mod); | |
116 | |
117 Dsymbol vparent = var.toParent(); | |
118 AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null; | |
119 e1 = getRightThis(loc, sc, ad, e1, var); | |
120 if (!sc.noaccesscheck) | |
121 accessCheck(loc, sc, e1, var); | |
122 | |
123 VarDeclaration v = var.isVarDeclaration(); | |
124 Expression e = expandVar(WANT.WANTvalue, v); | |
125 if (e) | |
126 return e; | |
127 } | |
128 } | |
129 //printf("-DotVarExp.semantic('%s')\n", toChars()); | |
0 | 130 return this; |
131 } | |
132 | |
96 | 133 override bool isLvalue() |
0 | 134 { |
96 | 135 return true; |
0 | 136 } |
137 | |
72 | 138 override Expression toLvalue(Scope sc, Expression e) |
0 | 139 { |
72 | 140 //printf("DotVarExp::toLvalue(%s)\n", toChars()); |
0 | 141 return this; |
142 } | |
143 | |
72 | 144 override Expression modifiableLvalue(Scope sc, Expression e) |
0 | 145 { |
72 | 146 static if (false) { |
147 printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); | |
148 printf("e1.type = %s\n", e1.type.toChars()); | |
149 printf("var.type = %s\n", var.type.toChars()); | |
150 } | |
151 | |
152 if (var.isCtorinit()) | |
153 { | |
154 // It's only modifiable if inside the right constructor | |
155 Dsymbol s = sc.func; | |
156 while (true) | |
157 { | |
158 FuncDeclaration fd = null; | |
159 if (s) | |
160 fd = s.isFuncDeclaration(); | |
161 if (fd && ((fd.isCtorDeclaration() && var.storage_class & STC.STCfield) || | |
162 (fd.isStaticCtorDeclaration() && !(var.storage_class & STC.STCfield))) && | |
163 fd.toParent() == var.toParent() && e1.op == TOK.TOKthis) | |
164 { | |
165 VarDeclaration v = var.isVarDeclaration(); | |
166 assert(v); | |
167 v.ctorinit = 1; | |
168 //printf("setting ctorinit\n"); | |
169 } | |
170 else | |
171 { | |
172 if (s) | |
173 { | |
174 s = s.toParent2(); | |
175 continue; | |
176 } | |
177 else | |
178 { | |
179 string p = var.isStatic() ? "static " : ""; | |
180 error("can only initialize %sconst member %s inside %sconstructor", p, var.toChars(), p); | |
181 } | |
182 } | |
183 break; | |
184 } | |
185 } | |
186 else | |
187 { | |
188 version (DMDV2) { | |
189 Type t1 = e1.type.toBasetype(); | |
190 | |
191 if (!t1.isMutable() || (t1.ty == TY.Tpointer && !t1.nextOf().isMutable()) || | |
192 !var.type.isMutable() || !var.type.isAssignable() || var.storage_class & STC.STCmanifest) | |
193 { | |
135 | 194 error("cannot modify const/immutable/inout expression %s", toChars()); |
72 | 195 } |
196 } | |
197 } | |
198 | |
0 | 199 return this; |
200 } | |
201 | |
72 | 202 override Expression optimize(int result) |
0 | 203 { |
96 | 204 //writef("DotVarExp.optimize(result = x%x) %s\n", result, toChars()); |
72 | 205 e1 = e1.optimize(result); |
206 | |
96 | 207 Expression e = e1; |
208 | |
72 | 209 if (e1.op == TOK.TOKvar) |
210 { | |
211 VarExp ve = cast(VarExp)e1; | |
212 VarDeclaration v = ve.var.isVarDeclaration(); | |
96 | 213 e = expandVar(result, v); |
72 | 214 } |
96 | 215 if (e && e.op == TOK.TOKstructliteral) |
216 { | |
217 StructLiteralExp sle = cast(StructLiteralExp) e; | |
72 | 218 VarDeclaration vf = var.isVarDeclaration(); |
219 if (vf) | |
220 { | |
96 | 221 e = sle.getField(type, vf.offset); |
72 | 222 if (e && e !is EXP_CANT_INTERPRET) |
223 return e; | |
224 } | |
225 } | |
226 | |
0 | 227 return this; |
228 } | |
229 | |
72 | 230 override Expression interpret(InterState istate) |
0 | 231 { |
123 | 232 Expression e = EXP_CANT_INTERPRET; |
233 | |
234 version (LOG) { | |
235 printf("DotVarExp.interpret() %.*s\n", toChars()); | |
236 } | |
237 | |
238 Expression ex = e1.interpret(istate); | |
239 if (ex !is EXP_CANT_INTERPRET) | |
240 { | |
241 if (ex.op == TOKstructliteral) | |
242 { | |
243 StructLiteralExp se = cast(StructLiteralExp)ex; | |
244 VarDeclaration v = var.isVarDeclaration(); | |
245 if (v) | |
246 { | |
247 e = se.getField(type, v.offset); | |
248 if (!e) | |
135 | 249 { |
250 error("couldn't find field %s in %s", v.toChars(), type.toChars()); | |
123 | 251 e = EXP_CANT_INTERPRET; |
135 | 252 } |
123 | 253 return e; |
254 } | |
135 | 255 } |
256 else | |
257 { | |
123 | 258 error("%s.%s is not yet implemented at compile time", ex.toChars(), var.toChars()); |
259 } | |
260 } | |
261 | |
262 version (LOG) { | |
263 if (e is EXP_CANT_INTERPRET) | |
264 printf("DotVarExp.interpret() %.*s = EXP_CANT_INTERPRET\n", toChars()); | |
265 } | |
266 return e; | |
0 | 267 } |
268 | |
72 | 269 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 270 { |
72 | 271 expToCBuffer(buf, hgs, e1, PREC.PREC_primary); |
272 buf.writeByte('.'); | |
0 | 273 buf.writestring(var.toChars()); |
274 } | |
275 | |
72 | 276 override void dump(int indent) |
0 | 277 { |
278 assert(false); | |
279 } | |
280 | |
72 | 281 override elem* toElem(IRState* irs) |
0 | 282 { |
72 | 283 // *(&e + offset) |
284 //printf("DotVarExp.toElem('%s')\n", toChars()); | |
285 | |
286 VarDeclaration v = var.isVarDeclaration(); | |
287 if (!v) | |
288 { | |
289 error("%s is not a field, but a %s", var.toChars(), var.kind()); | |
290 } | |
291 | |
292 elem* e = e1.toElem(irs); | |
293 Type tb1 = e1.type.toBasetype(); | |
294 | |
295 if (tb1.ty != TY.Tclass && tb1.ty != TY.Tpointer) | |
296 //e = el_una(OPaddr, TYnptr, e); | |
297 e = addressElem(e, tb1); | |
298 | |
299 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, v ? v.offset : 0)); | |
300 e = el_una(OPER.OPind, type.totym(), e); | |
301 if (tybasic(e.Ety) == TYM.TYstruct) | |
302 { | |
303 e.Enumbytes = cast(uint)type.size(); | |
304 } | |
305 el_setLoc(e,loc); | |
306 | |
0 | 307 return e; |
308 } | |
309 } | |
310 |