]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
a3b38b77 | 3 | * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved |
b4c522fa IB |
4 | * written by Walter Bright |
5 | * http://www.digitalmars.com | |
6 | * Distributed under the Boost Software License, Version 1.0. | |
7 | * http://www.boost.org/LICENSE_1_0.txt | |
8 | * https://github.com/D-Programming-Language/dmd/blob/master/src/import.c | |
9 | */ | |
10 | ||
f9ab59ff | 11 | #include "root/dsystem.h" |
b4c522fa | 12 | #include "root/root.h" |
f9ab59ff | 13 | |
b4c522fa IB |
14 | #include "mars.h" |
15 | #include "dsymbol.h" | |
16 | #include "import.h" | |
17 | #include "identifier.h" | |
18 | #include "module.h" | |
19 | #include "scope.h" | |
20 | #include "mtype.h" | |
21 | #include "declaration.h" | |
22 | #include "id.h" | |
23 | #include "attrib.h" | |
24 | #include "hdrgen.h" | |
25 | ||
26 | /********************************* Import ****************************/ | |
27 | ||
28 | Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, | |
29 | int isstatic) | |
30 | : Dsymbol(NULL) | |
31 | { | |
32 | assert(id); | |
33 | this->loc = loc; | |
34 | this->packages = packages; | |
35 | this->id = id; | |
36 | this->aliasId = aliasId; | |
37 | this->isstatic = isstatic; | |
0a2ee409 | 38 | this->protection = Prot(Prot::private_); // default to private |
b4c522fa IB |
39 | this->pkg = NULL; |
40 | this->mod = NULL; | |
41 | ||
42 | // Set symbol name (bracketed) | |
43 | if (aliasId) | |
44 | { | |
45 | // import [cstdio] = std.stdio; | |
46 | this->ident = aliasId; | |
47 | } | |
2cbc99d1 | 48 | else if (packages && packages->length) |
b4c522fa IB |
49 | { |
50 | // import [std].stdio; | |
51 | this->ident = (*packages)[0]; | |
52 | } | |
53 | else | |
54 | { | |
55 | // import [foo]; | |
56 | this->ident = id; | |
57 | } | |
58 | } | |
59 | ||
60 | void Import::addAlias(Identifier *name, Identifier *alias) | |
61 | { | |
62 | if (isstatic) | |
63 | error("cannot have an import bind list"); | |
64 | ||
65 | if (!aliasId) | |
66 | this->ident = NULL; // make it an anonymous import | |
67 | ||
68 | names.push(name); | |
69 | aliases.push(alias); | |
70 | } | |
71 | ||
f9ab59ff | 72 | const char *Import::kind() const |
b4c522fa IB |
73 | { |
74 | return isstatic ? "static import" : "import"; | |
75 | } | |
76 | ||
77 | Prot Import::prot() | |
78 | { | |
79 | return protection; | |
80 | } | |
81 | ||
82 | Dsymbol *Import::syntaxCopy(Dsymbol *s) | |
83 | { | |
84 | assert(!s); | |
85 | ||
86 | Import *si = new Import(loc, packages, id, aliasId, isstatic); | |
87 | ||
2cbc99d1 | 88 | for (size_t i = 0; i < names.length; i++) |
b4c522fa IB |
89 | { |
90 | si->addAlias(names[i], aliases[i]); | |
91 | } | |
92 | ||
93 | return si; | |
94 | } | |
95 | ||
96 | void Import::load(Scope *sc) | |
97 | { | |
98 | //printf("Import::load('%s') %p\n", toPrettyChars(), this); | |
99 | ||
100 | // See if existing module | |
101 | DsymbolTable *dst = Package::resolve(packages, NULL, &pkg); | |
102 | Dsymbol *s = dst->lookup(id); | |
103 | if (s) | |
104 | { | |
105 | if (s->isModule()) | |
106 | mod = (Module *)s; | |
107 | else | |
108 | { | |
109 | if (s->isAliasDeclaration()) | |
110 | { | |
111 | ::error(loc, "%s %s conflicts with %s", s->kind(), s->toPrettyChars(), id->toChars()); | |
112 | } | |
113 | else if (Package *p = s->isPackage()) | |
114 | { | |
115 | if (p->isPkgMod == PKGunknown) | |
116 | { | |
117 | mod = Module::load(loc, packages, id); | |
118 | if (!mod) | |
119 | p->isPkgMod = PKGpackage; | |
120 | else | |
121 | { | |
122 | // mod is a package.d, or a normal module which conflicts with the package name. | |
123 | assert(mod->isPackageFile == (p->isPkgMod == PKGmodule)); | |
124 | if (mod->isPackageFile) | |
125 | mod->tag = p->tag; // reuse the same package tag | |
126 | } | |
127 | } | |
128 | else | |
129 | { | |
130 | mod = p->isPackageMod(); | |
131 | } | |
132 | if (!mod) | |
133 | { | |
134 | ::error(loc, "can only import from a module, not from package %s.%s", | |
135 | p->toPrettyChars(), id->toChars()); | |
136 | } | |
137 | } | |
138 | else if (pkg) | |
139 | { | |
140 | ::error(loc, "can only import from a module, not from package %s.%s", | |
141 | pkg->toPrettyChars(), id->toChars()); | |
142 | } | |
143 | else | |
144 | { | |
145 | ::error(loc, "can only import from a module, not from package %s", | |
146 | id->toChars()); | |
147 | } | |
148 | } | |
149 | } | |
150 | ||
151 | if (!mod) | |
152 | { | |
153 | // Load module | |
154 | mod = Module::load(loc, packages, id); | |
155 | if (mod) | |
156 | { | |
157 | dst->insert(id, mod); // id may be different from mod->ident, | |
158 | // if so then insert alias | |
159 | } | |
160 | } | |
161 | if (mod && !mod->importedFrom) | |
162 | mod->importedFrom = sc ? sc->_module->importedFrom : Module::rootModule; | |
163 | if (!pkg) | |
164 | pkg = mod; | |
165 | ||
166 | //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg); | |
167 | } | |
168 | ||
169 | void Import::importAll(Scope *sc) | |
170 | { | |
171 | if (!mod) | |
172 | { | |
173 | load(sc); | |
174 | if (mod) // if successfully loaded module | |
175 | { | |
42a84c28 IB |
176 | mod->importAll(NULL); |
177 | ||
b4c522fa IB |
178 | if (mod->md && mod->md->isdeprecated) |
179 | { | |
180 | Expression *msg = mod->md->msg; | |
181 | if (StringExp *se = msg ? msg->toStringExp() : NULL) | |
182 | mod->deprecation(loc, "is deprecated - %s", se->string); | |
183 | else | |
184 | mod->deprecation(loc, "is deprecated"); | |
185 | } | |
186 | ||
b4c522fa IB |
187 | if (sc->explicitProtection) |
188 | protection = sc->protection; | |
2cbc99d1 | 189 | if (!isstatic && !aliasId && !names.length) |
b4c522fa IB |
190 | { |
191 | sc->scopesym->importScope(mod, protection); | |
192 | } | |
193 | } | |
194 | } | |
195 | } | |
196 | ||
b4c522fa IB |
197 | Dsymbol *Import::toAlias() |
198 | { | |
199 | if (aliasId) | |
200 | return mod; | |
201 | return this; | |
202 | } | |
203 | ||
204 | /***************************** | |
205 | * Add import to sd's symbol table. | |
206 | */ | |
207 | ||
208 | void Import::addMember(Scope *sc, ScopeDsymbol *sd) | |
209 | { | |
210 | //printf("Import::addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd->toChars(), sc); | |
2cbc99d1 | 211 | if (names.length == 0) |
b4c522fa IB |
212 | return Dsymbol::addMember(sc, sd); |
213 | ||
214 | if (aliasId) | |
215 | Dsymbol::addMember(sc, sd); | |
216 | ||
217 | /* Instead of adding the import to sd's symbol table, | |
218 | * add each of the alias=name pairs | |
219 | */ | |
2cbc99d1 | 220 | for (size_t i = 0; i < names.length; i++) |
b4c522fa IB |
221 | { |
222 | Identifier *name = names[i]; | |
223 | Identifier *alias = aliases[i]; | |
224 | ||
225 | if (!alias) | |
226 | alias = name; | |
227 | ||
228 | TypeIdentifier *tname = new TypeIdentifier(loc, name); | |
229 | AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname); | |
230 | ad->_import = this; | |
231 | ad->addMember(sc, sd); | |
232 | ||
233 | aliasdecls.push(ad); | |
234 | } | |
235 | } | |
236 | ||
237 | void Import::setScope(Scope *sc) | |
238 | { | |
239 | Dsymbol::setScope(sc); | |
2cbc99d1 | 240 | if (aliasdecls.length) |
b4c522fa IB |
241 | { |
242 | if (!mod) | |
243 | importAll(sc); | |
244 | ||
245 | sc = sc->push(mod); | |
246 | sc->protection = protection; | |
2cbc99d1 | 247 | for (size_t i = 0; i < aliasdecls.length; i++) |
b4c522fa IB |
248 | { |
249 | AliasDeclaration *ad = aliasdecls[i]; | |
250 | ad->setScope(sc); | |
251 | } | |
252 | sc = sc->pop(); | |
253 | } | |
254 | } | |
255 | ||
256 | Dsymbol *Import::search(const Loc &loc, Identifier *ident, int flags) | |
257 | { | |
258 | //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags); | |
259 | ||
260 | if (!pkg) | |
261 | { | |
262 | load(NULL); | |
263 | mod->importAll(NULL); | |
a3b38b77 | 264 | dsymbolSemantic(mod, NULL); |
b4c522fa IB |
265 | } |
266 | ||
267 | // Forward it to the package/module | |
268 | return pkg->search(loc, ident, flags); | |
269 | } | |
270 | ||
271 | bool Import::overloadInsert(Dsymbol *s) | |
272 | { | |
273 | /* Allow multiple imports with the same package base, but disallow | |
274 | * alias collisions (Bugzilla 5412). | |
275 | */ | |
276 | assert(ident && ident == s->ident); | |
277 | Import *imp; | |
278 | if (!aliasId && (imp = s->isImport()) != NULL && !imp->aliasId) | |
279 | return true; | |
280 | else | |
281 | return false; | |
282 | } |