tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

directory.tri (2019B)


      1 !import io as IO
      2 !import base as B
      3 !import native_math as N
      4 !export inventory
      5 !export count
      6 !export initialize
      7 !export removeFile
      8 !export removeDirectory
      9 !export rename
     10 !export metadata
     11 
     12 -- Caller-owned accumulation: inventory intentionally retains all entries, count
     13 -- consumes each entry without retaining names. Neither assumes enumeration order.
     14 walk directory root entries = IO.require (IO.nextDirectory directory) (reply : case reply of
     15   ("eof", t) = IO.pure entries
     16   ("entry", name) = IO.require (IO.lstatPath (B.append root (B.append "/" name)))
     17     (status : walk directory root (B.pair [name status] entries))
     18   _ = IO.fail "Invalid directory reply")
     19 inventory root = IO.io <| IO.scope (owner : IO.require (IO.openDirectory owner root)
     20   (directory : walk directory root []))
     21 
     22 -- Force the small counter before the next host request; lazy successor chains
     23 -- would retain pending arithmetic even though directory names are discarded.
     24 forceCounter t next = next t
     25 forceCounter (t bit rest) next = case bit of
     26   t = forceCounter rest next
     27   (t t) = forceCounter rest next
     28   _ = IO.fail "Invalid counter"
     29 forceCounter _ _ = IO.fail "Invalid counter"
     30 countLoop directory total = forceCounter total (_ : IO.require (IO.nextDirectory directory) (reply : case reply of
     31   ("eof", t) = IO.pure total
     32   ("entry", _) = countLoop directory (N.successor total)
     33   _ = IO.fail "Invalid directory reply"))
     34 count root = IO.io <| IO.scope (owner : IO.require (IO.openDirectory owner root)
     35   (directory : countLoop directory 0))
     36 
     37 -- Ordered nonrecursive initialization like the compiler's store/cache callers.
     38 initialize root = IO.io <| IO.onOk (IO.ensureDirectory root) (_ :
     39   IO.ensureDirectory (B.append root "/cache"))
     40 removeFile path = IO.io (IO.removeFile path)
     41 removeDirectory path = IO.io (IO.removeDirectory path)
     42 rename source destination = IO.io (IO.renamePath source destination)
     43 metadata path = IO.io <| do IO.bind
     44   followed <- IO.statPath path
     45   unfollowed <- IO.lstatPath path
     46   IO.pure [followed unfollowed]