Mercurial > projects > ddmd
diff dmd/Dsymbol.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 427f8aa74d28 2cc604139636 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/Dsymbol.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,862 @@ +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; +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; +} + +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; + + 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, int 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; + 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; + } +} + 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; } +} +} \ No newline at end of file