Mercurial > projects > ddmd
diff dmd/Scope.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 427f8aa74d28 26b9f97f6162 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/Scope.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,355 @@ +module dmd.Scope; + +import dmd.Module; +import dmd.ScopeDsymbol; +import dmd.FuncDeclaration; +import dmd.Id; +import dmd.Dsymbol; +import dmd.LabelStatement; +import dmd.SwitchStatement; +import dmd.TryFinallyStatement; +import dmd.TemplateInstance; +import dmd.Statement; +import dmd.ForeachStatement; +import dmd.LINK; +import dmd.PROT; +import dmd.STC; +import dmd.AnonymousAggregateDeclaration; +import dmd.AggregateDeclaration; +import dmd.ClassDeclaration; +import dmd.Identifier; +import dmd.Loc; +import dmd.OutBuffer; +import dmd.DocComment; +import dmd.DsymbolTable; +import dmd.Global; +import dmd.CSX; +import dmd.Util; + +enum SCOPE +{ + SCOPEctor = 1, // constructor type + SCOPEstaticif = 2, // inside static if + SCOPEfree = 4, // is on free list +} + +class Scope +{ + Scope enclosing; // enclosing Scope + + Module module_; // Root module + ScopeDsymbol scopesym; // current symbol + ScopeDsymbol sd; // if in static if, and declaring new symbols, + // sd gets the addMember() + FuncDeclaration func; // function we are in + Dsymbol parent; // parent to use + LabelStatement slabel; // enclosing labelled statement + SwitchStatement sw; // enclosing switch statement + TryFinallyStatement tf; // enclosing try finally statement + TemplateInstance tinst; // enclosing template instance + Statement sbreak; // enclosing statement that supports "break" + Statement scontinue; // enclosing statement that supports "continue" + ForeachStatement fes; // if nested function for ForeachStatement, this is it + uint offset; // next offset to use in aggregate + int inunion; // we're processing members of a union + int incontract; // we're inside contract code + int nofree; // set if shouldn't free it + int noctor; // set if constructor calls aren't allowed + int intypeof; // in typeof(exp) + int parameterSpecialization; // if in template parameter specialization + int noaccesscheck; // don't do access checks + int mustsemantic; // cannot defer semantic() + + uint callSuper; // primitive flow analysis for constructors +///#define CSXthis_ctor 1 // called this() +///#define CSXsuper_ctor 2 // called super() +///#define CSXthis 4 // referenced this +///#define CSXsuper 8 // referenced super +///#define CSXlabel 0x10 // seen a label +///#define CSXreturn 0x20 // seen a return statement +///#define CSXany_ctor 0x40 // either this() or super() was called + + uint structalign; // alignment for struct members + LINK linkage = LINK.LINKd; // linkage for external functions + + PROT protection = PROT.PROTpublic; // protection for class members + int explicitProtection; // set if in an explicit protection attribute + + STC stc; // storage class + + SCOPE flags; + + AnonymousAggregateDeclaration anonAgg; // for temporary analysis + + DocComment lastdc; // documentation comment for last symbol at this scope + uint lastoffset; // offset in docbuf of where to insert next dec + OutBuffer docbuf; // buffer for documentation output + + static Scope freelist; +/// static void *operator new(size_t sz); + static Scope createGlobal(Module module_) + { + Scope sc = new Scope(); + sc.module_ = module_; + sc.scopesym = new ScopeDsymbol(); + sc.scopesym.symtab = new DsymbolTable(); + + // Add top level package as member of this global scope + Dsymbol m = module_; + while (m.parent !is null) + m = m.parent; + + m.addMember(null, sc.scopesym, 1); + m.parent = null; // got changed by addMember() + + // Create the module scope underneath the global scope + sc = sc.push(module_); + sc.parent = module_; + return sc; + } + + this() + { + // Create root scope + + //printf("Scope.Scope() %p\n", this); + this.structalign = global.structalign; + } + + this(Module module_) + { + assert(false); + } + + this(Scope enclosing) + { + //printf("Scope.Scope(enclosing = %p) %p\n", enclosing, this); + assert(!(enclosing.flags & SCOPE.SCOPEfree)); + this.module_ = enclosing.module_; + this.func = enclosing.func; + this.parent = enclosing.parent; + this.sw = enclosing.sw; + this.tf = enclosing.tf; + this.tinst = enclosing.tinst; + this.sbreak = enclosing.sbreak; + this.scontinue = enclosing.scontinue; + this.fes = enclosing.fes; + this.structalign = enclosing.structalign; + this.enclosing = enclosing; +debug { + if (enclosing.enclosing) + assert(!(enclosing.enclosing.flags & SCOPE.SCOPEfree)); + + if (this is enclosing.enclosing) /// huh? + { + writef("this = %p, enclosing = %p, enclosing.enclosing = %p\n", this, enclosing, enclosing.enclosing); + } + assert(this !is enclosing.enclosing); +} + this.linkage = enclosing.linkage; + this.protection = enclosing.protection; + this.explicitProtection = enclosing.explicitProtection; + this.stc = enclosing.stc; + this.inunion = enclosing.inunion; + this.incontract = enclosing.incontract; + this.noctor = enclosing.noctor; + this.noaccesscheck = enclosing.noaccesscheck; + this.mustsemantic = enclosing.mustsemantic; + this.intypeof = enclosing.intypeof; + this.parameterSpecialization = enclosing.parameterSpecialization; + this.callSuper = enclosing.callSuper; + this.docbuf = enclosing.docbuf; + assert(this !is enclosing); /// huh? + } + + Scope push() + { + //printf("Scope.push()\n"); + Scope s = new Scope(this); + assert(this !is s); /// huh? + return s; + } + + Scope push(ScopeDsymbol ss) + { + //printf("Scope.push(%s)\n", ss.toChars()); + Scope s = push(); + s.scopesym = ss; + return s; + } + + Scope pop() + { + //printf("Scope.pop() %p nofree = %d\n", this, nofree); + Scope enc = enclosing; + + if (enclosing) + enclosing.callSuper |= callSuper; + + if (!nofree) + { + enclosing = freelist; + freelist = this; + flags |= SCOPE.SCOPEfree; + } + + return enc; + } + + void mergeCallSuper(Loc loc, uint cs) + { + // This does a primitive flow analysis to support the restrictions + // regarding when and how constructors can appear. + // It merges the results of two paths. + // The two paths are callSuper and cs; the result is merged into callSuper. + + if (cs != callSuper) + { + int a; + int b; + + callSuper |= cs & (CSX.CSXany_ctor | CSX.CSXlabel); + if (cs & CSX.CSXreturn) + { + ; + } + else if (callSuper & CSX.CSXreturn) + { + callSuper = cs | (callSuper & (CSX.CSXany_ctor | CSX.CSXlabel)); + } + else + { + a = (cs & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0; + b = (callSuper & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0; + + if (a != b) + error(loc, "one path skips constructor"); + callSuper |= cs; + } + } + } + + Dsymbol search(Loc loc, Identifier ident, Dsymbol* pscopesym) + { + Dsymbol s; + Scope sc; + + //printf("Scope.search(%p, '%s')\n", this, ident.toChars()); + if (ident is Id.empty) + { + // Look for module scope + for (sc = this; sc; sc = sc.enclosing) + { + assert(sc != sc.enclosing); + if (sc.scopesym) + { + s = sc.scopesym.isModule(); + if (s) + { + //printf("\tfound %s.%s\n", s.parent ? s.parent.toChars() : "", s.toChars()); + if (pscopesym) + *pscopesym = sc.scopesym; + return s; + } + } + } + return null; + } + + for (sc = this; sc; sc = sc.enclosing) + { + assert(sc != sc.enclosing); + if (sc.scopesym) + { + //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc.scopesym.toChars(), sc.scopesym.kind()); + s = sc.scopesym.search(loc, ident, 0); + if (s) + { + if ((global.params.warnings || + global.params.Dversion > 1) && + ident == Id.length && + sc.scopesym.isArrayScopeSymbol() && + sc.enclosing && + sc.enclosing.search(loc, ident, null)) + { + warning(s.loc, "array 'length' hides other 'length' name in outer scope"); + } + + //printf("\tfound %s.%s, kind = '%s'\n", s.parent ? s.parent.toChars() : "", s.toChars(), s.kind()); + if (pscopesym) + *pscopesym = sc.scopesym; + return s; + } + } + } + + return null; + } + + Dsymbol insert(Dsymbol s) + { + for (Scope sc = this; sc; sc = sc.enclosing) + { + //printf("\tsc = %p\n", sc); + if (sc.scopesym) + { + //printf("\t\tsc.scopesym = %p\n", sc.scopesym); + if (!sc.scopesym.symtab) + sc.scopesym.symtab = new DsymbolTable(); + + return sc.scopesym.symtab.insert(s); + } + } + + assert(false); + } + + ClassDeclaration getClassScope() + { + assert(false); + } + + /******************************************** + * Search enclosing scopes for ClassDeclaration. + */ + AggregateDeclaration getStructClassScope() + { + for (Scope sc = this; sc; sc = sc.enclosing) + { + AggregateDeclaration ad; + + if (sc.scopesym) + { + ad = sc.scopesym.isClassDeclaration(); + if (ad) + return ad; + else + { + ad = sc.scopesym.isStructDeclaration(); + if (ad) + return ad; + } + } + } + + return null; + } + + void setNoFree() + { + //int i = 0; + + //printf("Scope.setNoFree(this = %p)\n", this); + for (Scope sc = this; sc; sc = sc.enclosing) + { + //printf("\tsc = %p\n", sc); + sc.nofree = 1; + + assert(!(flags & SCOPE.SCOPEfree)); + //assert(sc != sc.enclosing); + //assert(!sc.enclosing || sc != sc.enclosing.enclosing); + //if (++i == 10) + //assert(0); + } + } +} \ No newline at end of file