687cd83bc56d246e2126875cf894e08a82e8e59c470debb56f11263e7fd9ceeb.tri (6365B)
1 !import prelude * 2 !import patterns * 3 !export * 4 5 -- IO constructors for host-interpreted interaction trees. 6 -- Free-monad style: Bind is the single sequencing mechanism. 7 8 version = 1 9 10 io = action : pair "tricuIO" (pair version action) 11 12 pure = x : pair 0 x 13 bind = action k : pair 1 (pair action k) 14 -- Terminal diagnostic control for the Haskell IO scheduler. 15 abortIO = diagnostic : pair 2 diagnostic 16 17 putStr = s : pair 10 s 18 getLine = pair 11 t 19 20 readFile = p : pair 20 p 21 writeFile = p c : pair 21 (pair p c) 22 putBytes = bs : pair 12 bs 23 writeBytes = p c : pair 22 (pair p c) 24 25 listDirectory = p : pair 23 p 26 renameFile = old new : pair 24 (pair old new) 27 createDirectory = p : pair 25 p 28 deleteFile = p : pair 26 p 29 fileExists = p : pair 27 p 30 31 sha256Hex = bs : pair 28 bs 32 currentTime = pair 29 t 33 -- Filesystem-only atomic primitives. writeBytesIfAbsent returns ok true 34 -- for a new object and ok false if the path already exists, without changing 35 -- it. atomicWriteBytes returns ok true after atomic replacement of an alias. 36 -- Hosts sync file contents before publication and the parent directory 37 -- afterwards. Publish referenced objects before replacing a lock or alias; 38 -- a post-publication sync failure can leave the new name visible. 39 writeBytesIfAbsent = p bs : pair 32 (pair p bs) 40 atomicWriteBytes = p bs : pair 33 (pair p bs) 41 42 -- Read-permitted canonical tree-term transport. Verify the fixed 43 -- arboricx.tree-term.v1 digest before decoding; returns Result tree. 44 -- This loads an inert normal-form tree, never source or an applied program. 45 readTreeTerm = p digest : pair 34 (pair p digest) 46 47 -- Fixed canonical tree-term domain. No byte-list marshalling. Publication 48 -- requires read and write permission, never replaces an existing path, and 49 -- verifies its bytes even when another publisher wins. Directories are explicit. 50 hashTreeTerm = tree : pair 35 tree 51 writeTreeTermIfAbsent = p digest tree : pair 36 (pair p (pair digest tree)) 52 53 ask = pair 30 t 54 local = f action : pair 31 (pair f action) 55 56 get = pair 40 t 57 put = s : pair 41 s 58 59 fork = action : pair 60 action 60 await = handle : pair 61 handle 61 yield = pair 62 t 62 sleep = ms : pair 63 ms 63 64 -- --------------------------------------------------------------------------- 65 -- Generic sequencing combinators 66 -- --------------------------------------------------------------------------- 67 68 thenIO = a b : bind a (_ : b) 69 mapIO = action f : bind action (x : pure (f x)) 70 void = action : bind action (_ : pure t) 71 72 -- --------------------------------------------------------------------------- 73 -- Conditional execution 74 -- --------------------------------------------------------------------------- 75 76 when = cond action : matchBool action (pure t) cond 77 unless = cond action : matchBool (pure t) action cond 78 79 -- --------------------------------------------------------------------------- 80 -- Infinite loop 81 -- --------------------------------------------------------------------------- 82 83 forever = y (self : action : 84 bind action (_ : 85 self action)) 86 87 -- --------------------------------------------------------------------------- 88 -- Result-aware combinators 89 -- --------------------------------------------------------------------------- 90 91 -- Propagate driver Result on error; run okCase on success. 92 onOk = action okCase : 93 bind action (result : 94 matchResult 95 (err rest : pure result) 96 okCase 97 result) 98 99 -- Same as onOk, but the okCase only receives the value (rest is dropped). 100 onOk_ = action okCase : 101 bind action (result : 102 matchResult 103 (err rest : pure result) 104 (val _ : okCase val) 105 result) 106 107 -- Generalized Result handler with explicit branches. 108 onResult = action errCase okCase : 109 bind action (result : 110 matchResult errCase okCase result) 111 112 -- Same as onResult, but handlers only receive the value/msg (rest is dropped). 113 onResult_ = action errCase okCase : 114 bind action (result : 115 matchResult 116 (err _ : errCase err) 117 (val _ : okCase val) 118 result) 119 120 mapErrIO prefix action = 121 onResult_ action 122 (e : pure (err (append prefix e) t)) 123 (v : pure (ok v t)) 124 125 -- --------------------------------------------------------------------------- 126 -- Convenience helpers 127 -- --------------------------------------------------------------------------- 128 129 print = s : void (putStr s) 130 putStrLn = s : void (putStr (append s "\n")) 131 132 -- --------------------------------------------------------------------------- 133 -- Result-aware file helpers 134 -- --------------------------------------------------------------------------- 135 136 onReadFile = path : onResult (readFile path) 137 138 onWriteFile = path contents : onResult (writeFile path contents) 139 140 onListDirectory = path : onResult (listDirectory path) 141 onRenameFile = old new : onResult (renameFile old new) 142 onCreateDirectory = path : onResult (createDirectory path) 143 onDeleteFile = path : onResult (deleteFile path) 144 onFileExists = path : onResult (fileExists path) 145 onSha256Hex = bs : onResult (sha256Hex bs) 146 onCurrentTime = onResult currentTime 147 148 -- --------------------------------------------------------------------------- 149 -- Convenience helpers for the common cases 150 -- --------------------------------------------------------------------------- 151 152 readFileOrPrintError = (path okCase : 153 onReadFile path 154 (err rest : putStrLn (append "Read failed: " err)) 155 okCase) 156 157 writeFileOrPrintError = (path contents okCase : 158 onWriteFile path contents 159 (err rest : putStrLn (append "Write failed: " err)) 160 okCase) 161 162 copyFile = (src dst : 163 onResult (readFile src) 164 (err rest : putStrLn (append "Read failed: " err)) 165 (contents rest : 166 onResult (writeFile dst contents) 167 (err rest : putStrLn (append "Write failed: " err)) 168 (_ _ : pure t))) 169 170 -- --------------------------------------------------------------------------- 171 -- Resource-safe combinators 172 -- --------------------------------------------------------------------------- 173 174 finally = action cleanup : 175 bind action (result : 176 bind cleanup (_ : 177 pure result)) 178 179 bracket = acquire release use : 180 bind acquire (resource : 181 bind (use resource) (result : 182 bind (release resource) (_ : 183 pure result))) 184