Mercurial > projects > ddmd
diff dmd/Import.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 427f8aa74d28 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/Import.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,339 @@ +module dmd.Import; + +import dmd.Dsymbol; +import dmd.Array; +import dmd.DsymbolTable; +import dmd.PROT; +import dmd.Identifier; +import dmd.Module; +import dmd.Package; +import dmd.Loc; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.Scope; +import dmd.TypeIdentifier; +import dmd.AliasDeclaration; +import dmd.ScopeDsymbol; +import dmd.StorageClassDeclaration; +import dmd.STC; +import dmd.ProtDeclaration; +import dmd.Global; + +import std.stdio; + +void escapePath(OutBuffer buf, string fname) +{ + foreach (char c; fname) + { + switch (c) + { + case '(': + case ')': + case '\\': + buf.writebyte('\\'); + default: + buf.writebyte(*fname); + break; + } + } +} + +class Import : Dsymbol +{ + Array packages; // array of Identifier's representing packages + Identifier id; // module Identifier + Identifier aliasId; + int isstatic; // !=0 if static import + + // Pairs of alias=name to bind into current namespace + Array names; + Array aliases; + + Array aliasdecls; // AliasDeclarations for names/aliases + + Module mod; + Package pkg; // leftmost package/module + + this(Loc loc, Array packages, Identifier id, Identifier aliasId, int isstatic) + { + super(id); + + names = new Array(); + aliases = new Array(); + aliasdecls = new Array(); + + assert(id); + this.loc = loc; + this.packages = packages; + this.id = id; + this.aliasId = aliasId; + this.isstatic = isstatic; + + if (aliasId) + this.ident = aliasId; + // Kludge to change Import identifier to first package + else if (packages && packages.dim) + this.ident = cast(Identifier)packages.data[0]; + } + + void addAlias(Identifier name, Identifier alias_) + { + if (isstatic) + error("cannot have an import bind list"); + + if (!aliasId) + this.ident = null; // make it an anonymous import + + names.push(cast(void*)name); + aliases.push(cast(void*)alias_); + } + + string kind() + { + return isstatic ? "static import" : "import"; + } + + Dsymbol syntaxCopy(Dsymbol s) // copy only syntax trees + { + assert(false); + } + + void load(Scope sc) + { + DsymbolTable dst; + Dsymbol s; + + //writef("Import::load('%s')\n", toChars()); + + // See if existing module + dst = Package.resolve(packages, null, &pkg); + + s = dst.lookup(id); + if (s) + { +version (TARGET_NET) { + mod = cast(Module)s; +} else { + if (s.isModule()) + mod = cast(Module)s; + else + error("package and module have the same name"); +} + } + + if (!mod) + { + // Load module + mod = Module.load(loc, packages, id); + dst.insert(id, mod); // id may be different from mod->ident, + // if so then insert alias + if (!mod.importedFrom) + mod.importedFrom = sc ? sc.module_.importedFrom : Module.rootModule; + } + + if (!pkg) + pkg = mod; + + //writef("-Import::load('%s'), pkg = %p\n", toChars(), pkg); + } + + void semantic(Scope sc) + { + //writef("Import.semantic('%s')\n", toChars()); + + load(sc); + + if (mod) + { +static if (false) { + if (mod.loc.linnum != 0) + { /* If the line number is not 0, then this is not + * a 'root' module, i.e. it was not specified on the command line. + */ + mod.importedFrom = sc.module_.importedFrom; + assert(mod.importedFrom); + } +} + + // Modules need a list of each imported module + //printf("%s imports %s\n", sc.module.toChars(), mod.toChars()); + sc.module_.aimports.push(cast(void*)mod); + + if (!isstatic && !aliasId && !names.dim) + { + /* Default to private importing + */ + PROT prot = sc.protection; + if (!sc.explicitProtection) + prot = PROT.PROTprivate; + + sc.scopesym.importScope(mod, prot); + } + + mod.semantic(); + + if (mod.needmoduleinfo) + sc.module_.needmoduleinfo = 1; + + sc = sc.push(mod); + for (size_t i = 0; i < aliasdecls.dim; i++) + { + Dsymbol s = cast(Dsymbol)aliasdecls.data[i]; + + //writef("\tImport alias semantic('%s')\n", s.toChars()); + if (!mod.search(loc, cast(Identifier)names.data[i], 0)) + error("%s not found", (cast(Identifier)names.data[i]).toChars()); + + s.semantic(sc); + } + sc = sc.pop(); + } + + if (global.params.moduleDeps !is null) + { + /* The grammar of the file is: + * ImportDeclaration + * .= BasicImportDeclaration [ " : " ImportBindList ] [ " . " + * ModuleAliasIdentifier ] "\n" + * + * BasicImportDeclaration + * .= ModuleFullyQualifiedName " (" FilePath ") : " Protection + * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")" + * + * FilePath + * - any string with '(', ')' and '\' escaped with the '\' character + */ + + OutBuffer ob = global.params.moduleDeps; + + ob.writestring(sc.module_.toPrettyChars()); + ob.writestring(" ("); + escapePath(ob, sc.module_.srcfile.toChars()); + ob.writestring(") : "); + + ProtDeclaration.protectionToCBuffer(ob, sc.protection); + if (isstatic) + StorageClassDeclaration.stcToCBuffer(ob, STC.STCstatic); + ob.writestring(": "); + + if (packages) + { + for (size_t i = 0; i < packages.dim; i++) + { + Identifier pid = cast(Identifier)packages.data[i]; + ob.printf("%s.", pid.toChars()); + } + } + + ob.writestring(id.toChars()); + ob.writestring(" ("); + if (mod) + escapePath(ob, mod.srcfile.toChars()); + else + ob.writestring("???"); + ob.writebyte(')'); + + for (size_t i = 0; i < names.dim; i++) + { + if (i == 0) + ob.writebyte(':'); + else + ob.writebyte(','); + + Identifier name = cast(Identifier)names.data[i]; + Identifier alias_ = cast(Identifier)aliases.data[i]; + + if (!alias_) + { + ob.printf("%s", name.toChars()); + alias_ = name; + } + else + ob.printf("%s=%s", alias_.toChars(), name.toChars()); + } + + if (aliasId) + ob.printf(" . %s", aliasId.toChars()); + + ob.writenl(); + } + + //printf("-Import.semantic('%s'), pkg = %p\n", toChars(), pkg); + } + + void semantic2(Scope sc) + { + //printf("Import::semantic2('%s')\n", toChars()); + mod.semantic2(); + if (mod.needmoduleinfo) + sc.module_.needmoduleinfo = 1; + } + + Dsymbol toAlias() + { + if (aliasId) + return mod; + return this; + } + + /***************************** + * Add import to sd's symbol table. + */ + bool addMember(Scope sc, ScopeDsymbol sd, int memnum) + { + bool result = false; + + if (names.dim == 0) + return Dsymbol.addMember(sc, sd, memnum); + + if (aliasId) + result = Dsymbol.addMember(sc, sd, memnum); + + /* Instead of adding the import to sd's symbol table, + * add each of the alias=name pairs + */ + for (size_t i = 0; i < names.dim; i++) + { + Identifier name = cast(Identifier)names.data[i]; + Identifier alias_ = cast(Identifier)aliases.data[i]; + + if (!alias_) + alias_ = name; + + TypeIdentifier tname = new TypeIdentifier(loc, name); + AliasDeclaration ad = new AliasDeclaration(loc, alias_, tname); + result |= ad.addMember(sc, sd, memnum); + + aliasdecls.push(cast(void*)ad); + } + + return result; + } + + Dsymbol search(Loc loc, Identifier ident, int flags) + { + //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags); + + if (!pkg) + { + load(null); + mod.semantic(); + } + + // Forward it to the package/module + return pkg.search(loc, ident, flags); + } + + bool overloadInsert(Dsymbol s) + { + // Allow multiple imports of the same name + return s.isImport() !is null; + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + + Import isImport() { return this; } +} \ No newline at end of file