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