aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/world/file.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/world/file.lux')
-rw-r--r--stdlib/source/lux/world/file.lux345
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)])])))