{ : sort_by_dependence : gather_imports } Where Define (sort_by_dependence packages) Do (LIST.for_each packages Func p (LIST.for_each p.imports Func path When (STRING.equal path p.path) (OS.die (STRING.concat [Right "Package " & path & " imports itself." & 'nil])) End)) Let ordered_paths Let components Let MAP (SEARCH.MAP STRING.compare [Func {key _} key]) In Let G (GRAPH.G MAP) Let g (MAP.new (LIST.map packages [Func p {p.path p.imports}])) In (G.strongly_connected_components g) In (LIST.map components Func c Match c | 'cons.{path paths} Match paths | 'nil path | 'cons._ (OS.die "There is a cycle in the package dependence graph.") ; ;) In (LIST.map ordered_paths Func path Define (has_matching_path package) (STRING.equal package.path path) In Match (LIST.filter packages has_matching_path) | 'cons.{package _} package ;) Define (gather_imports expr) Let SET (SEARCH.SET STRING.compare) In Let f Let empty Func set set In Unfold exprs From [expr & 'nil] Match exprs | 'nil empty | 'cons.{expr exprs} Let g (Fold exprs) Let f Match expr | 'true empty | 'false empty | 'num._ empty | 'str._ empty | 'package.path [Func set (SET.insert set path)] | 'prim._ empty | 'var._ empty | 'chain.{expr _} (Fold [expr & 'nil]) | 'tuple.exprs (Fold exprs) | 'record.{_ inits} (Fold inits) | 'block.{binders expr} (Fold (LIST.cons expr (LIST.map binders Func binder Match binder | 'let.{_ expr} expr | 'do.expr expr ;))) | 'app.{func args} (Fold [func & args]) | 'func.{_ expr} (Fold [expr & 'nil]) | 'iterate.{_ inits expr} (Fold [expr & inits]) | 'continue.exprs (Fold exprs) | 'unfold.{_ inits expr} (Fold [expr & inits]) | 'fold.exprs (Fold exprs) | 'cond.clauses (Fold (LIST.concat_map clauses Func {test body} [Right test & body & 'nil])) | 'if.{test then else} (Fold [Right test & then & else & 'nil]) | 'and.{test then} (Fold [Right test & then & 'nil]) | 'or.{test else} (Fold [Right test & else & 'nil]) | 'labeled.{_ expr} (Fold [expr & 'nil]) | 'match.{expr clauses} (Fold [expr & (LIST.map clauses [Func {_ body} body])]) ; In [f >> g] ; In (SET.list (f SET.empty)) Where Let GRAPH Package "graph" Let LIST Package "list" Let OS Package "os" Let SEARCH Package "search" Let STRING Package "string"