0
|
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 {
|
79
|
26 foreach (char c; fname)
|
|
27 {
|
0
|
28 switch (c)
|
|
29 {
|
|
30 case '(':
|
|
31 case ')':
|
|
32 case '\\':
|
|
33 buf.writebyte('\\');
|
|
34 default:
|
|
35 buf.writebyte(*fname);
|
|
36 break;
|
|
37 }
|
79
|
38 }
|
0
|
39 }
|
|
40
|
|
41 class Import : Dsymbol
|
|
42 {
|
79
|
43 Array packages; // array of Identifier's representing packages
|
|
44 Identifier id; // module Identifier
|
|
45 Identifier aliasId;
|
|
46 int isstatic; // !=0 if static import
|
0
|
47
|
79
|
48 // Pairs of alias=name to bind into current namespace
|
|
49 Array names;
|
|
50 Array aliases;
|
0
|
51
|
79
|
52 Array aliasdecls; // AliasDeclarations for names/aliases
|
0
|
53
|
79
|
54 Module mod;
|
|
55 Package pkg; // leftmost package/module
|
0
|
56
|
79
|
57 this(Loc loc, Array packages, Identifier id, Identifier aliasId, int isstatic)
|
0
|
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 }
|
79
|
78
|
0
|
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
|
79
|
91 override string kind()
|
0
|
92 {
|
|
93 return isstatic ? "static import" : "import";
|
|
94 }
|
|
95
|
79
|
96 override Dsymbol syntaxCopy(Dsymbol s) // copy only syntax trees
|
0
|
97 {
|
|
98 assert(false);
|
|
99 }
|
|
100
|
79
|
101 void load(Scope sc)
|
0
|
102 {
|
|
103 //writef("Import::load('%s')\n", toChars());
|
|
104
|
|
105 // See if existing module
|
79
|
106 DsymbolTable dst = Package.resolve(packages, null, &pkg);
|
0
|
107
|
79
|
108 Dsymbol s = dst.lookup(id);
|
0
|
109 if (s)
|
|
110 {
|
79
|
111 version (TARGET_NET)
|
|
112 {
|
0
|
113 mod = cast(Module)s;
|
79
|
114 }
|
|
115 else
|
|
116 {
|
0
|
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);
|
79
|
128 dst.insert(id, mod); // id may be different from mod.ident,
|
0
|
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
|
79
|
140 override void importAll(Scope sc)
|
|
141 {
|
|
142 if (!mod)
|
|
143 {
|
|
144 load(sc);
|
|
145 mod.importAll(null);
|
|
146
|
|
147 if (!isstatic && !aliasId && !names.dim)
|
|
148 {
|
|
149 /* Default to private importing
|
|
150 */
|
|
151 PROT prot = sc.protection;
|
|
152 if (!sc.explicitProtection)
|
|
153 prot = PROT.PROTprivate;
|
|
154 sc.scopesym.importScope(mod, prot);
|
|
155 }
|
|
156 }
|
|
157 }
|
|
158
|
|
159 override void semantic(Scope sc)
|
0
|
160 {
|
|
161 //writef("Import.semantic('%s')\n", toChars());
|
|
162
|
79
|
163 // Load if not already done so
|
|
164 if (!mod)
|
|
165 {
|
|
166 load(sc);
|
|
167 mod.importAll(null);
|
|
168 }
|
0
|
169
|
|
170 if (mod)
|
|
171 {
|
79
|
172 static if (false)
|
|
173 {
|
0
|
174 if (mod.loc.linnum != 0)
|
|
175 { /* If the line number is not 0, then this is not
|
|
176 * a 'root' module, i.e. it was not specified on the command line.
|
|
177 */
|
|
178 mod.importedFrom = sc.module_.importedFrom;
|
|
179 assert(mod.importedFrom);
|
|
180 }
|
|
181 }
|
|
182
|
|
183 // Modules need a list of each imported module
|
|
184 //printf("%s imports %s\n", sc.module.toChars(), mod.toChars());
|
|
185 sc.module_.aimports.push(cast(void*)mod);
|
|
186
|
|
187 if (!isstatic && !aliasId && !names.dim)
|
|
188 {
|
|
189 /* Default to private importing
|
|
190 */
|
|
191 PROT prot = sc.protection;
|
|
192 if (!sc.explicitProtection)
|
|
193 prot = PROT.PROTprivate;
|
|
194
|
|
195 sc.scopesym.importScope(mod, prot);
|
|
196 }
|
|
197
|
|
198 mod.semantic();
|
|
199
|
|
200 if (mod.needmoduleinfo)
|
98
|
201 {
|
|
202 // writef("module4 %s because of %s\n", sc.module.toChars(), mod.toChars());
|
0
|
203 sc.module_.needmoduleinfo = 1;
|
98
|
204 }
|
0
|
205
|
|
206 sc = sc.push(mod);
|
|
207 for (size_t i = 0; i < aliasdecls.dim; i++)
|
|
208 {
|
|
209 Dsymbol s = cast(Dsymbol)aliasdecls.data[i];
|
|
210
|
|
211 //writef("\tImport alias semantic('%s')\n", s.toChars());
|
|
212 if (!mod.search(loc, cast(Identifier)names.data[i], 0))
|
|
213 error("%s not found", (cast(Identifier)names.data[i]).toChars());
|
|
214
|
|
215 s.semantic(sc);
|
|
216 }
|
|
217 sc = sc.pop();
|
|
218 }
|
|
219
|
|
220 if (global.params.moduleDeps !is null)
|
|
221 {
|
|
222 /* The grammar of the file is:
|
|
223 * ImportDeclaration
|
79
|
224 * .= BasicImportDeclaration [ " : " ImportBindList ] [ " . "
|
0
|
225 * ModuleAliasIdentifier ] "\n"
|
|
226 *
|
|
227 * BasicImportDeclaration
|
79
|
228 * .= ModuleFullyQualifiedName " (" FilePath ") : " Protection
|
0
|
229 * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
|
|
230 *
|
|
231 * FilePath
|
79
|
232 * - any string with '(', ')' and '\' escaped with the '\' character
|
0
|
233 */
|
|
234
|
|
235 OutBuffer ob = global.params.moduleDeps;
|
|
236
|
|
237 ob.writestring(sc.module_.toPrettyChars());
|
|
238 ob.writestring(" (");
|
|
239 escapePath(ob, sc.module_.srcfile.toChars());
|
|
240 ob.writestring(") : ");
|
|
241
|
|
242 ProtDeclaration.protectionToCBuffer(ob, sc.protection);
|
|
243 if (isstatic)
|
|
244 StorageClassDeclaration.stcToCBuffer(ob, STC.STCstatic);
|
|
245 ob.writestring(": ");
|
|
246
|
|
247 if (packages)
|
|
248 {
|
|
249 for (size_t i = 0; i < packages.dim; i++)
|
|
250 {
|
|
251 Identifier pid = cast(Identifier)packages.data[i];
|
|
252 ob.printf("%s.", pid.toChars());
|
|
253 }
|
|
254 }
|
|
255
|
|
256 ob.writestring(id.toChars());
|
|
257 ob.writestring(" (");
|
|
258 if (mod)
|
|
259 escapePath(ob, mod.srcfile.toChars());
|
|
260 else
|
|
261 ob.writestring("???");
|
|
262 ob.writebyte(')');
|
|
263
|
|
264 for (size_t i = 0; i < names.dim; i++)
|
|
265 {
|
|
266 if (i == 0)
|
|
267 ob.writebyte(':');
|
|
268 else
|
|
269 ob.writebyte(',');
|
|
270
|
|
271 Identifier name = cast(Identifier)names.data[i];
|
|
272 Identifier alias_ = cast(Identifier)aliases.data[i];
|
|
273
|
|
274 if (!alias_)
|
|
275 {
|
|
276 ob.printf("%s", name.toChars());
|
|
277 alias_ = name;
|
|
278 }
|
|
279 else
|
|
280 ob.printf("%s=%s", alias_.toChars(), name.toChars());
|
|
281 }
|
|
282
|
|
283 if (aliasId)
|
|
284 ob.printf(" . %s", aliasId.toChars());
|
|
285
|
|
286 ob.writenl();
|
|
287 }
|
|
288
|
|
289 //printf("-Import.semantic('%s'), pkg = %p\n", toChars(), pkg);
|
|
290 }
|
|
291
|
79
|
292 override void semantic2(Scope sc)
|
0
|
293 {
|
|
294 //printf("Import::semantic2('%s')\n", toChars());
|
|
295 mod.semantic2();
|
|
296 if (mod.needmoduleinfo)
|
98
|
297 {
|
|
298 // writef("module5 %s because of %s\n", sc.module.toChars(), mod.toChars());
|
0
|
299 sc.module_.needmoduleinfo = 1;
|
98
|
300 }
|
0
|
301 }
|
|
302
|
79
|
303 override Dsymbol toAlias()
|
0
|
304 {
|
|
305 if (aliasId)
|
|
306 return mod;
|
|
307 return this;
|
|
308 }
|
|
309
|
|
310 /*****************************
|
|
311 * Add import to sd's symbol table.
|
|
312 */
|
79
|
313 override bool addMember(Scope sc, ScopeDsymbol sd, bool memnum)
|
0
|
314 {
|
|
315 bool result = false;
|
|
316
|
|
317 if (names.dim == 0)
|
|
318 return Dsymbol.addMember(sc, sd, memnum);
|
|
319
|
|
320 if (aliasId)
|
|
321 result = Dsymbol.addMember(sc, sd, memnum);
|
|
322
|
|
323 /* Instead of adding the import to sd's symbol table,
|
|
324 * add each of the alias=name pairs
|
|
325 */
|
|
326 for (size_t i = 0; i < names.dim; i++)
|
|
327 {
|
|
328 Identifier name = cast(Identifier)names.data[i];
|
|
329 Identifier alias_ = cast(Identifier)aliases.data[i];
|
|
330
|
|
331 if (!alias_)
|
|
332 alias_ = name;
|
|
333
|
|
334 TypeIdentifier tname = new TypeIdentifier(loc, name);
|
|
335 AliasDeclaration ad = new AliasDeclaration(loc, alias_, tname);
|
|
336 result |= ad.addMember(sc, sd, memnum);
|
|
337
|
|
338 aliasdecls.push(cast(void*)ad);
|
|
339 }
|
|
340
|
|
341 return result;
|
|
342 }
|
|
343
|
79
|
344 override Dsymbol search(Loc loc, Identifier ident, int flags)
|
0
|
345 {
|
|
346 //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
|
|
347
|
|
348 if (!pkg)
|
|
349 {
|
|
350 load(null);
|
|
351 mod.semantic();
|
|
352 }
|
|
353
|
|
354 // Forward it to the package/module
|
|
355 return pkg.search(loc, ident, flags);
|
|
356 }
|
|
357
|
79
|
358 override bool overloadInsert(Dsymbol s)
|
0
|
359 {
|
|
360 // Allow multiple imports of the same name
|
|
361 return s.isImport() !is null;
|
|
362 }
|
|
363
|
79
|
364 override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
0
|
365 {
|
|
366 assert(false);
|
|
367 }
|
|
368
|
79
|
369 override Import isImport() { return this; }
|
72
|
370 }
|