Mercurial > projects > ddmd
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 } |