... https://en.wikipedia.org/wiki/Tree_shaking (.using [library [lux "*" [abstract [hash {"+" Hash}] ["[0]" monad {"+" do}]] [data ["[0]" product] [collection ["[0]" list ("[1]#[0]" monoid mix monad)] ["[0]" set {"+" Set}] ["[0]" dictionary {"+" Dictionary}] ["[0]" sequence]]] [math [number ["[0]" nat]]] [meta ["[0]" symbol]] [tool [compiler ["[0]" phase] ["[0]" reference {"+" Constant}] [language [lux ["[0]" analysis ["[1]/[0]" composite]] ["[0]" synthesis {"+" Synthesis Path}] ["[0]" generation {"+" Context Operation}]]] [meta ["[0]" archive {"+" Archive} ["[0]" artifact] ["[0]" descriptor]]]]]]]) (def: (path_references references) (-> (-> Synthesis (List Constant)) (-> Path (List Constant))) (function (again path) (case path (^or {synthesis.#Pop} {synthesis.#Access _} {synthesis.#Bind _}) (list) (^template [] [{ left right} ($_ list#composite (again left) (again right))]) ([synthesis.#Alt] [synthesis.#Seq]) {synthesis.#Bit_Fork when then else} (case else {.#Some else} ($_ list#composite (again then) (again else)) {.#None} (again then)) (^template [] [{ fork} (|> {.#Item fork} (list#each (|>> product.right again)) list#conjoint)]) ([synthesis.#I64_Fork] [synthesis.#F64_Fork] [synthesis.#Text_Fork]) {synthesis.#Then then} (references then)))) (def: (references value) (-> Synthesis (List Constant)) (case value {synthesis.#Primitive value} (list) {synthesis.#Structure value} (case value {analysis/composite.#Variant value} (|> value (value@ analysis/composite.#value) references) {analysis/composite.#Tuple value} (|> value (list#each references) list#conjoint)) {synthesis.#Reference value} (case value {reference.#Variable _} (list) {reference.#Constant value} (list value)) {synthesis.#Control value} (case value {synthesis.#Branch value} (case value {synthesis.#Exec this that} ($_ list#composite (references this) (references that)) {synthesis.#Let input _ body} ($_ list#composite (references input) (references body)) {synthesis.#If test then else} ($_ list#composite (references test) (references then) (references else)) {synthesis.#Get _ record} (references record) {synthesis.#Case input path} ($_ list#composite (references input) (path_references references path))) {synthesis.#Loop value} (case value {synthesis.#Scope value} (|> value (value@ synthesis.#iteration) references) {synthesis.#Again value} (|> value (list#each references) list#conjoint)) {synthesis.#Function value} (case value {synthesis.#Abstraction value} (|> value (value@ synthesis.#body) references) {synthesis.#Apply function arguments} (|> (list& function arguments) (list#each references) list#conjoint))) {synthesis.#Extension [name parameters]} (|> parameters (list#each references) list#conjoint))) (def: context_hash (Hash Context) (product.hash nat.hash nat.hash)) (def: .public (dependencies archive value) (All (_ anchor expression directive) (-> Archive Synthesis (Operation anchor expression directive (Set artifact.Dependency)))) (let [! phase.monad] (|> value ..references (set.of_list symbol.hash) set.list (monad.each ! (generation.remember archive)) (# ! each (set.of_list context_hash))))) (def: .public (path_dependencies archive value) (All (_ anchor expression directive) (-> Archive Path (Operation anchor expression directive (Set artifact.Dependency)))) (let [! phase.monad] (|> value (..path_references ..references) (set.of_list symbol.hash) set.list (monad.each ! (generation.remember archive)) (# ! each (set.of_list context_hash))))) (def: .public all (-> (List (Set artifact.Dependency)) (Set artifact.Dependency)) (list#mix set.union artifact.no_dependencies)) (def: (immediate_dependencies archive) (-> Archive [(List artifact.Dependency) (Dictionary artifact.Dependency (Set artifact.Dependency))]) (|> archive archive.entries (list#each (function (_ [module [module_id [descriptor document output]]]) (|> descriptor (value@ descriptor.#registry) artifact.artifacts sequence.list (list#each (function (_ artifact) [[module_id (value@ artifact.#id artifact)] (value@ artifact.#mandatory? artifact) (value@ artifact.#dependencies artifact)]))))) list.together (list#mix (function (_ [artifact_id mandatory? dependencies] [mandatory_dependencies all_dependencies]) [(if mandatory? (list& artifact_id mandatory_dependencies) mandatory_dependencies) (dictionary.has artifact_id dependencies all_dependencies)]) [(list) (dictionary.empty context_hash)]))) (def: .public (necessary_dependencies archive) (-> Archive (Set artifact.Dependency)) (let [[mandatory immediate] (immediate_dependencies archive)] (loop [pending mandatory minimum artifact.no_dependencies] (case pending {.#Item head tail} (if (set.member? minimum head) (again tail minimum) (again (case (dictionary.value head immediate) {.#Some additional} (list#composite (set.list additional) tail) {.#None} tail) (set.has head minimum))) {.#End} minimum))))