diff options
Diffstat (limited to 'stdlib/source/lux/world/file.lux')
-rw-r--r-- | stdlib/source/lux/world/file.lux | 345 |
1 files changed, 228 insertions, 117 deletions
diff --git a/stdlib/source/lux/world/file.lux b/stdlib/source/lux/world/file.lux index 176f7ccf8..21f5c1d3c 100644 --- a/stdlib/source/lux/world/file.lux +++ b/stdlib/source/lux/world/file.lux @@ -1,129 +1,240 @@ (.module: lux - (lux (control [monad #+ do] - ["ex" exception #+ exception:]) - (data (coll [array])) - (time ["i" instant] - ["d" duration]) + (lux (control [monad #+ Monad do] + ["ex" exception #+ Exception exception:] + pipe) + (data [error #+ Error] + text/format + (coll [array])) + (time [instant #+ Instant] + [duration]) (world [blob #+ Blob]) [io #+ Process] - [host])) + [host #+ import:] + [lang/host])) (type: #export File Text) -(exception: #export (could-not-read-all-data {file File}) - file) - -(exception: #export (not-a-directory {file File}) - file) - -(host.import: #long java/io/File - (new [String]) - (exists [] #io #try boolean) - (mkdirs [] #io #try boolean) - (delete [] #io #try boolean) - (length [] #io #try long) - (listFiles [] #io #try #? (Array java/io/File)) - (getAbsolutePath [] #io #try String) - (renameTo [java/io/File] #io #try boolean) - (isFile [] #io #try boolean) - (isDirectory [] #io #try boolean) - (lastModified [] #io #try long) - (setLastModified [long] #io #try boolean) - (canRead [] #io #try boolean) - (canWrite [] #io #try boolean) - (canExecute [] #io #try boolean) - (#static separator String)) - -(host.import: java/lang/AutoCloseable - (close [] #io #try void)) - -(host.import: java/io/OutputStream - (write [(Array byte)] #io #try void) - (flush [] #io #try void)) - -(host.import: java/io/FileOutputStream - (new [java/io/File boolean] #io #try)) - -(host.import: java/io/InputStream - (read [(Array byte)] #io #try int)) - -(host.import: java/io/FileInputStream - (new [java/io/File] #io #try)) - -(do-template [<name> <flag>] - [(def: #export (<name> data file) - (-> Blob File (Process Any)) - (do io.Monad<Process> - [stream (FileOutputStream::new [(java/io/File::new file) <flag>]) - _ (OutputStream::write [data] stream) - _ (OutputStream::flush [] stream)] - (AutoCloseable::close [] stream)))] - - [append true] - [write false] - ) +(type: #export Permission + #Read + #Write + #Execute) -(def: #export (read 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 (.nat size))] - stream (FileInputStream::new [file']) - bytes-read (InputStream::read [data] stream) - _ (AutoCloseable::close [] stream)] - (if (i/= size bytes-read) - (wrap data) - (io.io (ex.throw could-not-read-all-data file))))) - -(def: #export (size file) - (-> File (Process Nat)) - (do io.Monad<Process> - [size (java/io/File::length [] (java/io/File::new file))] - (wrap (.nat size)))) - -(def: #export (files dir) - (-> File (Process (List File))) - (do io.Monad<Process> - [?files (java/io/File::listFiles [] (java/io/File::new dir))] - (case ?files - (#.Some files) - (monad.map @ (java/io/File::getAbsolutePath []) - (array.to-list files)) - - #.None - (io.throw not-a-directory dir)))) - -(do-template [<name> <method>] - [(def: #export (<name> file) - (-> File (Process Bool)) - (<method> [] (java/io/File::new file)))] - - [exists? java/io/File::exists] - [make-directory java/io/File::mkdirs] - [delete java/io/File::delete] - [file? java/io/File::isFile] - [directory? java/io/File::isDirectory] - [can-read? java/io/File::canRead] - [can-write? java/io/File::canWrite] - [can-execute? java/io/File::canExecute] - ) +(sig: #export (System m) + (: (Monad m) + &monad) + + (: (All [e a] (-> (Exception e) e (m a))) + throw) + + (: (All [a] (-> (m a) (m (Error a)))) + try) + + (do-template [<name>] + [(: (-> Blob File (m Any)) + <name>)] + + [append] [write]) + + (do-template [<name> <output>] + [(: (-> File (m <output>)) + <name>)] + + [read Blob] + [size Nat] + [files (List File)] + [last-modified Instant]) + + (do-template [<name>] + [(: (-> File (m Bool)) + <name>)] -(def: #export (move target source) - (-> File File (Process Bool)) - (java/io/File::renameTo [(java/io/File::new target)] - (java/io/File::new source))) + [file?] + [directory?] + ) -(def: #export (last-modified file) - (-> File (Process i.Instant)) - (do io.Monad<Process> - [millis (java/io/File::lastModified [] (java/io/File::new file))] - (wrap (|> millis d.from-millis i.absolute)))) + (: (-> Permission File (m Bool)) + can?) -(def: #export (modify time file) - (-> i.Instant File (Process Bool)) - (java/io/File::setLastModified [(|> time i.relative d.to-millis)] - (java/io/File::new file))) + (do-template [<name>] + [(: (-> File (m Any)) + <name>)] + + [make-directory] + [delete] + ) + + (: (-> File File (m Any)) + move) + + (: (-> Instant File (m Any)) + modify) + + (: Text + separator) + ) + +(do-template [<name>] + [(exception: #export (<name> {file File}) + (ex.report ["File" file]))] + + [cannot-read-all-data] + [not-a-directory] + [cannot-make-directory] + [cannot-delete] + ) -(def: #export separator Text java/io/File::separator) +(exception: #export (cannot-move {target File} {source File}) + (ex.report ["Source" source] + ["Target" target])) + +(exception: #export (cannot-modify {instant Instant} {file File}) + (ex.report ["Instant" (%instant instant)] + ["File" file])) + +(`` (for {(~~ (static lang/host.jvm)) + (as-is (import: #long java/io/File + (new [String]) + (exists [] #io #try boolean) + (mkdirs [] #io #try boolean) + (delete [] #io #try boolean) + (length [] #io #try long) + (listFiles [] #io #try #? (Array java/io/File)) + (getAbsolutePath [] #io #try String) + (renameTo [java/io/File] #io #try boolean) + (isFile [] #io #try boolean) + (isDirectory [] #io #try boolean) + (lastModified [] #io #try long) + (setLastModified [long] #io #try boolean) + (canRead [] #io #try boolean) + (canWrite [] #io #try boolean) + (canExecute [] #io #try boolean) + (#static separator String)) + + (import: java/lang/AutoCloseable + (close [] #io #try void)) + + (import: java/io/OutputStream + (write [(Array byte)] #io #try void) + (flush [] #io #try void)) + + (import: java/io/FileOutputStream + (new [java/io/File boolean] #io #try)) + + (import: java/io/InputStream + (read [(Array byte)] #io #try int)) + + (import: java/io/FileInputStream + (new [java/io/File] #io #try)) + + (struct: #export JVM@System (System Process) + (def: &monad io.Monad<Process>) + + (def: throw io.throw) + + (def: (try computation) + (do io.Monad<IO> + [outcome computation] + (:: io.Monad<Process> wrap outcome))) + + (do-template [<name> <flag>] + [(def: (<name> data file) + (do io.Monad<Process> + [stream (FileOutputStream::new [(java/io/File::new file) <flag>]) + _ (OutputStream::write [data] stream) + _ (OutputStream::flush [] stream)] + (AutoCloseable::close [] stream)))] + + [append true] + [write false] + ) + + (def: (read file) + (do io.Monad<Process> + [#let [file' (java/io/File::new file)] + size (java/io/File::length [] file') + #let [data (blob.create (.nat size))] + stream (FileInputStream::new [file']) + bytes-read (InputStream::read [data] stream) + _ (AutoCloseable::close [] stream)] + (if (i/= size bytes-read) + (wrap data) + (io.io (ex.throw cannot-read-all-data file))))) + + (def: size + (|>> [] java/io/File::new + (java/io/File::length []) + (:: io.Monad<Process> map .nat))) + + (def: (files dir) + (do io.Monad<Process> + [?files (java/io/File::listFiles [] (java/io/File::new dir))] + (case ?files + (#.Some files) + (monad.map @ (java/io/File::getAbsolutePath []) + (array.to-list files)) + + #.None + (io.throw not-a-directory dir)))) + + (do-template [<name> <method>] + [(def: <name> (|>> [] java/io/File::new (<method> [])))] + + [file? java/io/File::isFile] + [directory? java/io/File::isDirectory] + ) + + (def: (can? permission file) + (let [jvm-file (java/io/File::new file)] + (case permission + #Read (java/io/File::canRead [] jvm-file) + #Write (java/io/File::canWrite [] jvm-file) + #Execute (java/io/File::canExecute [] jvm-file)))) + + (def: last-modified + (|>> [] java/io/File::new + (java/io/File::lastModified []) + (:: io.Monad<Process> map (|>> duration.from-millis instant.absolute)))) + + (do-template [<name> <exception> <method>] + [(def: (<name> subject) + (do io.Monad<IO> + [outcome (<method> [] (java/io/File::new subject))] + (case outcome + (#error.Success true) + (wrap (#error.Success [])) + + _ + (io.throw <exception> [subject]))))] + + [make-directory cannot-make-directory java/io/File::mkdirs] + [delete cannot-delete java/io/File::delete] + ) + + (do-template [<name> <exception> <method> <parameter-pre>] + [(def: (<name> parameter subject) + (do io.Monad<IO> + [outcome (<method> [(|> parameter <parameter-pre>)] + (java/io/File::new subject))] + (case outcome + (#error.Success true) + (wrap (#error.Success [])) + + _ + (io.throw <exception> [parameter subject]))))] + + [move cannot-move java/io/File::renameTo java/io/File::new] + [modify cannot-modify java/io/File::setLastModified (<| duration.to-millis instant.relative)] + ) + + (def: separator java/io/File::separator) + )) + })) + +(def: #export (exists? System<m> file) + (All [m] (-> (System m) File (m Bool))) + (|> file + (do> (:: System<m> &monad) + [(:: System<m> file?)] + [(if> [(wrap true)] + [(:: System<m> directory? file)])]))) |