{
: 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 empty [Func {set} set]
Define (reduce rec exprs)
Func {set}
(LIST.reduce exprs set
Func {set expr} For (f set) Let f (rec rec expr))
In
Define (rec rec 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 _} (rec rec expr)
| 'tuple.exprs (reduce rec exprs)
| 'record.{_ inits} (reduce rec inits)
| 'block.{binders expr}
(reduce rec
(LIST.cons expr
(LIST.map binders
Func {binder}
Match binder
| 'let.{_ expr} expr
| 'do.expr expr
;)))
| 'app.{func args} (reduce rec [func & args])
| 'func.{_ expr} (rec rec expr)
| 'iterate.{_ inits expr} (reduce rec [expr & inits])
| 'continue.exprs (reduce rec exprs)
| 'cond.clauses
(reduce rec
(LIST.concat_map clauses
Func {{test body}}
[Right test & body & 'nil]))
| 'if.{test then else}
(reduce rec
[Right test & then & else & 'nil])
| 'and.{test then}
(reduce rec [Right test & then & 'nil])
| 'or.{test else}
(reduce rec [Right test & else & 'nil])
| 'list.exprs (reduce rec exprs)
| 'labeled.{_ expr} (rec rec expr)
| 'match.{expr clauses}
(reduce rec [expr & (LIST.map clauses [Func {{_ body}} body])])
;
In
For (SET.list (f SET.empty))
Let f (rec rec expr)
Where
Let GRAPH Package "graph"
Let LIST Package "list"
Let OS Package "os"
Let SEARCH Package "search"
Let STRING Package "string"