Mercurial > projects > ddmd
view dmd/Dsymbol.d @ 32:81796b717a39
A few bad cast fixed. TODO: either get rid of dyncast(), or derive all objects from intermediate supertype.
author | korDen |
---|---|
date | Tue, 18 May 2010 17:51:46 +0400 |
parents | 460959608115 |
children | ccbc1e0bb3f0 |
line wrap: on
line source
module dmd.Dsymbol; import dmd.Loc; import dmd.STC; import dmd.Scope; import dmd.Lexer; import dmd.Module; import dmd.Array; import dmd.ScopeDsymbol; import dmd.OutBuffer; import dmd.Id; import dmd.Identifier; import dmd.TemplateInstance; import dmd.HdrGenState; import dmd.AggregateDeclaration; import dmd.ClassDeclaration; import dmd.LabelDsymbol; import dmd.Type; import dmd.PROT; import dmd.ArrayTypes; import dmd.Package; import dmd.EnumMember; import dmd.TemplateDeclaration; import dmd.TemplateMixin; import dmd.Declaration; import dmd.ThisDeclaration; import dmd.TupleDeclaration; import dmd.TypedefDeclaration; import dmd.AliasDeclaration; import dmd.FuncDeclaration; import dmd.FuncAliasDeclaration; import dmd.FuncLiteralDeclaration; import dmd.CtorDeclaration; import dmd.PostBlitDeclaration; import dmd.DtorDeclaration; import dmd.StaticCtorDeclaration; import dmd.StaticDtorDeclaration; import dmd.InvariantDeclaration; import dmd.UnitTestDeclaration; import dmd.NewDeclaration; import dmd.VarDeclaration; import dmd.StructDeclaration; import dmd.UnionDeclaration; import dmd.InterfaceDeclaration; import dmd.WithScopeSymbol; import dmd.ArrayScopeSymbol; import dmd.Import; import dmd.EnumDeclaration; import dmd.DeleteDeclaration; import dmd.SymbolDeclaration; import dmd.AttribDeclaration; import dmd.OverloadSet; import dmd.DYNCAST; import dmd.Global; import dmd.Expression; import dmd.TOK; import dmd.VarExp; import dmd.FuncExp; import dmd.backend.Symbol; import dmd.backend.TYPE; import dmd.backend.Util; import dmd.backend.mTYman; import dmd.backend.TYFL; import dmd.backend.TYM; import dmd.backend.mTY; import dmd.backend.SC; import dmd.backend.FL; import dmd.backend.LIST; import core.stdc.string : strcmp, memcpy, strlen; version (Bug4054) import core.memory; else import core.stdc.stdlib : alloca; import std.stdio; // TODO: remove dependencies on these Expression isExpression(Object o) { return cast(Expression)o; } Dsymbol isDsymbol(Object o) { return cast(Dsymbol)o; } Type isType(Object o) { return cast(Type)o; } /*********************** * Try to get arg as a type. */ Type getType(Object o) { Type t = isType(o); if (!t) { Expression e = isExpression(o); if (e) t = e.type; } return t; } Dsymbol getDsymbol(Object oarg) { Dsymbol sa; Expression ea = isExpression(oarg); if (ea) { // Try to convert Expression to symbol if (ea.op == TOK.TOKvar) sa = (cast(VarExp)ea).var; else if (ea.op == TOK.TOKfunction) sa = (cast(FuncExp)ea).fd; else sa = null; } else { // Try to convert Type to symbol Type ta = isType(oarg); if (ta) sa = ta.toDsymbol(null); else sa = isDsymbol(oarg); // if already a symbol } return sa; } class Dsymbol { Identifier ident; Identifier c_ident; Dsymbol parent; Symbol* csym; // symbol for code generator Symbol* isym; // import version of csym ubyte* comment; // documentation comment for this Dsymbol Loc loc; // where defined Scope scope_; // !=null means context to use for semantic() this() { // do nothing } this(Identifier ident) { this.ident = ident; } string toChars() { return ident ? ident.toChars() : "__anonymous"; } string locToChars() { scope OutBuffer buf = new OutBuffer(); Module m = getModule(); if (m && m.srcfile) loc.filename = m.srcfile.toChars(); return loc.toChars(); } int equals(Object o) { assert(false); } bool isAnonymous() { return ident ? 0 : 1; } void error(T...)(Loc loc, string format, T t) { if (!global.gag) { string p = loc.toChars(); if (p.length == 0) p = locToChars(); if (p.length != 0) { writef("%s: ", p); } write("Error: "); writef("%s %s ", kind(), toPrettyChars()); writefln(format, t); } global.errors++; //fatal(); } void error(T...)(string format, T t) { //printf("Dsymbol.error()\n"); if (!global.gag) { string p = loc.toChars(); if (p.length != 0) { writef("%s: ", p); } write("Error: "); if (isAnonymous()) { writef("%s ", kind()); } else { writef("%s %s ", kind(), toPrettyChars()); } writefln(format, t); } global.errors++; //fatal(); } void checkDeprecated(Loc loc, Scope sc) { if (!global.params.useDeprecated && isDeprecated()) { // Don't complain if we're inside a deprecated symbol's scope for (Dsymbol sp = sc.parent; sp; sp = sp.parent) { if (sp.isDeprecated()) return; } for (; sc; sc = sc.enclosing) { if (sc.scopesym && sc.scopesym.isDeprecated()) return; // If inside a StorageClassDeclaration that is deprecated if (sc.stc & STC.STCdeprecated) return; } error(loc, "is deprecated"); } } Module getModule() { //printf("Dsymbol.getModule()\n"); Dsymbol s = this; while (s) { //printf("\ts = '%s'\n", s.toChars()); Module m = s.isModule(); if (m) return m; s = s.parent; } return null; } Dsymbol pastMixin() { Dsymbol s = this; //printf("Dsymbol::pastMixin() %s\n", toChars()); while (s && s.isTemplateMixin()) s = s.parent; return s; } Dsymbol toParent() { return parent ? parent.pastMixin() : null; } /********************************** * Use this instead of toParent() when looking for the * 'this' pointer of the enclosing function/class. */ Dsymbol toParent2() { Dsymbol s = parent; while (s && s.isTemplateInstance()) s = s.parent; return s; } TemplateInstance inTemplateInstance() { for (Dsymbol parent = this.parent; parent; parent = parent.parent) { TemplateInstance ti = parent.isTemplateInstance(); if (ti) return ti; } return null; } DYNCAST dyncast() { return DYNCAST.DYNCAST_DSYMBOL; } // kludge for template.isSymbol() /************************************* * Do syntax copy of an array of Dsymbol's. */ static Array arraySyntaxCopy(Array a) { Array b = null; if (a) { b = a.copy(); for (int i = 0; i < b.dim; i++) { Dsymbol s = cast(Dsymbol)b.data[i]; s = s.syntaxCopy(null); b.data[i] = cast(void*)s; } } return b; } string toPrettyChars() { //printf("Dsymbol.toPrettyChars() '%s'\n", toChars()); if (!parent) { return toChars(); } size_t len = 0; for (Dsymbol p = this; p; p = p.parent) { len += p.toChars().length + 1; } --len; version (Bug4054) char* s = cast(char*)GC.malloc(len); else char* s = cast(char*)alloca(len); char* q = s + len; for (Dsymbol p = this; p; p = p.parent) { string t = p.toChars(); size_t length = t.length; q -= length; memcpy(q, t.ptr, length); if (q is s) break; q--; version (TARGET_NET) { if (AggregateDeclaration ad = p.isAggregateDeclaration()) { if (ad.isNested() && p.parent && p.parent.isAggregateDeclaration()) { *q = '/'; continue; } } } *q = '.'; } return s[0..len].idup; } string kind() { assert(false); } /********************************* * If this symbol is really an alias for another, * return that other. */ Dsymbol toAlias() // resolve real symbol { return this; } bool addMember(Scope sc, ScopeDsymbol sd, bool memnum) { //printf("Dsymbol.addMember('%s')\n", toChars()); //printf("Dsymbol.addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd.toChars()); assert(sd !is null); parent = sd; if (!isAnonymous()) // no name, so can't add it to symbol table { if (!sd.symtab.insert(this)) // if name is already defined { Dsymbol s2 = sd.symtab.lookup(ident); if (!s2.overloadInsert(this)) { sd.multiplyDefined(Loc(0), this, s2); } } if (sd.isAggregateDeclaration() || sd.isEnumDeclaration()) { if (ident is Id.__sizeof || ident is Id.alignof_ || ident is Id.mangleof_) error(".%s property cannot be redefined", ident.toChars()); } return true; } return false; } void setScope(Scope sc) { //printf("Dsymbol.setScope() %p %s\n", this, toChars()); if (!sc.nofree) sc.setNoFree(); // may need it even after semantic() finishes scope_ = sc; } void semantic(Scope sc) { assert(false); } /************************************* * Does semantic analysis on initializers and members of aggregates. */ void semantic2(Scope sc) { // Most Dsymbols have no further semantic analysis needed } /************************************* * Does semantic analysis on function bodies. */ void semantic3(Scope sc) { // Most Dsymbols have no further semantic analysis needed } /************************************* * Look for function inlining possibilities. */ void inlineScan() { // Most Dsymbols aren't functions } Dsymbol search(Loc loc, Identifier ident, int flags) { assert(false); } /*************************************** * Search for identifier id as a member of 'this'. * id may be a template instance. * Returns: * symbol found, null if not */ Dsymbol searchX(Loc loc, Scope sc, Identifier id) { //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); Dsymbol s = toAlias(); Dsymbol sm; /// HUH???? switch (id.dyncast()) { case DYNCAST.DYNCAST_IDENTIFIER: sm = s.search(loc, id, 0); break; case DYNCAST.DYNCAST_DSYMBOL: { assert(false); /// how can it happen? // It's a template instance //printf("\ttemplate instance id\n"); Dsymbol st = cast(Dsymbol)id; TemplateInstance ti = st.isTemplateInstance(); id = ti.name; sm = s.search(loc, id, 0); if (!sm) { error("template identifier %s is not a member of %s %s", id.toChars(), s.kind(), s.toChars()); return null; } sm = sm.toAlias(); TemplateDeclaration td = sm.isTemplateDeclaration(); if (!td) { error("%s is not a template, it is a %s", id.toChars(), sm.kind()); return null; } ti.tempdecl = td; if (!ti.semanticRun) ti.semantic(sc); sm = ti.toAlias(); break; } default: assert(0); } return sm; } bool overloadInsert(Dsymbol s) { assert(false); } version (_DH) { char* toHChars() { assert(false); } void toHBuffer(OutBuffer buf, HdrGenState* hgs) { assert(false); } } void toCBuffer(OutBuffer buf, HdrGenState* hgs) { assert(false); } void toDocBuffer(OutBuffer buf) { assert(false); } uint size(Loc loc) { assert(false); } int isforwardRef() { assert(false); } void defineRef(Dsymbol s) { assert(false); } AggregateDeclaration isThis() // is a 'this' required to access the member { assert(false); } ClassDeclaration isClassMember() // are we a member of a class? { Dsymbol parent = toParent(); if (parent && parent.isClassDeclaration()) return cast(ClassDeclaration)parent; return null; } bool isExport() // is Dsymbol exported? { return false; } bool isImportedSymbol() // is Dsymbol imported? { return false; } bool isDeprecated() // is Dsymbol deprecated? { return false; } version (DMDV2) { bool isOverloadable() { return false; } } LabelDsymbol isLabel() // is this a LabelDsymbol? { return null; } AggregateDeclaration isMember() // is this symbol a member of an AggregateDeclaration? { //printf("Dsymbol::isMember() %s\n", toChars()); Dsymbol parent = toParent(); //printf("parent is %s %s\n", parent.kind(), parent.toChars()); return parent ? parent.isAggregateDeclaration() : null; } Type getType() // is this a type? { return null; } string mangle() { OutBuffer buf = new OutBuffer(); string id; static if (false) { printf("Dsymbol::mangle() '%s'", toChars()); if (parent) printf(" parent = %s %s", parent.kind(), parent.toChars()); printf("\n"); } id = ident ? ident.toChars() : toChars(); if (parent) { string p = parent.mangle(); if (p[0] == '_' && p[1] == 'D') p = p[2..$]; buf.writestring(p); } ///buf.printf("%zu%s", id.length, id); buf.printf("%d%s", id.length, id); id = buf.toChars(); buf.data = null; //printf("Dsymbol::mangle() %s = %s\n", toChars(), id); return id; } bool needThis() // need a 'this' pointer? { return false; } PROT prot() { assert(false); } Dsymbol syntaxCopy(Dsymbol s) // copy only syntax trees { assert(false); } /************************************** * Determine if this symbol is only one. * Returns: * false, *ps = null: There are 2 or more symbols * true, *ps = null: There are zero symbols * true, *ps = symbol: The one and only one symbol */ bool oneMember(Dsymbol* ps) { //printf("Dsymbol::oneMember()\n"); *ps = this; return true; } /***************************************** * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. */ static bool oneMembers(Array members, Dsymbol* ps) { //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0); Dsymbol s = null; if (members) { for (int i = 0; i < members.dim; i++) { Dsymbol sx = cast(Dsymbol)members.data[i]; bool x = sx.oneMember(ps); //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); if (!x) { //printf("\tfalse 1\n"); assert(*ps is null); return false; } if (*ps) { if (s) // more than one symbol { *ps = null; //printf("\tfalse 2\n"); return false; } s = *ps; } } } *ps = s; // s is the one symbol, null if none //printf("\ttrue\n"); return true; } /***************************************** * Is Dsymbol a variable that contains pointers? */ bool hasPointers() { //printf("Dsymbol::hasPointers() %s\n", toChars()); return 0; } void addLocalClass(ClassDeclarations) { } void checkCtorConstInit() { } void addComment(ubyte* comment) { //if (comment) //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); if (this.comment is null) { this.comment = comment; } else { static if (true) { if (comment !is null && strcmp(cast(char*)comment, cast(char*)this.comment) != 0) { // Concatenate the two this.comment = Lexer.combineComments(this.comment, comment); } } } } void emitComment(Scope sc) { assert(false); } void emitDitto(Scope sc) { assert(false); } // Backend Symbol* toSymbol() // to backend symbol { assert(false); } void toObjFile(int multiobj) // compile to .obj file { //printf("Dsymbol::toObjFile('%s')\n", toChars()); // ignore } int cvMember(ubyte* p) // emit cv debug info for member { assert(false); } /********************************* * Generate import symbol from symbol. */ Symbol* toImport() // to backend import symbol { if (!isym) { if (!csym) csym = toSymbol(); isym = toImport(csym); } return isym; } static Symbol* toImport(Symbol* sym) // to backend import symbol { char* id; char* n; Symbol* s; type* t; //printf("Dsymbol::toImport('%s')\n", sym->Sident); n = sym.Sident.ptr; version (Bug4054) id = cast(char*) GC.malloc(6 + strlen(n) + 1 + (type_paramsize_i(sym.Stype)).sizeof*3 + 1); else id = cast(char*) alloca(6 + strlen(n) + 1 + (type_paramsize_i(sym.Stype)).sizeof*3 + 1); if (sym.Stype.Tmangle == mTYman_std && tyfunc(sym.Stype.Tty)) { sprintf(id, "_imp__%s@%lu", n, type_paramsize_i(sym.Stype)); } else if (sym.Stype.Tmangle == mTYman_d) sprintf(id,"_imp_%s",n); else sprintf(id,"_imp__%s",n); t = type_alloc(TYnptr | mTYconst); t.Tnext = sym.Stype; t.Tnext.Tcount++; t.Tmangle = mTYman_c; t.Tcount++; s = symbol_calloc(id); s.Stype = t; s.Sclass = SCextern; s.Sfl = FLextern; slist_add(s); return s; } Symbol* toSymbolX(string prefix, int sclass, TYPE* t, string suffix) // helper { Symbol* s; char* id; string n; size_t nlen; //writef("Dsymbol::toSymbolX('%s', '%s')\n", prefix, this.classinfo.name); n = mangle(); assert(n.length != 0); nlen = n.length; static if (false) { if (nlen > 2 && n[0] == '_' && n[1] == 'D') { nlen -= 2; n += 2; } } version (Bug4054) id = cast(char*) GC.malloc(2 + nlen + size_t.sizeof * 3 + prefix.length + suffix.length + 1); else id = cast(char*) alloca(2 + nlen + size_t.sizeof * 3 + prefix.length + suffix.length + 1); sprintf(id, "_D%.*s%lu%.*s%.*s", n, prefix.length, prefix, suffix); static if (false) { if (global.params.isWindows && (type_mangle(t) == mTYman.mTYman_c || type_mangle(t) == mTYman.mTYman_std)) id++; // Windows C mangling will put the '_' back in } s = symbol_name(id, sclass, t); //printf("-Dsymbol::toSymbolX() %s\n", id); return s; } // Eliminate need for dynamic_cast Package isPackage() { return null; } Module isModule() { return null; } EnumMember isEnumMember() { return null; } TemplateDeclaration isTemplateDeclaration() { return null; } TemplateInstance isTemplateInstance() { return null; } TemplateMixin isTemplateMixin() { return null; } Declaration isDeclaration() { return null; } ThisDeclaration isThisDeclaration() { return null; } TupleDeclaration isTupleDeclaration() { return null; } TypedefDeclaration isTypedefDeclaration() { return null; } AliasDeclaration isAliasDeclaration() { return null; } AggregateDeclaration isAggregateDeclaration() { return null; } FuncDeclaration isFuncDeclaration() { return null; } FuncAliasDeclaration isFuncAliasDeclaration() { return null; } FuncLiteralDeclaration isFuncLiteralDeclaration() { return null; } CtorDeclaration isCtorDeclaration() { return null; } PostBlitDeclaration isPostBlitDeclaration() { return null; } DtorDeclaration isDtorDeclaration() { return null; } StaticCtorDeclaration isStaticCtorDeclaration() { return null; } StaticDtorDeclaration isStaticDtorDeclaration() { return null; } InvariantDeclaration isInvariantDeclaration() { return null; } UnitTestDeclaration isUnitTestDeclaration() { return null; } NewDeclaration isNewDeclaration() { return null; } VarDeclaration isVarDeclaration() { return null; } ClassDeclaration isClassDeclaration() { return null; } StructDeclaration isStructDeclaration() { return null; } UnionDeclaration isUnionDeclaration() { return null; } InterfaceDeclaration isInterfaceDeclaration() { return null; } ScopeDsymbol isScopeDsymbol() { return null; } WithScopeSymbol isWithScopeSymbol() { return null; } ArrayScopeSymbol isArrayScopeSymbol() { return null; } Import isImport() { return null; } EnumDeclaration isEnumDeclaration() { return null; } version (_DH) { DeleteDeclaration isDeleteDeclaration() { return null; } } SymbolDeclaration isSymbolDeclaration() { return null; } AttribDeclaration isAttribDeclaration() { return null; } OverloadSet isOverloadSet() { return null; } version (TARGET_NET) { PragmaScope isPragmaScope() { return null; } } }