comparison dmd/Import.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 427f8aa74d28
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
1 module dmd.Import;
2
3 import dmd.Dsymbol;
4 import dmd.Array;
5 import dmd.DsymbolTable;
6 import dmd.PROT;
7 import dmd.Identifier;
8 import dmd.Module;
9 import dmd.Package;
10 import dmd.Loc;
11 import dmd.OutBuffer;
12 import dmd.HdrGenState;
13 import dmd.Scope;
14 import dmd.TypeIdentifier;
15 import dmd.AliasDeclaration;
16 import dmd.ScopeDsymbol;
17 import dmd.StorageClassDeclaration;
18 import dmd.STC;
19 import dmd.ProtDeclaration;
20 import dmd.Global;
21
22 import std.stdio;
23
24 void escapePath(OutBuffer buf, string fname)
25 {
26 foreach (char c; fname)
27 {
28 switch (c)
29 {
30 case '(':
31 case ')':
32 case '\\':
33 buf.writebyte('\\');
34 default:
35 buf.writebyte(*fname);
36 break;
37 }
38 }
39 }
40
41 class Import : Dsymbol
42 {
43 Array packages; // array of Identifier's representing packages
44 Identifier id; // module Identifier
45 Identifier aliasId;
46 int isstatic; // !=0 if static import
47
48 // Pairs of alias=name to bind into current namespace
49 Array names;
50 Array aliases;
51
52 Array aliasdecls; // AliasDeclarations for names/aliases
53
54 Module mod;
55 Package pkg; // leftmost package/module
56
57 this(Loc loc, Array packages, Identifier id, Identifier aliasId, int isstatic)
58 {
59 super(id);
60
61 names = new Array();
62 aliases = new Array();
63 aliasdecls = new Array();
64
65 assert(id);
66 this.loc = loc;
67 this.packages = packages;
68 this.id = id;
69 this.aliasId = aliasId;
70 this.isstatic = isstatic;
71
72 if (aliasId)
73 this.ident = aliasId;
74 // Kludge to change Import identifier to first package
75 else if (packages && packages.dim)
76 this.ident = cast(Identifier)packages.data[0];
77 }
78
79 void addAlias(Identifier name, Identifier alias_)
80 {
81 if (isstatic)
82 error("cannot have an import bind list");
83
84 if (!aliasId)
85 this.ident = null; // make it an anonymous import
86
87 names.push(cast(void*)name);
88 aliases.push(cast(void*)alias_);
89 }
90
91 string kind()
92 {
93 return isstatic ? "static import" : "import";
94 }
95
96 Dsymbol syntaxCopy(Dsymbol s) // copy only syntax trees
97 {
98 assert(false);
99 }
100
101 void load(Scope sc)
102 {
103 DsymbolTable dst;
104 Dsymbol s;
105
106 //writef("Import::load('%s')\n", toChars());
107
108 // See if existing module
109 dst = Package.resolve(packages, null, &pkg);
110
111 s = dst.lookup(id);
112 if (s)
113 {
114 version (TARGET_NET) {
115 mod = cast(Module)s;
116 } else {
117 if (s.isModule())
118 mod = cast(Module)s;
119 else
120 error("package and module have the same name");
121 }
122 }
123
124 if (!mod)
125 {
126 // Load module
127 mod = Module.load(loc, packages, id);
128 dst.insert(id, mod); // id may be different from mod->ident,
129 // if so then insert alias
130 if (!mod.importedFrom)
131 mod.importedFrom = sc ? sc.module_.importedFrom : Module.rootModule;
132 }
133
134 if (!pkg)
135 pkg = mod;
136
137 //writef("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
138 }
139
140 void semantic(Scope sc)
141 {
142 //writef("Import.semantic('%s')\n", toChars());
143
144 load(sc);
145
146 if (mod)
147 {
148 static if (false) {
149 if (mod.loc.linnum != 0)
150 { /* If the line number is not 0, then this is not
151 * a 'root' module, i.e. it was not specified on the command line.
152 */
153 mod.importedFrom = sc.module_.importedFrom;
154 assert(mod.importedFrom);
155 }
156 }
157
158 // Modules need a list of each imported module
159 //printf("%s imports %s\n", sc.module.toChars(), mod.toChars());
160 sc.module_.aimports.push(cast(void*)mod);
161
162 if (!isstatic && !aliasId && !names.dim)
163 {
164 /* Default to private importing
165 */
166 PROT prot = sc.protection;
167 if (!sc.explicitProtection)
168 prot = PROT.PROTprivate;
169
170 sc.scopesym.importScope(mod, prot);
171 }
172
173 mod.semantic();
174
175 if (mod.needmoduleinfo)
176 sc.module_.needmoduleinfo = 1;
177
178 sc = sc.push(mod);
179 for (size_t i = 0; i < aliasdecls.dim; i++)
180 {
181 Dsymbol s = cast(Dsymbol)aliasdecls.data[i];
182
183 //writef("\tImport alias semantic('%s')\n", s.toChars());
184 if (!mod.search(loc, cast(Identifier)names.data[i], 0))
185 error("%s not found", (cast(Identifier)names.data[i]).toChars());
186
187 s.semantic(sc);
188 }
189 sc = sc.pop();
190 }
191
192 if (global.params.moduleDeps !is null)
193 {
194 /* The grammar of the file is:
195 * ImportDeclaration
196 * .= BasicImportDeclaration [ " : " ImportBindList ] [ " . "
197 * ModuleAliasIdentifier ] "\n"
198 *
199 * BasicImportDeclaration
200 * .= ModuleFullyQualifiedName " (" FilePath ") : " Protection
201 * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
202 *
203 * FilePath
204 * - any string with '(', ')' and '\' escaped with the '\' character
205 */
206
207 OutBuffer ob = global.params.moduleDeps;
208
209 ob.writestring(sc.module_.toPrettyChars());
210 ob.writestring(" (");
211 escapePath(ob, sc.module_.srcfile.toChars());
212 ob.writestring(") : ");
213
214 ProtDeclaration.protectionToCBuffer(ob, sc.protection);
215 if (isstatic)
216 StorageClassDeclaration.stcToCBuffer(ob, STC.STCstatic);
217 ob.writestring(": ");
218
219 if (packages)
220 {
221 for (size_t i = 0; i < packages.dim; i++)
222 {
223 Identifier pid = cast(Identifier)packages.data[i];
224 ob.printf("%s.", pid.toChars());
225 }
226 }
227
228 ob.writestring(id.toChars());
229 ob.writestring(" (");
230 if (mod)
231 escapePath(ob, mod.srcfile.toChars());
232 else
233 ob.writestring("???");
234 ob.writebyte(')');
235
236 for (size_t i = 0; i < names.dim; i++)
237 {
238 if (i == 0)
239 ob.writebyte(':');
240 else
241 ob.writebyte(',');
242
243 Identifier name = cast(Identifier)names.data[i];
244 Identifier alias_ = cast(Identifier)aliases.data[i];
245
246 if (!alias_)
247 {
248 ob.printf("%s", name.toChars());
249 alias_ = name;
250 }
251 else
252 ob.printf("%s=%s", alias_.toChars(), name.toChars());
253 }
254
255 if (aliasId)
256 ob.printf(" . %s", aliasId.toChars());
257
258 ob.writenl();
259 }
260
261 //printf("-Import.semantic('%s'), pkg = %p\n", toChars(), pkg);
262 }
263
264 void semantic2(Scope sc)
265 {
266 //printf("Import::semantic2('%s')\n", toChars());
267 mod.semantic2();
268 if (mod.needmoduleinfo)
269 sc.module_.needmoduleinfo = 1;
270 }
271
272 Dsymbol toAlias()
273 {
274 if (aliasId)
275 return mod;
276 return this;
277 }
278
279 /*****************************
280 * Add import to sd's symbol table.
281 */
282 bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
283 {
284 bool result = false;
285
286 if (names.dim == 0)
287 return Dsymbol.addMember(sc, sd, memnum);
288
289 if (aliasId)
290 result = Dsymbol.addMember(sc, sd, memnum);
291
292 /* Instead of adding the import to sd's symbol table,
293 * add each of the alias=name pairs
294 */
295 for (size_t i = 0; i < names.dim; i++)
296 {
297 Identifier name = cast(Identifier)names.data[i];
298 Identifier alias_ = cast(Identifier)aliases.data[i];
299
300 if (!alias_)
301 alias_ = name;
302
303 TypeIdentifier tname = new TypeIdentifier(loc, name);
304 AliasDeclaration ad = new AliasDeclaration(loc, alias_, tname);
305 result |= ad.addMember(sc, sd, memnum);
306
307 aliasdecls.push(cast(void*)ad);
308 }
309
310 return result;
311 }
312
313 Dsymbol search(Loc loc, Identifier ident, int flags)
314 {
315 //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
316
317 if (!pkg)
318 {
319 load(null);
320 mod.semantic();
321 }
322
323 // Forward it to the package/module
324 return pkg.search(loc, ident, flags);
325 }
326
327 bool overloadInsert(Dsymbol s)
328 {
329 // Allow multiple imports of the same name
330 return s.isImport() !is null;
331 }
332
333 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
334 {
335 assert(false);
336 }
337
338 Import isImport() { return this; }
339 }