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