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]