aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/compiler/meta/packager/ruby.lux
blob: 1c0d70dc20f212cef155ec4dbf77ad9984511ed5 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
(.require
 [library
  [lux (.except)
   [abstract
    ["[0]" monad (.only do)]]
   [control
    ["[0]" try (.only Try)]]
   [data
    [binary (.only Binary)]
    ["[0]" product]
    ["[0]" text (.only)
     ["%" \\format (.only format)]
     [encoding
      ["[0]" utf8]]]
    [collection
     ["[0]" sequence]
     ["[0]" list (.use "[1]#[0]" functor mix)]
     ["[0]" dictionary (.only Dictionary)]
     ["[0]" set (.only Set)]]]
   [math
    [number
     ["[0]" nat]]]
   [meta
    [type (.only sharing)]
    [target
     ["_" ruby]]]
   [world
    ["[0]" file]]]]
 ["[0]" // (.only Packager)
  [//
   ["[0]" archive (.only Output)
    [registry (.only Registry)]
    ["[0]" artifact]
    ["[0]" unit]
    ["[0]" module (.only)
     ["[0]" descriptor]
     ["[0]" document (.only Document)]]]
   ["[0]" cache
    [dependency
     ["[1]/[0]" module (.only Order)]
     ["[1]/[0]" artifact]]]
   ["[0]" io
    ["[1]" archive]]
   [//
    [language
     ["$" lux]]]]])

(def (bundle_module module module_id necessary_dependencies output)
  (-> descriptor.Module module.ID (Set unit.ID) Output (Try (Maybe _.Statement)))
  (do [! try.monad]
    []
    (case (|> output
              sequence.list
              (list.only (function (_ [artifact_id custom content])
                           (set.member? necessary_dependencies [module_id artifact_id]))))
      {.#End}
      (in {.#None})
      
      artifacts
      (do !
        [bundle (monad.mix !
                           (function (_ [artifact custom_name content] so_far)
                             (|> content
                                 (at utf8.codec decoded)
                                 (at ! each
                                     (|>> as_expected
                                          (is declaration)
                                          (sharing [declaration]
                                            (is declaration
                                                so_far))
                                          (_.then so_far)))))
                           (_.comment "Lux module"
                             (_.statement (_.string "")))
                           artifacts)]
        (in {.#Some bundle})))))

(def module_file
  (-> module.ID file.Path)
  (|>> %.nat (text.suffix ".rb")))

(def (write_module mapping necessary_dependencies [module [module_id entry]] sink)
  (-> (Dictionary descriptor.Module module.ID) (Set unit.ID)
      [descriptor.Module [module.ID (archive.Entry .Module)]]
      (List [module.ID [Text Binary]])
      (Try (List [module.ID [Text Binary]])))
  (do [! try.monad]
    [bundle (is (Try (Maybe _.Statement))
                (..bundle_module module module_id necessary_dependencies (the archive.#output entry)))]
    (case bundle
      {.#None}
      (in sink)

      {.#Some bundle}
      (let [entry_content (|> (list)
                              (list#mix _.then bundle)
                              (is _.Statement)
                              _.code
                              (at utf8.codec encoded))]
        (in (list.partial [module_id [(..module_file module_id) entry_content]]
                          sink))))))

(def .public main_file
  "main.rb")

(def module_id_mapping
  (-> (Order .Module) (Dictionary descriptor.Module module.ID))
  (|>> (list#each (function (_ [module [module_id entry]])
                    [module module_id]))
       (dictionary.of_list text.hash)))

(def included_modules
  (All (_ a) (-> (List [module.ID a]) (Set module.ID)))
  (|>> (list#each product.left)
       (list#mix set.has (set.empty nat.hash))))

(def .public (package host_dependencies archive program)
  Packager
  (do [! try.monad]
    [.let [necessary_dependencies (cache/artifact.necessary_dependencies archive)]
     order (cache/module.load_order $.key archive)
     entries (monad.mix ! (..write_module (module_id_mapping order) necessary_dependencies) {.#End} order)
     .let [included_modules (..included_modules entries)
           imports (|> order
                       (list.only (|>> product.right product.left (set.member? included_modules)))
                       list.reversed
                       (list#each (function (_ [module [module_id entry]])
                                    (let [relative_path (_.do "gsub" (list (_.string main_file)
                                                                           (_.string (..module_file module_id)))
                                                          {.#None}
                                                          (is _.CVar (_.manual "__FILE__")))]
                                      (_.statement (_.require/1 relative_path)))))
                       (list#mix _.then (_.comment "Lux program"
                                          (_.statement (_.string ""))))
                       (is _.Statement)
                       _.code
                       (at utf8.codec encoded))]]
    (in (|> entries
            (list#each product.right)
            {.#Item [..main_file imports]}
            {.#Right}))))