(.module: lux (lux (control monad ["ex" exception #+ exception:]) [io #+ Process] (concurrency ["P" promise] ["T" task]) (data ["e" error] [text "text/" Eq] 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 [#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 [?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 [#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 [[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 [_ (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 [_ (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)))