@@ -167,7 +167,7 @@ public defn resolve-il (packages:Tuple<IPackage|PackageExports>, env:Env) -> Res
167
167
168
168
;Resolve type dependencies from pkgs
169
169
check-exported-types(symtables, ipackages*, package-exports(symtables), error-accum)
170
-
170
+ check-forwarded-imports(symtables, package-exports(symtables), error-accum)
171
171
172
172
;Compute initialization order
173
173
defn init-order () :
@@ -228,7 +228,9 @@ defn resolve-package (ipackage:IPackage,
228
228
map(resolve-exp{_, eng}, exps(ipackage))
229
229
val ipackage* = sub-exps(ipackage, exps*)
230
230
if length(error-accum) == num-errors :
231
- add-qualified-imports(ipackage*, qualified-imports(eng))
231
+ ipackage*
232
+ $> add-qualified-imports{_, qualified-imports(eng)}
233
+ $> compute-forwarded-imports{_, symtables}
232
234
233
235
;<doc>=======================================================
234
236
;=================== Check Type Dependencies ================
@@ -260,7 +262,7 @@ issue an error if it doesn't.
260
262
defn check-exported-types (symtables:SymbolTables, pkgs:Collection<IPackage>, pexs:Tuple<PackageExports>, error-accum:Vector<ResolveError>) :
261
263
;Ensure that all types referenced in exports are defined
262
264
for pex in pexs do :
263
- ;Check for existence of typeid
265
+ ;Check for existence of typeid
264
266
defn check-for-type (e:TypeId) :
265
267
val symtable = symtables[package(e)]
266
268
match(symtable:SymbolTable) :
@@ -276,6 +278,41 @@ defn check-exported-types (symtables:SymbolTables, pkgs:Collection<IPackage>, pe
276
278
;Scan all exports
277
279
do(scan-for-type, exports(pex))
278
280
281
+ ;<doc>=======================================================
282
+ ;================ Check Forwarded Imports ===================
283
+ ;============================================================
284
+
285
+ At the time of creation, each .pkg file stores the packages
286
+ that were imported via forwarding.
287
+
288
+ This check ensures that for each of the .pkg files, any
289
+ package that was previously imported via forwarding is still
290
+ imported via forwarding.
291
+
292
+ ;============================================================
293
+ ;=======================================================<doc>
294
+
295
+ defn check-forwarded-imports (symtables:SymbolTables,
296
+ pexs:Tuple<PackageExports>,
297
+ error-accum:Vector<ResolveError>) ->
298
+ False :
299
+
300
+ ;For each PackageExports.
301
+ for pex in pexs do :
302
+
303
+ ;Compute the set of packages that are currently forwarded to the .pkg file.
304
+ val currently-forwarded = forwarded-imports(symtables, direct-imports(pex))
305
+
306
+ ;Retrieve the set of packages that were previously forwarded to the .pkg file
307
+ ;at the time the .pkg file was originally compiled.
308
+ val previously-forwarded = forwarded-imports(pex)
309
+
310
+ ;Ensure that any package that was previously imported via forwarding,
311
+ ;is still imported via forwarding.
312
+ for forwarded in previously-forwarded do :
313
+ if not currently-forwarded[forwarded] :
314
+ add(error-accum, MissingForwardedPackage(package(pex), forwarded))
315
+
279
316
;============================================================
280
317
;===================== Defresolver ==========================
281
318
;============================================================
@@ -686,6 +723,39 @@ defn add-qualified-imports (ipackage:IPackage, imps:Tuple<Symbol>) :
686
723
;Add imports
687
724
sub-imports(ipackage, to-tuple(imports))
688
725
726
+ ;Compute the 'forwarded-inputs' field for the given IPackage.
727
+ ;Finds all packages that are imported via forwarding.
728
+ defn compute-forwarded-imports (ipackage:IPackage,
729
+ symtables:SymbolTables) ->
730
+ IPackage :
731
+ val directly-imported = to-tuple(seq(package-name, imports(ipackage)))
732
+ val forwarded = forwarded-imports(symtables, directly-imported)
733
+ sub-forwarded-imports(ipackage, to-tuple(forwarded))
734
+
735
+ ;Given the list of direct imports, compute the set of
736
+ ;all additional packages that are imported via forwarding.
737
+ defn forwarded-imports (symtables:SymbolTables,
738
+ direct-imports:Seqable<Symbol>) ->
739
+ HashSet<Symbol> :
740
+ val forwarded-set = within package = transitive-set(direct-imports) :
741
+ seq(package-name, filter(forward,imports(symtables,package)))
742
+ do(remove{forwarded-set, _}, direct-imports)
743
+ forwarded-set
744
+
745
+ ;Helper: Return the name of the package being imported.
746
+ defn package-name (i:IImport) : package(i)
747
+
748
+ ;Returns all symbols reachable from the initial set 'xs'
749
+ ;via the 'next' relation.
750
+ defn transitive-set (next:Symbol -> Seqable<Symbol>,
751
+ xs:Seqable<Symbol>) ->
752
+ HashSet<Symbol> :
753
+ val hashset = HashSet<Symbol>()
754
+ defn scan (x:Symbol) :
755
+ do(scan,next(x)) when add(hashset,x)
756
+ do(scan, xs)
757
+ hashset
758
+
689
759
;============================================================
690
760
;=================== Symbol Tables ==========================
691
761
;============================================================
@@ -696,6 +766,10 @@ defmulti package-exports (st:SymbolTables) -> Tuple<PackageExports>
696
766
defmulti new-ipackages (st:SymbolTables) -> Tuple<IPackage>
697
767
defmulti load-conditional-dependencies (st:SymbolTables) -> Vector<Symbol>
698
768
769
+ ;Return the explicit import statements (ImportedPackage) listed
770
+ ;in the given package. Returns empty if the package could not be loaded.
771
+ defmulti imports (st:SymbolTables, package:Symbol) -> Tuple<IImport|ImportedPackage>
772
+
699
773
; Three different import modes:
700
774
; - "import" mode: copy all imported definitions into symbol table.
701
775
; Corresponds to "import" clause
@@ -907,6 +981,11 @@ defn SymbolTables (packages:Tuple<IPackage|PackageExports>, env:Env, errors:Vect
907
981
new SymbolTables :
908
982
defmethod get (this, package:Symbol) :
909
983
symtables[package]
984
+ defmethod imports (this, package:Symbol) :
985
+ match(load-package(package)) :
986
+ (p:IPackage) : imports(p)
987
+ (p:PackageExports) : imported-packages(p)
988
+ (f:False) : []
910
989
defmethod package-exports (this) :
911
990
to-tuple $ filter-by<PackageExports>(values(pkg-table))
912
991
defmethod new-ipackages (this) :
@@ -955,7 +1034,7 @@ defn SymbolTable (package-name:Symbol, base:NameMap|Tuple<Export>) :
955
1034
val basetable = HashTable<Symbol, List<BaseEntry>>(List())
956
1035
957
1036
958
-
1037
+
959
1038
; Update an entry in the basetable
960
1039
; Assumes the resulting entry should be forwarded
961
1040
defn forward-base-entry (e:VEntry, f, xs:List<BaseEntry>) -> List<BaseEntry> :
@@ -964,8 +1043,8 @@ defn SymbolTable (package-name:Symbol, base:NameMap|Tuple<Export>) :
964
1043
else : cons(BaseEntry(f(e), true), xs)
965
1044
966
1045
; Forward symbol table entry to new-package under some prefix by updating its package field
967
- ; Concretely:
968
- ; Search for existing entry e, update package field if found.
1046
+ ; Concretely:
1047
+ ; Search for existing entry e, update package field if found.
969
1048
; If not found, simply update package field in e and add
970
1049
defn forward-entry (e:VEntry, new-package:Symbol, prefix:String|False) :
971
1050
defn fwd (e) : sub-package(e, new-package) ; Update package field
@@ -986,7 +1065,7 @@ defn SymbolTable (package-name:Symbol, base:NameMap|Tuple<Export>) :
986
1065
; already been added
987
1066
defn add-unique<?E> (e:?E&Equalable, entries:List<E&Equalable>) -> List<E> :
988
1067
if contains?(entries, e) : entries
989
- else : cons(e, entries)
1068
+ else : cons(e, entries)
990
1069
991
1070
; Add a VEntry to the symbol table under its prefix
992
1071
defn add-entry (e:VEntry, prefix:String|False) :
@@ -1203,6 +1282,15 @@ public defstruct NotCapVar <: ResolveError :
1203
1282
public defstruct MissingType <: ResolveError :
1204
1283
src-package:Symbol
1205
1284
typeid:TypeId
1285
+
1286
+ ;Indicates that a package expected to be imported via forwarding
1287
+ ;is missing.
1288
+ ;- src-package: The package that is being analyzed by the resolver.
1289
+ ;- imported-package: The package that is being imported (via
1290
+ ; forwarding) that is missing.
1291
+ public defstruct MissingForwardedPackage <: ResolveError :
1292
+ src-package:Symbol
1293
+ imported-package:Symbol
1206
1294
public defstruct ForwardingCycle <: ResolveError :
1207
1295
src-packages:Seq<Symbol>
1208
1296
@@ -1214,6 +1302,10 @@ defmethod print (o:OutputStream, e:MissingType) :
1214
1302
val FMT = "Missing type: The %~ package requires the %_/%_ type to be defined."
1215
1303
print(o, FMT % [src-package(e), package(typeid(e)), name(typeid(e))])
1216
1304
1305
+ defmethod print (o:OutputStream, e:MissingForwardedPackage) :
1306
+ val FMT = "Missing forwarded package: The %~ package needs the %~ package."
1307
+ print(o, FMT % [src-package(e), imported-package(e)])
1308
+
1217
1309
defmethod print (o:OutputStream, e:NoResolve) :
1218
1310
val FMT = "%_Could not resolve %~."
1219
1311
print(o, FMT % [infostr(e), name(e)])
0 commit comments