Mercurial > projects > ldc
comparison dmd/scope.c @ 1:c53b6e3fe49a trunk
[svn r5] Initial commit. Most things are very rough.
author | lindquist |
---|---|
date | Sat, 01 Sep 2007 21:43:27 +0200 |
parents | |
children | 8f704cb9969b |
comparison
equal
deleted
inserted
replaced
0:a9e71648e74d | 1:c53b6e3fe49a |
---|---|
1 | |
2 // Copyright (c) 1999-2005 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 #include <stdio.h> | |
11 #include <assert.h> | |
12 | |
13 #include "root.h" | |
14 | |
15 #include "mars.h" | |
16 #include "init.h" | |
17 #include "identifier.h" | |
18 #include "attrib.h" | |
19 #include "dsymbol.h" | |
20 #include "scope.h" | |
21 #include "declaration.h" | |
22 #include "aggregate.h" | |
23 #include "module.h" | |
24 #include "id.h" | |
25 | |
26 Scope *Scope::freelist = NULL; | |
27 | |
28 void *Scope::operator new(size_t size) | |
29 { | |
30 if (freelist) | |
31 { | |
32 Scope *s = freelist; | |
33 freelist = s->enclosing; | |
34 //printf("freelist %p\n", s); | |
35 assert(s->flags & SCOPEfree); | |
36 s->flags &= ~SCOPEfree; | |
37 return s; | |
38 } | |
39 | |
40 void *p = ::operator new(size); | |
41 //printf("new %p\n", p); | |
42 return p; | |
43 } | |
44 | |
45 Scope::Scope() | |
46 { // Create root scope | |
47 | |
48 //printf("Scope::Scope() %p\n", this); | |
49 this->module = NULL; | |
50 this->scopesym = NULL; | |
51 this->sd = NULL; | |
52 this->enclosing = NULL; | |
53 this->parent = NULL; | |
54 this->sw = NULL; | |
55 this->tf = NULL; | |
56 this->sbreak = NULL; | |
57 this->scontinue = NULL; | |
58 this->fes = NULL; | |
59 this->structalign = global.structalign; | |
60 this->func = NULL; | |
61 this->slabel = NULL; | |
62 this->linkage = LINKd; | |
63 this->protection = PROTpublic; | |
64 this->explicitProtection = 0; | |
65 this->stc = 0; | |
66 this->offset = 0; | |
67 this->inunion = 0; | |
68 this->incontract = 0; | |
69 this->nofree = 0; | |
70 this->noctor = 0; | |
71 this->intypeof = 0; | |
72 this->parameterSpecialization = 0; | |
73 this->callSuper = 0; | |
74 this->flags = 0; | |
75 this->anonAgg = NULL; | |
76 this->lastdc = NULL; | |
77 this->lastoffset = 0; | |
78 this->docbuf = NULL; | |
79 } | |
80 | |
81 Scope::Scope(Scope *enclosing) | |
82 { | |
83 //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this); | |
84 assert(!(enclosing->flags & SCOPEfree)); | |
85 this->module = enclosing->module; | |
86 this->func = enclosing->func; | |
87 this->parent = enclosing->parent; | |
88 this->scopesym = NULL; | |
89 this->sd = NULL; | |
90 this->sw = enclosing->sw; | |
91 this->tf = enclosing->tf; | |
92 this->sbreak = enclosing->sbreak; | |
93 this->scontinue = enclosing->scontinue; | |
94 this->fes = enclosing->fes; | |
95 this->structalign = enclosing->structalign; | |
96 this->enclosing = enclosing; | |
97 #ifdef DEBUG | |
98 if (enclosing->enclosing) | |
99 assert(!(enclosing->enclosing->flags & SCOPEfree)); | |
100 if (this == enclosing->enclosing) | |
101 { | |
102 printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing); | |
103 } | |
104 assert(this != enclosing->enclosing); | |
105 #endif | |
106 this->slabel = NULL; | |
107 this->linkage = enclosing->linkage; | |
108 this->protection = enclosing->protection; | |
109 this->explicitProtection = enclosing->explicitProtection; | |
110 this->stc = enclosing->stc; | |
111 this->offset = 0; | |
112 this->inunion = enclosing->inunion; | |
113 this->incontract = enclosing->incontract; | |
114 this->nofree = 0; | |
115 this->noctor = enclosing->noctor; | |
116 this->intypeof = enclosing->intypeof; | |
117 this->parameterSpecialization = enclosing->parameterSpecialization; | |
118 this->callSuper = enclosing->callSuper; | |
119 this->flags = 0; | |
120 this->anonAgg = NULL; | |
121 this->lastdc = NULL; | |
122 this->lastoffset = 0; | |
123 this->docbuf = enclosing->docbuf; | |
124 assert(this != enclosing); | |
125 } | |
126 | |
127 Scope *Scope::createGlobal(Module *module) | |
128 { | |
129 Scope *sc; | |
130 | |
131 sc = new Scope(); | |
132 sc->module = module; | |
133 sc->scopesym = new ScopeDsymbol(); | |
134 sc->scopesym->symtab = new DsymbolTable(); | |
135 | |
136 // Add top level package as member of this global scope | |
137 Dsymbol *m = module; | |
138 while (m->parent) | |
139 m = m->parent; | |
140 m->addMember(NULL, sc->scopesym, 1); | |
141 m->parent = NULL; // got changed by addMember() | |
142 | |
143 // Create the module scope underneath the global scope | |
144 sc = sc->push(module); | |
145 sc->parent = module; | |
146 return sc; | |
147 } | |
148 | |
149 Scope *Scope::push() | |
150 { | |
151 //printf("Scope::push()\n"); | |
152 Scope *s = new Scope(this); | |
153 assert(this != s); | |
154 return s; | |
155 } | |
156 | |
157 Scope *Scope::push(ScopeDsymbol *ss) | |
158 { | |
159 //printf("Scope::push(%s)\n", ss->toChars()); | |
160 Scope *s = push(); | |
161 s->scopesym = ss; | |
162 return s; | |
163 } | |
164 | |
165 Scope *Scope::pop() | |
166 { | |
167 //printf("Scope::pop() %p nofree = %d\n", this, nofree); | |
168 Scope *enc = enclosing; | |
169 | |
170 if (enclosing) | |
171 enclosing->callSuper |= callSuper; | |
172 | |
173 if (!nofree) | |
174 { enclosing = freelist; | |
175 freelist = this; | |
176 flags |= SCOPEfree; | |
177 } | |
178 | |
179 return enc; | |
180 } | |
181 | |
182 void Scope::mergeCallSuper(Loc loc, unsigned cs) | |
183 { | |
184 // This does a primitive flow analysis to support the restrictions | |
185 // regarding when and how constructors can appear. | |
186 // It merges the results of two paths. | |
187 // The two paths are callSuper and cs; the result is merged into callSuper. | |
188 | |
189 if (cs != callSuper) | |
190 { int a; | |
191 int b; | |
192 | |
193 callSuper |= cs & (CSXany_ctor | CSXlabel); | |
194 if (cs & CSXreturn) | |
195 { | |
196 } | |
197 else if (callSuper & CSXreturn) | |
198 { | |
199 callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel)); | |
200 } | |
201 else | |
202 { | |
203 a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0; | |
204 b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0; | |
205 if (a != b) | |
206 error(loc, "one path skips constructor"); | |
207 callSuper |= cs; | |
208 } | |
209 } | |
210 } | |
211 | |
212 Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym) | |
213 { Dsymbol *s; | |
214 Scope *sc; | |
215 | |
216 //printf("Scope::search(%p, '%s')\n", this, ident->toChars()); | |
217 if (ident == Id::empty) | |
218 { | |
219 // Look for module scope | |
220 for (sc = this; sc; sc = sc->enclosing) | |
221 { | |
222 assert(sc != sc->enclosing); | |
223 if (sc->scopesym) | |
224 { | |
225 s = sc->scopesym->isModule(); | |
226 if (s) | |
227 { | |
228 //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars()); | |
229 if (pscopesym) | |
230 *pscopesym = sc->scopesym; | |
231 return s; | |
232 } | |
233 } | |
234 } | |
235 return NULL; | |
236 } | |
237 | |
238 for (sc = this; sc; sc = sc->enclosing) | |
239 { | |
240 assert(sc != sc->enclosing); | |
241 if (sc->scopesym) | |
242 { | |
243 //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind()); | |
244 s = sc->scopesym->search(loc, ident, 0); | |
245 if (s) | |
246 { | |
247 if ((global.params.warnings || | |
248 global.params.Dversion > 1) && | |
249 ident == Id::length && | |
250 sc->scopesym->isArrayScopeSymbol() && | |
251 sc->enclosing && | |
252 sc->enclosing->search(loc, ident, NULL)) | |
253 { | |
254 if (global.params.warnings) | |
255 fprintf(stdmsg, "warning - "); | |
256 error(s->loc, "array 'length' hides other 'length' name in outer scope"); | |
257 } | |
258 | |
259 //printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind()); | |
260 if (pscopesym) | |
261 *pscopesym = sc->scopesym; | |
262 return s; | |
263 } | |
264 } | |
265 } | |
266 | |
267 return NULL; | |
268 } | |
269 | |
270 Dsymbol *Scope::insert(Dsymbol *s) | |
271 { Scope *sc; | |
272 | |
273 for (sc = this; sc; sc = sc->enclosing) | |
274 { | |
275 //printf("\tsc = %p\n", sc); | |
276 if (sc->scopesym) | |
277 { | |
278 //printf("\t\tsc->scopesym = %p\n", sc->scopesym); | |
279 if (!sc->scopesym->symtab) | |
280 sc->scopesym->symtab = new DsymbolTable(); | |
281 return sc->scopesym->symtab->insert(s); | |
282 } | |
283 } | |
284 assert(0); | |
285 return NULL; | |
286 } | |
287 | |
288 /******************************************** | |
289 * Search enclosing scopes for ClassDeclaration. | |
290 */ | |
291 | |
292 ClassDeclaration *Scope::getClassScope() | |
293 { Scope *sc; | |
294 | |
295 for (sc = this; sc; sc = sc->enclosing) | |
296 { | |
297 ClassDeclaration *cd; | |
298 | |
299 if (sc->scopesym) | |
300 { | |
301 cd = sc->scopesym->isClassDeclaration(); | |
302 if (cd) | |
303 return cd; | |
304 } | |
305 } | |
306 return NULL; | |
307 } | |
308 | |
309 /******************************************** | |
310 * Search enclosing scopes for ClassDeclaration. | |
311 */ | |
312 | |
313 AggregateDeclaration *Scope::getStructClassScope() | |
314 { Scope *sc; | |
315 | |
316 for (sc = this; sc; sc = sc->enclosing) | |
317 { | |
318 AggregateDeclaration *ad; | |
319 | |
320 if (sc->scopesym) | |
321 { | |
322 ad = sc->scopesym->isClassDeclaration(); | |
323 if (ad) | |
324 return ad; | |
325 else | |
326 { ad = sc->scopesym->isStructDeclaration(); | |
327 if (ad) | |
328 return ad; | |
329 } | |
330 } | |
331 } | |
332 return NULL; | |
333 } | |
334 | |
335 /******************************************* | |
336 * For TemplateDeclarations, we need to remember the Scope | |
337 * where it was declared. So mark the Scope as not | |
338 * to be free'd. | |
339 */ | |
340 | |
341 void Scope::setNoFree() | |
342 { Scope *sc; | |
343 //int i = 0; | |
344 | |
345 //printf("Scope::setNoFree(this = %p)\n", this); | |
346 for (sc = this; sc; sc = sc->enclosing) | |
347 { | |
348 //printf("\tsc = %p\n", sc); | |
349 sc->nofree = 1; | |
350 | |
351 assert(!(flags & SCOPEfree)); | |
352 //assert(sc != sc->enclosing); | |
353 //assert(!sc->enclosing || sc != sc->enclosing->enclosing); | |
354 //if (++i == 10) | |
355 //assert(0); | |
356 } | |
357 } |