diff options
Diffstat (limited to '')
-rw-r--r-- | stdlib/source/library/lux/tool/compiler/meta/archive/dependency.lux | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/stdlib/source/library/lux/tool/compiler/meta/archive/dependency.lux b/stdlib/source/library/lux/tool/compiler/meta/archive/dependency.lux new file mode 100644 index 000000000..70f5b5744 --- /dev/null +++ b/stdlib/source/library/lux/tool/compiler/meta/archive/dependency.lux @@ -0,0 +1,215 @@ +... 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] + ["[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 [<tag>] + [{<tag> 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 [<tag>] + [{<tag> 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.#Variant value} + (|> value + (value@ analysis.#value) + references) + + {analysis.#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.#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 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)))) |