aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/tool/compiler/meta/cache/dependency/module.lux
blob: 0a9b6028f02b394cfcaaa827f31de15eed8fc294 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
(.require
 [library
  [lux (.except)
   [abstract
    ["[0]" monad (.only do)]]
   [control
    ["[0]" maybe (.use "[1]#[0]" functor)]
    ["[0]" try (.only Try)]
    ["[0]" state]
    [function
     ["[0]" memo (.only Memo)]]]
   [data
    ["[0]" text (.only)
     ["%" \\format (.only format)]]
    [collection
     ["[0]" list (.use "[1]#[0]" functor mix)]
     ["[0]" dictionary (.only Dictionary)]
     ["[0]" set (.only Set)]]]]]
 [////
  ["[0]" archive (.only Output Archive)
   [key (.only Key)]
   ["[0]" module (.only)
    ["[0]" descriptor (.only Descriptor)]
    ["[0]" document (.only Document)]]]])

(type .public Ancestry
  (Set descriptor.Module))

(def fresh
  Ancestry
  (set.empty text.hash))

(type .public Graph
  (Dictionary descriptor.Module Ancestry))

(def empty
  Graph
  (dictionary.empty text.hash))

(def .public modules
  (-> Graph (List descriptor.Module))
  dictionary.keys)

(type .public Dependency
  (Record
   [#module descriptor.Module
    #imports Ancestry]))

(def .public graph
  (-> (List Dependency) Graph)
  (list#mix (function (_ [module imports] graph)
              (dictionary.has module imports graph))
            ..empty))

(def (ancestry archive)
  (-> Archive Graph)
  (let [memo (is (Memo descriptor.Module Ancestry)
                 (function (_ again module)
                   (do [! state.monad]
                     [.let [parents (case (archive.find module archive)
                                      {try.#Success [module output registry]}
                                      (the [module.#descriptor descriptor.#references] module)
                                      
                                      {try.#Failure error}
                                      ..fresh)]
                      ancestors (monad.each ! again (set.list parents))]
                     (in (list#mix set.union parents ancestors)))))
        ancestry (memo.open memo)]
    (list#mix (function (_ module memory)
                (if (dictionary.key? memory module)
                  memory
                  (let [[memory _] (ancestry [memory module])]
                    memory)))
              ..empty
              (archive.archived archive))))

(def (dependency? ancestry target source)
  (-> Graph descriptor.Module descriptor.Module Bit)
  (let [target_ancestry (|> ancestry
                            (dictionary.value target)
                            (maybe.else ..fresh))]
    (set.member? target_ancestry source)))

(type .public (Order a)
  (List [descriptor.Module [module.ID (archive.Entry a)]]))

(def .public (load_order key archive)
  (All (_ a) (-> (Key a) Archive (Try (Order a))))
  (let [ancestry (..ancestry archive)]
    (|> ancestry
        dictionary.keys
        (list.sorted (..dependency? ancestry))
        (monad.each try.monad
                    (function (_ module)
                      (do try.monad
                        [module_id (archive.id module archive)
                         entry (archive.find module archive)
                         document (document.marked? key (the [archive.#module module.#document] entry))]
                        (in [module [module_id (has [archive.#module module.#document] document entry)]])))))))