Mercurial > projects > ddmd
comparison dmd/DeclarationExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | cab4c37afb89 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.DeclarationExp; | |
2 | |
3 import dmd.Expression; | |
4 import dmd.backend.elem; | |
5 import dmd.InterState; | |
6 import dmd.ExpInitializer; | |
7 import dmd.OutBuffer; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
10 import dmd.InlineCostState; | |
11 import dmd.IRState; | |
12 import dmd.InlineDoState; | |
13 import dmd.HdrGenState; | |
14 import dmd.TupleDeclaration; | |
15 import dmd.InlineScanState; | |
16 import dmd.Dsymbol; | |
17 import dmd.AttribDeclaration; | |
18 import dmd.VarDeclaration; | |
19 import dmd.Global; | |
20 import dmd.TOK; | |
21 import dmd.VoidInitializer; | |
22 import dmd.Type; | |
23 import dmd.codegen.Util; | |
24 | |
25 // Declaration of a symbol | |
26 | |
27 class DeclarationExp : Expression | |
28 { | |
29 Dsymbol declaration; | |
30 | |
31 this(Loc loc, Dsymbol declaration) | |
32 { | |
33 super(loc, TOK.TOKdeclaration, DeclarationExp.sizeof); | |
34 this.declaration = declaration; | |
35 } | |
36 | |
37 Expression syntaxCopy() | |
38 { | |
39 return new DeclarationExp(loc, declaration.syntaxCopy(null)); | |
40 } | |
41 | |
42 Expression semantic(Scope sc) | |
43 { | |
44 if (type) | |
45 return this; | |
46 | |
47 version (LOGSEMANTIC) { | |
48 printf("DeclarationExp.semantic() %s\n", toChars()); | |
49 } | |
50 | |
51 /* This is here to support extern(linkage) declaration, | |
52 * where the extern(linkage) winds up being an AttribDeclaration | |
53 * wrapper. | |
54 */ | |
55 Dsymbol s = declaration; | |
56 | |
57 AttribDeclaration ad = declaration.isAttribDeclaration(); | |
58 if (ad) | |
59 { | |
60 if (ad.decl && ad.decl.dim == 1) | |
61 s = cast(Dsymbol)ad.decl.data[0]; | |
62 } | |
63 | |
64 if (s.isVarDeclaration()) | |
65 { | |
66 // Do semantic() on initializer first, so: | |
67 // int a = a; | |
68 // will be illegal. | |
69 declaration.semantic(sc); | |
70 s.parent = sc.parent; | |
71 } | |
72 | |
73 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc); | |
74 // Insert into both local scope and function scope. | |
75 // Must be unique in both. | |
76 if (s.ident) | |
77 { | |
78 if (!sc.insert(s)) | |
79 error("declaration %s is already defined", s.toPrettyChars()); | |
80 else if (sc.func) | |
81 { | |
82 VarDeclaration v = s.isVarDeclaration(); | |
83 if (s.isFuncDeclaration() && !sc.func.localsymtab.insert(s)) | |
84 error("declaration %s is already defined in another scope in %s", s.toPrettyChars(), sc.func.toChars()); | |
85 else if (!global.params.useDeprecated) | |
86 { | |
87 // Disallow shadowing | |
88 | |
89 for (Scope scx = sc.enclosing; scx && scx.func is sc.func; scx = scx.enclosing) | |
90 { | |
91 Dsymbol s2; | |
92 | |
93 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s !is s2) | |
94 { | |
95 error("shadowing declaration %s is deprecated", s.toPrettyChars()); | |
96 } | |
97 } | |
98 } | |
99 } | |
100 } | |
101 if (!s.isVarDeclaration()) | |
102 { | |
103 declaration.semantic(sc); | |
104 s.parent = sc.parent; | |
105 } | |
106 if (!global.errors) | |
107 { | |
108 declaration.semantic2(sc); | |
109 if (!global.errors) | |
110 { | |
111 declaration.semantic3(sc); | |
112 | |
113 if (!global.errors && global.params.useInline) | |
114 declaration.inlineScan(); | |
115 } | |
116 } | |
117 | |
118 type = Type.tvoid; | |
119 return this; | |
120 } | |
121 | |
122 Expression interpret(InterState* istate) | |
123 { | |
124 assert(false); | |
125 } | |
126 | |
127 bool checkSideEffect(int flag) | |
128 { | |
129 return true; | |
130 } | |
131 | |
132 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
133 { | |
134 declaration.toCBuffer(buf, hgs); | |
135 } | |
136 | |
137 elem* toElem(IRState* irs) | |
138 { | |
139 //printf("DeclarationExp::toElem() %s\n", toChars()); | |
140 elem* e = Dsymbol_toElem(declaration, irs); | |
141 return e; | |
142 } | |
143 | |
144 void scanForNestedRef(Scope sc) | |
145 { | |
146 assert(false); | |
147 } | |
148 | |
149 version (DMDV2) { | |
150 bool canThrow() | |
151 { | |
152 VarDeclaration v = declaration.isVarDeclaration(); | |
153 if (v && v.init) | |
154 { | |
155 ExpInitializer ie = v.init.isExpInitializer(); | |
156 return ie && ie.exp.canThrow(); | |
157 } | |
158 | |
159 return false; | |
160 } | |
161 } | |
162 int inlineCost(InlineCostState* ics) | |
163 { | |
164 int cost = 0; | |
165 VarDeclaration vd; | |
166 | |
167 //printf("DeclarationExp.inlineCost()\n"); | |
168 vd = declaration.isVarDeclaration(); | |
169 if (vd) | |
170 { | |
171 TupleDeclaration td = vd.toAlias().isTupleDeclaration(); | |
172 if (td) | |
173 { | |
174 static if (true) { | |
175 return COST_MAX; // finish DeclarationExp.doInline | |
176 } else { | |
177 for (size_t i = 0; i < td.objects.dim; i++) | |
178 { | |
179 Object o = cast(Object)td.objects.data[i]; | |
180 Expression eo = cast(Expression)o; | |
181 if (eo is null) | |
182 return COST_MAX; | |
183 | |
184 if (eo.op != TOKdsymbol) | |
185 return COST_MAX; | |
186 } | |
187 | |
188 return td.objects.dim; | |
189 } | |
190 } | |
191 if (!ics.hdrscan && vd.isDataseg()) | |
192 return COST_MAX; | |
193 | |
194 cost += 1; | |
195 | |
196 // Scan initializer (vd.init) | |
197 if (vd.init) | |
198 { | |
199 ExpInitializer ie = vd.init.isExpInitializer(); | |
200 | |
201 if (ie) | |
202 { | |
203 cost += ie.exp.inlineCost(ics); | |
204 } | |
205 } | |
206 } | |
207 | |
208 // These can contain functions, which when copied, get output twice. | |
209 if (declaration.isStructDeclaration() || | |
210 declaration.isClassDeclaration() || | |
211 declaration.isFuncDeclaration() || | |
212 declaration.isTypedefDeclaration() || | |
213 declaration.isTemplateMixin() | |
214 ) | |
215 return COST_MAX; | |
216 | |
217 //printf("DeclarationExp.inlineCost('%s')\n", toChars()); | |
218 return cost; | |
219 } | |
220 | |
221 Expression doInline(InlineDoState ids) | |
222 { | |
223 DeclarationExp de = cast(DeclarationExp)copy(); | |
224 VarDeclaration vd; | |
225 | |
226 //printf("DeclarationExp.doInline(%s)\n", toChars()); | |
227 vd = declaration.isVarDeclaration(); | |
228 if (vd) | |
229 { | |
230 static if (false) { | |
231 // Need to figure this out before inlining can work for tuples | |
232 TupleDeclaration td = vd.toAlias().isTupleDeclaration(); | |
233 if (td) | |
234 { | |
235 for (size_t i = 0; i < td.objects.dim; i++) | |
236 { | |
237 DsymbolExp se = cast(DsymbolExp)td.objects.data[i]; | |
238 assert(se.op == TOKdsymbol); | |
239 se.s; | |
240 } | |
241 return st.objects.dim; | |
242 } | |
243 } | |
244 if (vd.isStatic()) | |
245 { | |
246 ; | |
247 } | |
248 else | |
249 { | |
250 VarDeclaration vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init); | |
251 | |
252 ///*vto = *vd; | |
253 memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length); | |
254 | |
255 vto.parent = ids.parent; | |
256 vto.csym = null; | |
257 vto.isym = null; | |
258 | |
259 ids.from.push(cast(void*)vd); | |
260 ids.to.push(cast(void*)vto); | |
261 | |
262 if (vd.init) | |
263 { | |
264 if (vd.init.isVoidInitializer()) | |
265 { | |
266 vto.init = new VoidInitializer(vd.init.loc); | |
267 } | |
268 else | |
269 { | |
270 Expression e = vd.init.toExpression(); | |
271 assert(e); | |
272 vto.init = new ExpInitializer(e.loc, e.doInline(ids)); | |
273 } | |
274 } | |
275 de.declaration = vto; | |
276 } | |
277 } | |
278 /* This needs work, like DeclarationExp.toElem(), if we are | |
279 * to handle TemplateMixin's. For now, we just don't inline them. | |
280 */ | |
281 return de; | |
282 } | |
283 | |
284 Expression inlineScan(InlineScanState* iss) | |
285 { | |
286 //printf("DeclarationExp.inlineScan()\n"); | |
287 scanVar(declaration, iss); | |
288 return this; | |
289 } | |
290 } | |
291 |