aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/io.jvm.lux
blob: f3e8eacee72a59a9ba7c0878b6049f67e227e3d8 (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
(.module:
  lux
  (lux (control monad
                ["ex" exception #+ exception:])
       [io #+ Process]
       (concurrency ["P" promise]
                    ["T" task])
       (data ["e" error]
             [text "text/" Eq<Text>]
             text/format)
       [macro]
       [host]
       (world [file #+ File]
              [blob #+ Blob])))

(host.import java/lang/String
  (new [(Array byte)]))

(def: host-extension Text ".jvm")
(def: lux-extension Text ".lux")

(exception: #export File-Not-Found)
(exception: #export Module-Not-Found)
(exception: #export Could-Not-Read-All-Data)

(host.import #long java/io/File
  (new [String])
  (exists [] #io #try boolean)
  (mkdir [] #io #try boolean)
  (delete [] #io #try boolean)
  (length [] #io #try long)
  (listFiles [] #io #try (Array java/io/File))
  (getAbsolutePath [] #io #try String)
  (isFile [] #io #try boolean)
  (isDirectory [] #io #try boolean)
  (#static separator String))

(host.import java/lang/AutoCloseable
  (close [] #io #try void))

(host.import java/io/InputStream
  (read [(Array byte)] #io #try int))

(host.import java/io/FileInputStream
  (new [java/io/File] #io #try))

(def: file-exists?
  (-> File (Process Bool))
  (|>> java/io/File::new (java/io/File::exists [])))

(def: (find-source path dirs)
  (-> Text (List File) (Process [Text File]))
  (case dirs
    #.Nil
    (io.fail (File-Not-Found path))

    (#.Cons dir dirs')
    (do io.Monad<Process>
      [#let [file (format dir java/io/File::separator path)]
       ? (file-exists? file)]
      (if ?
        (wrap [path file])
        (find-source path dirs')))))

(def: (either left right)
  (All [a] (-> (Process a) (Process a) (Process a)))
  (do io.Monad<IO>
    [?output left]
    (case ?output
      (#e.Success output)
      (wrap (#e.Success output))

      (#e.Error error)
      right)))

(def: #export (read-file file)
  (-> File (Process Blob))
  (do io.Monad<Process>
    [#let [file' (java/io/File::new file)]
     size (java/io/File::length [] file')
     #let [data (blob.create (int-to-nat size))]
     stream (FileInputStream::new [file'])
     bytes-read (InputStream::read [data] stream)
     _ (AutoCloseable::close [] stream)]
    (if (i/= size bytes-read)
      (wrap data)
      (io.fail (Could-Not-Read-All-Data file)))))

(def: #export (read-module dirs name)
  (-> (List File) Text (Process [File Text]))
  (let [host-path (format name host-extension lux-extension)
        lux-path (format name lux-extension)]
    (do io.Monad<Process>
      [[path file] (: (Process [Text File])
                      ($_ either
                          (find-source host-path dirs)
                          (find-source lux-path dirs)
                          (io.fail (Module-Not-Found name))))
       blob (read-file file)]
      (wrap [path (String::new blob)]))))

(def: #export (write-module name descriptor)
  (-> Text Text (T.Task Unit))
  (T.fail "'write-module' is undefined."))

(def: (platform-target root-target)
  (-> File File)
  (format root-target
          java/io/File::separator
          (for {"JVM" "jvm"
                "JS" "js"})))

(def: #export (prepare-target target-dir)
  (-> File (T.Task Unit))
  (do T.Monad<Task>
    [_ (file.make-dir target-dir)
     _ (file.make-dir (platform-target target-dir))]
    (wrap [])))

(def: #export (prepare-module target-dir module-name)
  (-> File Text (T.Task Unit))
  (do T.Monad<Task>
    [_ (file.make-dir (format (platform-target target-dir) java/io/File::separator module-name))]
    (wrap [])))

(def: #export (write-file target-dir file-name content)
  (-> File Text Blob (T.Task Unit))
  (|> file-name
      (format (platform-target target-dir) java/io/File::separator)
      (file.write content)))