Mercurial > projects > ddmd
annotate dmd/DeclarationExp.d @ 114:e28b18c23469
added a module dmd.common for commonly used stuff
it currently holds code for consistency checking of predefined versions
also added a VisualD project file
author | Trass3r |
---|---|
date | Wed, 01 Sep 2010 18:21:58 +0200 |
parents | 43073c7c7769 |
children | 9e39c7de8438 |
rev | line source |
---|---|
72 | 1 module dmd.DeclarationExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.backend.elem; | |
6 import dmd.InterState; | |
7 import dmd.ExpInitializer; | |
8 import dmd.OutBuffer; | |
9 import dmd.Loc; | |
79 | 10 import dmd.STC; |
72 | 11 import dmd.Scope; |
12 import dmd.InlineCostState; | |
13 import dmd.IRState; | |
14 import dmd.InlineDoState; | |
15 import dmd.HdrGenState; | |
16 import dmd.TupleDeclaration; | |
17 import dmd.InlineScanState; | |
18 import dmd.Dsymbol; | |
19 import dmd.AttribDeclaration; | |
20 import dmd.VarDeclaration; | |
21 import dmd.Global; | |
22 import dmd.TOK; | |
23 import dmd.VoidInitializer; | |
24 import dmd.GlobalExpressions; | |
25 import dmd.Type; | |
26 import dmd.codegen.Util; | |
27 | |
28 // Declaration of a symbol | |
29 | |
0 | 30 class DeclarationExp : Expression |
31 { | |
32 Dsymbol declaration; | |
33 | |
34 this(Loc loc, Dsymbol declaration) | |
35 { | |
72 | 36 super(loc, TOK.TOKdeclaration, DeclarationExp.sizeof); |
0 | 37 this.declaration = declaration; |
38 } | |
39 | |
72 | 40 override Expression syntaxCopy() |
0 | 41 { |
42 return new DeclarationExp(loc, declaration.syntaxCopy(null)); | |
43 } | |
44 | |
72 | 45 override Expression semantic(Scope sc) |
0 | 46 { |
72 | 47 if (type) |
48 return this; | |
49 | |
50 version (LOGSEMANTIC) { | |
51 printf("DeclarationExp.semantic() %s\n", toChars()); | |
52 } | |
53 | |
54 /* This is here to support extern(linkage) declaration, | |
55 * where the extern(linkage) winds up being an AttribDeclaration | |
56 * wrapper. | |
57 */ | |
58 Dsymbol s = declaration; | |
59 | |
60 AttribDeclaration ad = declaration.isAttribDeclaration(); | |
61 if (ad) | |
62 { | |
63 if (ad.decl && ad.decl.dim == 1) | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
64 s = ad.decl[0]; |
72 | 65 } |
66 | |
67 if (s.isVarDeclaration()) | |
68 { | |
69 // Do semantic() on initializer first, so: | |
70 // int a = a; | |
71 // will be illegal. | |
72 declaration.semantic(sc); | |
73 s.parent = sc.parent; | |
74 } | |
75 | |
76 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc); | |
77 // Insert into both local scope and function scope. | |
78 // Must be unique in both. | |
79 if (s.ident) | |
80 { | |
81 if (!sc.insert(s)) | |
82 error("declaration %s is already defined", s.toPrettyChars()); | |
83 else if (sc.func) | |
84 { | |
85 VarDeclaration v = s.isVarDeclaration(); | |
86 if (s.isFuncDeclaration() && !sc.func.localsymtab.insert(s)) | |
87 error("declaration %s is already defined in another scope in %s", s.toPrettyChars(), sc.func.toChars()); | |
88 else if (!global.params.useDeprecated) | |
89 { | |
90 // Disallow shadowing | |
91 | |
92 for (Scope scx = sc.enclosing; scx && scx.func is sc.func; scx = scx.enclosing) | |
93 { | |
94 Dsymbol s2; | |
95 | |
96 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s !is s2) | |
97 { | |
98 error("shadowing declaration %s is deprecated", s.toPrettyChars()); | |
99 } | |
100 } | |
101 } | |
102 } | |
103 } | |
104 if (!s.isVarDeclaration()) | |
105 { | |
79 | 106 Scope sc2 = sc; |
107 if (sc2.stc & (STC.STCpure | STC.STCnothrow)) | |
108 sc2 = sc.push(); | |
109 sc2.stc &= ~(STC.STCpure | STC.STCnothrow); | |
110 declaration.semantic(sc2); | |
111 if (sc2 != sc) | |
112 sc2.pop(); | |
113 | |
72 | 114 s.parent = sc.parent; |
115 } | |
116 if (!global.errors) | |
117 { | |
118 declaration.semantic2(sc); | |
119 if (!global.errors) | |
120 { | |
121 declaration.semantic3(sc); | |
122 | |
123 if (!global.errors && global.params.useInline) | |
124 declaration.inlineScan(); | |
125 } | |
126 } | |
127 | |
128 type = Type.tvoid; | |
0 | 129 return this; |
130 } | |
131 | |
72 | 132 override Expression interpret(InterState istate) |
0 | 133 { |
72 | 134 version (LOG) { |
135 printf("DeclarationExp.interpret() %s\n", toChars()); | |
136 } | |
137 Expression e; | |
138 VarDeclaration v = declaration.isVarDeclaration(); | |
139 if (v) | |
140 { | |
141 Dsymbol s = v.toAlias(); | |
142 if (s == v && !v.isStatic() && v.init) | |
143 { | |
144 ExpInitializer ie = v.init.isExpInitializer(); | |
145 if (ie) | |
146 e = ie.exp.interpret(istate); | |
147 else if (v.init.isVoidInitializer()) | |
148 e = null; | |
149 } | |
150 ///version (DMDV2) { | |
151 else if (s == v && (v.isConst() || v.isInvariant()) && v.init) | |
152 ///} else { | |
153 /// else if (s == v && v.isConst() && v.init) | |
154 ///} | |
155 { | |
156 e = v.init.toExpression(); | |
157 if (!e) | |
158 e = EXP_CANT_INTERPRET; | |
159 else if (!e.type) | |
160 e.type = v.type; | |
161 } | |
162 } | |
163 else if (declaration.isAttribDeclaration() || | |
164 declaration.isTemplateMixin() || | |
165 declaration.isTupleDeclaration()) | |
166 { | |
167 // These can be made to work, too lazy now | |
168 error("Declaration %s is not yet implemented in CTFE", toChars()); | |
169 | |
170 e = EXP_CANT_INTERPRET; | |
171 } | |
172 else | |
173 { // Others should not contain executable code, so are trivial to evaluate | |
174 e = null; | |
175 } | |
176 version (LOG) { | |
177 printf("-DeclarationExp.interpret(%.*s): %p\n", toChars(), e); | |
178 } | |
63 | 179 return e; |
0 | 180 } |
181 | |
72 | 182 override bool checkSideEffect(int flag) |
0 | 183 { |
184 return true; | |
185 } | |
186 | |
72 | 187 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 188 { |
189 declaration.toCBuffer(buf, hgs); | |
190 } | |
191 | |
72 | 192 override elem* toElem(IRState* irs) |
0 | 193 { |
72 | 194 //printf("DeclarationExp::toElem() %s\n", toChars()); |
195 elem* e = Dsymbol_toElem(declaration, irs); | |
0 | 196 return e; |
197 } | |
198 | |
72 | 199 override void scanForNestedRef(Scope sc) |
0 | 200 { |
201 assert(false); | |
202 } | |
72 | 203 |
0 | 204 version (DMDV2) { |
72 | 205 override bool canThrow() |
0 | 206 { |
72 | 207 VarDeclaration v = declaration.isVarDeclaration(); |
208 if (v && v.init) | |
209 { | |
210 ExpInitializer ie = v.init.isExpInitializer(); | |
211 return ie && ie.exp.canThrow(); | |
212 } | |
213 | |
0 | 214 return false; |
215 } | |
216 } | |
72 | 217 override int inlineCost(InlineCostState* ics) |
0 | 218 { |
72 | 219 int cost = 0; |
220 VarDeclaration vd; | |
221 | |
222 //printf("DeclarationExp.inlineCost()\n"); | |
223 vd = declaration.isVarDeclaration(); | |
224 if (vd) | |
225 { | |
226 TupleDeclaration td = vd.toAlias().isTupleDeclaration(); | |
227 if (td) | |
228 { | |
229 static if (true) { | |
230 return COST_MAX; // finish DeclarationExp.doInline | |
231 } else { | |
232 for (size_t i = 0; i < td.objects.dim; i++) | |
233 { | |
234 Object o = cast(Object)td.objects.data[i]; | |
235 Expression eo = cast(Expression)o; | |
236 if (eo is null) | |
237 return COST_MAX; | |
238 | |
239 if (eo.op != TOKdsymbol) | |
240 return COST_MAX; | |
241 } | |
242 | |
243 return td.objects.dim; | |
244 } | |
245 } | |
246 if (!ics.hdrscan && vd.isDataseg()) | |
247 return COST_MAX; | |
248 | |
249 cost += 1; | |
250 | |
251 // Scan initializer (vd.init) | |
252 if (vd.init) | |
253 { | |
254 ExpInitializer ie = vd.init.isExpInitializer(); | |
255 | |
256 if (ie) | |
257 { | |
258 cost += ie.exp.inlineCost(ics); | |
259 } | |
260 } | |
261 } | |
262 | |
263 // These can contain functions, which when copied, get output twice. | |
264 if (declaration.isStructDeclaration() || | |
265 declaration.isClassDeclaration() || | |
266 declaration.isFuncDeclaration() || | |
267 declaration.isTypedefDeclaration() || | |
268 declaration.isTemplateMixin() | |
269 ) | |
270 return COST_MAX; | |
271 | |
272 //printf("DeclarationExp.inlineCost('%s')\n", toChars()); | |
0 | 273 return cost; |
274 } | |
275 | |
72 | 276 override Expression doInline(InlineDoState ids) |
0 | 277 { |
72 | 278 DeclarationExp de = cast(DeclarationExp)copy(); |
279 VarDeclaration vd; | |
280 | |
281 //printf("DeclarationExp.doInline(%s)\n", toChars()); | |
282 vd = declaration.isVarDeclaration(); | |
283 if (vd) | |
284 { | |
285 static if (false) { | |
286 // Need to figure this out before inlining can work for tuples | |
287 TupleDeclaration td = vd.toAlias().isTupleDeclaration(); | |
288 if (td) | |
289 { | |
290 for (size_t i = 0; i < td.objects.dim; i++) | |
291 { | |
292 DsymbolExp se = cast(DsymbolExp)td.objects.data[i]; | |
293 assert(se.op == TOKdsymbol); | |
294 se.s; | |
295 } | |
296 return st.objects.dim; | |
297 } | |
298 } | |
299 if (vd.isStatic()) | |
300 { | |
301 ; | |
302 } | |
303 else | |
304 { | |
305 VarDeclaration vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init); | |
306 | |
307 ///*vto = *vd; | |
308 memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length); | |
309 | |
310 vto.parent = ids.parent; | |
311 vto.csym = null; | |
312 vto.isym = null; | |
313 | |
314 ids.from.push(cast(void*)vd); | |
315 ids.to.push(cast(void*)vto); | |
316 | |
317 if (vd.init) | |
318 { | |
319 if (vd.init.isVoidInitializer()) | |
320 { | |
321 vto.init = new VoidInitializer(vd.init.loc); | |
322 } | |
323 else | |
324 { | |
325 Expression e = vd.init.toExpression(); | |
326 assert(e); | |
327 vto.init = new ExpInitializer(e.loc, e.doInline(ids)); | |
328 } | |
329 } | |
330 de.declaration = vto; | |
331 } | |
332 } | |
333 /* This needs work, like DeclarationExp.toElem(), if we are | |
334 * to handle TemplateMixin's. For now, we just don't inline them. | |
335 */ | |
0 | 336 return de; |
337 } | |
338 | |
72 | 339 override Expression inlineScan(InlineScanState* iss) |
0 | 340 { |
72 | 341 //printf("DeclarationExp.inlineScan()\n"); |
342 scanVar(declaration, iss); | |
0 | 343 return this; |
344 } | |
345 } | |
346 |