(.module: lux (lux (control monad ["ex" exception #+ exception:]) [io #+ Process] (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 Cannot-Prepare-Module) (def: sanitize (-> Text Text) (text.replace-all "/" file.separator)) (def: (find-source dirs path) (-> (List File) Text (Process [Text File])) (case dirs #.Nil (io.fail (File-Not-Found path)) (#.Cons dir dirs') (do io.Monad [#let [file (format dir file.separator path)] ? (file.exists? file)] (if ? (wrap [path file]) (find-source dirs' path))))) (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 blob-to-text (-> Blob Text) (|>> [] String::new)) (def: #export (read dirs name) (-> (List File) Text (Process [File Text])) (do io.Monad [[path file] (: (Process [Text File]) ($_ either (find-source dirs (format name host-extension lux-extension)) (find-source dirs (format name lux-extension)) (io.fail (Module-Not-Found name)))) blob (file.read file)] (wrap [path (blob-to-text blob)]))) (def: #export (platform-target root-target) (-> File File) (format root-target "/" (for {"JVM" "jvm" "JS" "js"}))) (def: #export (prepare-target target-dir) (-> File (Process Bool)) (do io.Monad [_ (file.make-dir (sanitize target-dir))] (file.make-dir (sanitize (platform-target target-dir))))) (def: #export (prepare-module target-dir module-name) (-> File Text (Process Unit)) (do io.Monad [made-dir? (|> module-name (format (platform-target target-dir) "/") sanitize file.make-dir)] (if made-dir? (wrap []) (io.fail (Cannot-Prepare-Module (format "Module: " module-name "\n" "Target: " target-dir "\n")))))) (def: #export (write target name content) (-> File Text Blob (Process Unit)) (|> name (format (platform-target target) "/") sanitize (file.write content))) (def: #export (module target-dir module-dir) (-> File File (Maybe Text)) (case (text.split-with target-dir module-dir) (#.Some ["" post]) (let [raw (text.replace-all file.separator "/" post)] (if (text.starts-with? "/" raw) (text.clip' +1 raw) (#.Some raw))) _ #.None)) (def: #export (file target-dir file-name) (-> File Text File) (format target-dir file.separator (sanitize file-name)))