aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/tool/compiler/meta/archive/dependency.lux
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/library/lux/tool/compiler/meta/archive/dependency.lux215
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))))