comparison dmd/Scope.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 427f8aa74d28 26b9f97f6162
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
1 module dmd.Scope;
2
3 import dmd.Module;
4 import dmd.ScopeDsymbol;
5 import dmd.FuncDeclaration;
6 import dmd.Id;
7 import dmd.Dsymbol;
8 import dmd.LabelStatement;
9 import dmd.SwitchStatement;
10 import dmd.TryFinallyStatement;
11 import dmd.TemplateInstance;
12 import dmd.Statement;
13 import dmd.ForeachStatement;
14 import dmd.LINK;
15 import dmd.PROT;
16 import dmd.STC;
17 import dmd.AnonymousAggregateDeclaration;
18 import dmd.AggregateDeclaration;
19 import dmd.ClassDeclaration;
20 import dmd.Identifier;
21 import dmd.Loc;
22 import dmd.OutBuffer;
23 import dmd.DocComment;
24 import dmd.DsymbolTable;
25 import dmd.Global;
26 import dmd.CSX;
27 import dmd.Util;
28
29 enum SCOPE
30 {
31 SCOPEctor = 1, // constructor type
32 SCOPEstaticif = 2, // inside static if
33 SCOPEfree = 4, // is on free list
34 }
35
36 class Scope
37 {
38 Scope enclosing; // enclosing Scope
39
40 Module module_; // Root module
41 ScopeDsymbol scopesym; // current symbol
42 ScopeDsymbol sd; // if in static if, and declaring new symbols,
43 // sd gets the addMember()
44 FuncDeclaration func; // function we are in
45 Dsymbol parent; // parent to use
46 LabelStatement slabel; // enclosing labelled statement
47 SwitchStatement sw; // enclosing switch statement
48 TryFinallyStatement tf; // enclosing try finally statement
49 TemplateInstance tinst; // enclosing template instance
50 Statement sbreak; // enclosing statement that supports "break"
51 Statement scontinue; // enclosing statement that supports "continue"
52 ForeachStatement fes; // if nested function for ForeachStatement, this is it
53 uint offset; // next offset to use in aggregate
54 int inunion; // we're processing members of a union
55 int incontract; // we're inside contract code
56 int nofree; // set if shouldn't free it
57 int noctor; // set if constructor calls aren't allowed
58 int intypeof; // in typeof(exp)
59 int parameterSpecialization; // if in template parameter specialization
60 int noaccesscheck; // don't do access checks
61 int mustsemantic; // cannot defer semantic()
62
63 uint callSuper; // primitive flow analysis for constructors
64 ///#define CSXthis_ctor 1 // called this()
65 ///#define CSXsuper_ctor 2 // called super()
66 ///#define CSXthis 4 // referenced this
67 ///#define CSXsuper 8 // referenced super
68 ///#define CSXlabel 0x10 // seen a label
69 ///#define CSXreturn 0x20 // seen a return statement
70 ///#define CSXany_ctor 0x40 // either this() or super() was called
71
72 uint structalign; // alignment for struct members
73 LINK linkage = LINK.LINKd; // linkage for external functions
74
75 PROT protection = PROT.PROTpublic; // protection for class members
76 int explicitProtection; // set if in an explicit protection attribute
77
78 STC stc; // storage class
79
80 SCOPE flags;
81
82 AnonymousAggregateDeclaration anonAgg; // for temporary analysis
83
84 DocComment lastdc; // documentation comment for last symbol at this scope
85 uint lastoffset; // offset in docbuf of where to insert next dec
86 OutBuffer docbuf; // buffer for documentation output
87
88 static Scope freelist;
89 /// static void *operator new(size_t sz);
90 static Scope createGlobal(Module module_)
91 {
92 Scope sc = new Scope();
93 sc.module_ = module_;
94 sc.scopesym = new ScopeDsymbol();
95 sc.scopesym.symtab = new DsymbolTable();
96
97 // Add top level package as member of this global scope
98 Dsymbol m = module_;
99 while (m.parent !is null)
100 m = m.parent;
101
102 m.addMember(null, sc.scopesym, 1);
103 m.parent = null; // got changed by addMember()
104
105 // Create the module scope underneath the global scope
106 sc = sc.push(module_);
107 sc.parent = module_;
108 return sc;
109 }
110
111 this()
112 {
113 // Create root scope
114
115 //printf("Scope.Scope() %p\n", this);
116 this.structalign = global.structalign;
117 }
118
119 this(Module module_)
120 {
121 assert(false);
122 }
123
124 this(Scope enclosing)
125 {
126 //printf("Scope.Scope(enclosing = %p) %p\n", enclosing, this);
127 assert(!(enclosing.flags & SCOPE.SCOPEfree));
128 this.module_ = enclosing.module_;
129 this.func = enclosing.func;
130 this.parent = enclosing.parent;
131 this.sw = enclosing.sw;
132 this.tf = enclosing.tf;
133 this.tinst = enclosing.tinst;
134 this.sbreak = enclosing.sbreak;
135 this.scontinue = enclosing.scontinue;
136 this.fes = enclosing.fes;
137 this.structalign = enclosing.structalign;
138 this.enclosing = enclosing;
139 debug {
140 if (enclosing.enclosing)
141 assert(!(enclosing.enclosing.flags & SCOPE.SCOPEfree));
142
143 if (this is enclosing.enclosing) /// huh?
144 {
145 writef("this = %p, enclosing = %p, enclosing.enclosing = %p\n", this, enclosing, enclosing.enclosing);
146 }
147 assert(this !is enclosing.enclosing);
148 }
149 this.linkage = enclosing.linkage;
150 this.protection = enclosing.protection;
151 this.explicitProtection = enclosing.explicitProtection;
152 this.stc = enclosing.stc;
153 this.inunion = enclosing.inunion;
154 this.incontract = enclosing.incontract;
155 this.noctor = enclosing.noctor;
156 this.noaccesscheck = enclosing.noaccesscheck;
157 this.mustsemantic = enclosing.mustsemantic;
158 this.intypeof = enclosing.intypeof;
159 this.parameterSpecialization = enclosing.parameterSpecialization;
160 this.callSuper = enclosing.callSuper;
161 this.docbuf = enclosing.docbuf;
162 assert(this !is enclosing); /// huh?
163 }
164
165 Scope push()
166 {
167 //printf("Scope.push()\n");
168 Scope s = new Scope(this);
169 assert(this !is s); /// huh?
170 return s;
171 }
172
173 Scope push(ScopeDsymbol ss)
174 {
175 //printf("Scope.push(%s)\n", ss.toChars());
176 Scope s = push();
177 s.scopesym = ss;
178 return s;
179 }
180
181 Scope pop()
182 {
183 //printf("Scope.pop() %p nofree = %d\n", this, nofree);
184 Scope enc = enclosing;
185
186 if (enclosing)
187 enclosing.callSuper |= callSuper;
188
189 if (!nofree)
190 {
191 enclosing = freelist;
192 freelist = this;
193 flags |= SCOPE.SCOPEfree;
194 }
195
196 return enc;
197 }
198
199 void mergeCallSuper(Loc loc, uint cs)
200 {
201 // This does a primitive flow analysis to support the restrictions
202 // regarding when and how constructors can appear.
203 // It merges the results of two paths.
204 // The two paths are callSuper and cs; the result is merged into callSuper.
205
206 if (cs != callSuper)
207 {
208 int a;
209 int b;
210
211 callSuper |= cs & (CSX.CSXany_ctor | CSX.CSXlabel);
212 if (cs & CSX.CSXreturn)
213 {
214 ;
215 }
216 else if (callSuper & CSX.CSXreturn)
217 {
218 callSuper = cs | (callSuper & (CSX.CSXany_ctor | CSX.CSXlabel));
219 }
220 else
221 {
222 a = (cs & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0;
223 b = (callSuper & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0;
224
225 if (a != b)
226 error(loc, "one path skips constructor");
227 callSuper |= cs;
228 }
229 }
230 }
231
232 Dsymbol search(Loc loc, Identifier ident, Dsymbol* pscopesym)
233 {
234 Dsymbol s;
235 Scope sc;
236
237 //printf("Scope.search(%p, '%s')\n", this, ident.toChars());
238 if (ident is Id.empty)
239 {
240 // Look for module scope
241 for (sc = this; sc; sc = sc.enclosing)
242 {
243 assert(sc != sc.enclosing);
244 if (sc.scopesym)
245 {
246 s = sc.scopesym.isModule();
247 if (s)
248 {
249 //printf("\tfound %s.%s\n", s.parent ? s.parent.toChars() : "", s.toChars());
250 if (pscopesym)
251 *pscopesym = sc.scopesym;
252 return s;
253 }
254 }
255 }
256 return null;
257 }
258
259 for (sc = this; sc; sc = sc.enclosing)
260 {
261 assert(sc != sc.enclosing);
262 if (sc.scopesym)
263 {
264 //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc.scopesym.toChars(), sc.scopesym.kind());
265 s = sc.scopesym.search(loc, ident, 0);
266 if (s)
267 {
268 if ((global.params.warnings ||
269 global.params.Dversion > 1) &&
270 ident == Id.length &&
271 sc.scopesym.isArrayScopeSymbol() &&
272 sc.enclosing &&
273 sc.enclosing.search(loc, ident, null))
274 {
275 warning(s.loc, "array 'length' hides other 'length' name in outer scope");
276 }
277
278 //printf("\tfound %s.%s, kind = '%s'\n", s.parent ? s.parent.toChars() : "", s.toChars(), s.kind());
279 if (pscopesym)
280 *pscopesym = sc.scopesym;
281 return s;
282 }
283 }
284 }
285
286 return null;
287 }
288
289 Dsymbol insert(Dsymbol s)
290 {
291 for (Scope sc = this; sc; sc = sc.enclosing)
292 {
293 //printf("\tsc = %p\n", sc);
294 if (sc.scopesym)
295 {
296 //printf("\t\tsc.scopesym = %p\n", sc.scopesym);
297 if (!sc.scopesym.symtab)
298 sc.scopesym.symtab = new DsymbolTable();
299
300 return sc.scopesym.symtab.insert(s);
301 }
302 }
303
304 assert(false);
305 }
306
307 ClassDeclaration getClassScope()
308 {
309 assert(false);
310 }
311
312 /********************************************
313 * Search enclosing scopes for ClassDeclaration.
314 */
315 AggregateDeclaration getStructClassScope()
316 {
317 for (Scope sc = this; sc; sc = sc.enclosing)
318 {
319 AggregateDeclaration ad;
320
321 if (sc.scopesym)
322 {
323 ad = sc.scopesym.isClassDeclaration();
324 if (ad)
325 return ad;
326 else
327 {
328 ad = sc.scopesym.isStructDeclaration();
329 if (ad)
330 return ad;
331 }
332 }
333 }
334
335 return null;
336 }
337
338 void setNoFree()
339 {
340 //int i = 0;
341
342 //printf("Scope.setNoFree(this = %p)\n", this);
343 for (Scope sc = this; sc; sc = sc.enclosing)
344 {
345 //printf("\tsc = %p\n", sc);
346 sc.nofree = 1;
347
348 assert(!(flags & SCOPE.SCOPEfree));
349 //assert(sc != sc.enclosing);
350 //assert(!sc.enclosing || sc != sc.enclosing.enclosing);
351 //if (++i == 10)
352 //assert(0);
353 }
354 }
355 }