{Record sort_by_dependence gather_imports} Where Let (sort_by_dependence packages) Do (LIST.for_each packages Func p. (LIST.for_each p.imports Func path. If (STRING.equal path p.path) (OS.die (STRING.concat ["Package " path " imports itself."])) {})) 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. Let (has_matching_path package) (STRING.equal package.path path) In Match (LIST.filter packages has_matching_path) | `cons.{package _} package ;) Let (gather_imports expr) Let SET (SEARCH.SET STRING.compare) In Let empty (Func set. set) Let (reduce map exprs) Func set. (LIST.reduce exprs set Func set expr. For (f set) Let f (map expr)) In Define (map expr) Match expr | `true empty | `false empty | `num._ empty | `str._ empty | `package.path (Func set. (SET.insert set path)) | `prim._ empty | `var._ empty | `chain.{expr _} (map expr) | `tuple.exprs (reduce map exprs) | `record.{_ inits} (reduce map inits) | `block.{binders expr} (reduce map (LIST.cons expr (LIST.map binders Func binder. Match binder | `let.{_ expr} expr | `do.expr expr ;))) | `app.{func args} (reduce map (func :: args)) | `func.{_ _ expr} (map expr) | `iterate.{_ inits expr} (reduce map (expr :: inits)) | `continue.exprs (reduce map exprs) | `switch.{expr clauses} (reduce map (expr :: (LIST.map clauses (Func {_ body}. body)))) | `cond.clauses (reduce map (LIST.concat_map clauses (Func {test body}. [test body]))) | `if.{test then else} (reduce map [test then else]) | `and.{test then} (reduce map [test then]) | `or.{test else} (reduce map [test else]) | `list.exprs (reduce map exprs) | `labeled.{_ expr} (map expr) | `match.{expr clauses} (reduce map (expr :: (LIST.map clauses (Func {_ body}. body)))) ; In For (SET.list (f SET.empty)) Let f (map expr) Where Let GRAPH Package "graph" Let LIST Package "list" Let OS Package "os" Let SEARCH Package "search" Let STRING Package "string"