@@ -35,6 +35,7 @@ encapsulated package NFClassTree
3535 import NFType.Type ;
3636 import Mutable ;
3737 import NFModifier.Modifier ;
38+ import Import = NFImport ;
3839
3940protected
4041 import Array ;
@@ -165,7 +166,7 @@ public
165166 array< InstNode > classes;
166167 array< InstNode > components;
167168 array< InstNode > exts;
168- array< InstNode > imports;
169+ array< Import > imports;
169170 DuplicateTree . Tree duplicates;
170171 end PARTIAL_TREE ;
171172
@@ -177,7 +178,7 @@ public
177178 array< InstNode > classes;
178179 array< InstNode > components;
179180 array< InstNode > exts;
180- array< InstNode > imports;
181+ array< Import > imports;
181182 DuplicateTree . Tree duplicates;
182183 end EXPANDED_TREE ;
183184
@@ -188,7 +189,7 @@ public
188189 array< Mutable < InstNode >> components;
189190 list< Integer > localComponents;
190191 array< InstNode > exts;
191- array< InstNode > imports;
192+ array< Import > imports;
192193 DuplicateTree . Tree duplicates;
193194 end INSTANTIATED_TREE ;
194195
@@ -197,7 +198,7 @@ public
197198 LookupTree . Tree tree;
198199 array< InstNode > classes;
199200 array< InstNode > components;
200- array< InstNode > imports;
201+ array< Import > imports;
201202 DuplicateTree . Tree duplicates;
202203 end FLAT_TREE ;
203204
@@ -211,10 +212,12 @@ public
211212 LookupTree . Tree ltree;
212213 LookupTree . Entry lentry;
213214 Integer clsc, compc, extc, i;
214- array< InstNode > clss, comps, exts, imps ;
215+ array< InstNode > clss, comps, exts;
215216 Integer cls_idx = 0 , ext_idx = 0 , comp_idx = 0 ;
216- list< InstNode > imported_elems = {};
217217 DuplicateTree . Tree dups;
218+ list< Import > imps = {};
219+ array< Import > imps_arr;
220+ SourceInfo info;
218221 algorithm
219222 ltree := LookupTree . new();
220223
@@ -286,12 +289,22 @@ public
286289 then
287290 ();
288291
289- // An import clause. Instantiate it to get the elements it points to
290- // (might be multiple elements if it's unqualified) and store them in
291- // the list for later.
292+ // An unqualified import clause. We need to know which names are
293+ // imported by the clause, so it needs to be instantiated.
294+ case SCode . IMPORT (imp = Absyn . Import . UNQUAL_IMPORT (), info = info)
295+ algorithm
296+ imps := Import . instUnqualified(e. imp, parent, info, imps);
297+ then
298+ ();
299+
300+ // A qualified import clause. Since the import itself gives the name
301+ // of the imported element we can delay resolving the path until we
302+ // need it (i.e. when the name is used). Doing so avoids some
303+ // dependency issues, like when a package is imported into one of it's
304+ // enclosing scopes.
292305 case SCode . IMPORT ()
293306 algorithm
294- imported_elems := Inst . instImport (e. imp, parent, e. info, imported_elems) ;
307+ imps := Import . UNRESOLVED_IMPORT (e. imp, parent, e. info) :: imps ;
295308 then
296309 ();
297310
@@ -304,14 +317,16 @@ public
304317 end match;
305318 end for ;
306319
307- // Add all the imports to the tree.
320+
321+ // Add all the imported names to the lookup tree.
322+ imps_arr := listArray(imps);
308323 i := 1 ;
309- for e in imported_elems loop
310- ltree := addImport(e, i, ltree);
324+ for e in imps loop
325+ ltree := addImport(e, i, ltree, imps_arr );
311326 i := i + 1 ;
312327 end for ;
313328
314- tree := PARTIAL_TREE (ltree, clss, comps, exts, listArray(imported_elems) , dups);
329+ tree := PARTIAL_TREE (ltree, clss, comps, exts, imps_arr , dups);
315330 end fromSCode;
316331
317332 function fromEnumeration
@@ -360,7 +375,8 @@ public
360375 protected
361376 LookupTree . Tree ltree;
362377 LookupTree . Entry lentry;
363- array< InstNode > exts, clss, comps, imps;
378+ array< InstNode > exts, clss, comps;
379+ array< Import > imps;
364380 list< tuple< Integer , Integer >> ext_idxs = {};
365381 Integer ccount, cls_idx, comp_idx = 1 ;
366382 DuplicateTree . Tree dups;
@@ -448,7 +464,8 @@ public
448464 Class cls;
449465 ClassTree tree, ext_tree;
450466 LookupTree . Tree ltree;
451- array< InstNode > exts, old_clss, old_comps, imps;
467+ array< InstNode > exts, old_clss, old_comps;
468+ array< Import > imps;
452469 array< Mutable < InstNode >> clss, comps, ext_clss;
453470 list< Integer > local_comps = {};
454471 Integer cls_idx = 1 , comp_idx = 1 , cls_count, comp_count;
@@ -1182,25 +1199,59 @@ public
11821199 end addEnumConflict;
11831200
11841201 function addImport
1185- input InstNode node ;
1202+ input Import imp ;
11861203 input Integer index;
11871204 input output LookupTree . Tree tree;
1205+ input array< Import > imports;
11881206 algorithm
1189- tree := LookupTree . add(tree, InstNode . name(node ),
1190- LookupTree . Entry . IMPORT (index), addImportConflict);
1207+ tree := LookupTree . add(tree, Import . name(imp), LookupTree . Entry . IMPORT (index ),
1208+ function addImportConflict(imports = imports) );
11911209 end addImport;
11921210
11931211 function addImportConflict
11941212 input LookupTree . Entry newEntry;
11951213 input LookupTree . Entry oldEntry;
11961214 input String name;
1215+ input array< Import > imports;
11971216 output LookupTree . Entry entry;
11981217 algorithm
1199- entry := oldEntry;
1200- // TODO: We should probably give an error message here in some cases:
1201- // * Named/qualified import conflicting with normal element: warning
1202- // * Unqualified import conflicting with normal element: ignore import
1203- // * Import conflicting with import: Error, but only if used
1218+ entry := match (newEntry, oldEntry)
1219+ local
1220+ Import imp1, imp2;
1221+
1222+ case (LookupTree . Entry . IMPORT (), LookupTree . Entry . IMPORT ())
1223+ algorithm
1224+ imp1 := imports[newEntry. index];
1225+ imp2 := imports[oldEntry. index];
1226+
1227+ // Check what kind of imports we have. In case of an error we replace the import
1228+ // with the error information, and only print the error if the name is looked up.
1229+ entry := match (imp1, imp2)
1230+ // Two qualified imports of the same name gives an error.
1231+ case (Import . UNRESOLVED_IMPORT (), Import . UNRESOLVED_IMPORT ())
1232+ algorithm
1233+ arrayUpdate(imports, oldEntry. index, Import . CONFLICTING_IMPORT (imp1, imp2));
1234+ then
1235+ oldEntry;
1236+
1237+ // A name imported from several unqualified imports gives an error.
1238+ case (Import . RESOLVED_IMPORT (), Import . RESOLVED_IMPORT ())
1239+ algorithm
1240+ arrayUpdate(imports, oldEntry. index, Import . CONFLICTING_IMPORT (imp1, imp2));
1241+ then
1242+ oldEntry;
1243+
1244+ // Qualified import overwrites an unqualified.
1245+ case (Import . UNRESOLVED_IMPORT (), _) then newEntry;
1246+ // oldEntry is either qualified or a delayed error, keep it.
1247+ else oldEntry;
1248+ end match;
1249+ then
1250+ entry;
1251+
1252+ // Other elements overwrite an imported name.
1253+ else oldEntry;
1254+ end match;
12041255 end addImportConflict;
12051256
12061257 function addDuplicate
@@ -1307,7 +1358,9 @@ public
13071358 input ClassTree tree;
13081359 output InstNode element;
13091360 protected
1310- array< InstNode > imports;
1361+ array< Import > imports;
1362+ Import imp;
1363+ Boolean changed;
13111364 algorithm
13121365 imports := match tree
13131366 case PARTIAL_TREE () then tree. imports;
@@ -1316,7 +1369,13 @@ public
13161369 case FLAT_TREE () then tree. imports;
13171370 end match;
13181371
1319- element := imports[index];
1372+ // Imports are resolved on demand, i.e. here.
1373+ (element, changed, imp) := Import . resolve(imports[index]);
1374+
1375+ // Save the import if it wasn't already resolved.
1376+ if changed then
1377+ arrayUpdate(imports, index, imp);
1378+ end if ;
13201379 end resolveImport;
13211380
13221381 function countElements
0 commit comments