31ffd58166bf861e82da0a90594cfb9c6c12e19baa51d5166fe0e4414d24af94.tri (11363B)
1 !import prelude * 2 !import io * 3 !import source_module * 4 !import source_object * 5 !import source_resolve * 6 !export * 7 8 -- A named lock is an explicitly updated local snapshot. Rows record the 9 -- original reference, one coherent originating manifest, and every export 10 -- selected by that reference (the native import / re-export profile selects 11 -- a manifest's whole public interface). No ambient alias is read by a 12 -- locked build. The manifest remains authoritative for its export hashes. 13 sourceLockHeader = "arboricx.source-lock.v1\n" 14 sourceLockPath root name = append root (append "/locks/" name) 15 sourceLockRow ref hash entry = 16 append "pin\t" (append (sourceModuleEscape ref) 17 (append "\t" (append hash 18 (append "\t" (append (sourceModuleEscape (fst entry)) 19 (append "\t" (append (snd entry) "\n"))))))) 20 sourceLockRows entries ref hash = 21 lazyList 22 (_ : t) 23 (entry rest : append (sourceLockRow ref hash entry) 24 (sourceLockRows rest ref hash)) 25 entries 26 sourceLockGroups groups = 27 lazyList 28 (_ : t) 29 (group rest : append 30 (sourceLockRows (snd (snd group)) (fst group) (fst (snd group))) 31 (sourceLockGroups rest)) 32 groups 33 sourceLockEncode groups = 34 append sourceLockHeader (sourceLockGroups groups) 35 36 -- A row is ref -> (manifest hash -> (export name -> exact tree hash)). 37 sourceLockParseRow fields = 38 lazyList 39 (_ : err "invalid lock row" t) 40 (tag r1 : lazyList 41 (_ : err "invalid lock row" t) 42 (encodedRef r2 : lazyList 43 (_ : err "invalid lock row" t) 44 (manifest r3 : lazyList 45 (_ : err "invalid lock row" t) 46 (encodedName r4 : lazyList 47 (_ : err "invalid lock row" t) 48 (tree extra : lazyBool 49 (_ : lazyResult 50 (problem unused : err problem t) 51 (ref unused : lazyResult 52 (problem unused : err problem t) 53 (name unused : lazyBool 54 (_ : ok (pair ref (pair manifest 55 (pair name tree))) t) 56 (_ : err "invalid lock ref, export or digest" t) 57 (and? (or? (sourceModuleDigest? ref) 58 (sourceModuleAliasValid ref)) 59 (and? (sourceModuleDigest? manifest) 60 (and? (sourceModuleExportNameValid name) 61 (sourceModuleDigest? tree))))) 62 (sourceModuleUnescape encodedName)) 63 (sourceModuleUnescape encodedRef)) 64 (_ : err "invalid lock row" t) 65 (and? (equal? tag "pin") (emptyList? extra))) 66 r4) 67 r3) 68 r2) 69 r1) 70 fields 71 sourceLockParseRows rows acc = 72 lazyList 73 (_ : ok (reverse acc) t) 74 (line rest : lazyList 75 (_ : lazyList 76 (_ : ok (reverse acc) t) 77 (_ _ : err "blank lock row" t) 78 rest) 79 (_ _ : lazyResult 80 (problem unused : err problem t) 81 (entry unused : sourceLockParseRows rest (pair entry acc)) 82 (sourceLockParseRow (splitOnByte 9 line))) 83 line) 84 rows 85 sourceLockDecode bytes = 86 lazyList 87 (_ : err "empty lock" t) 88 (header lines : lazyBool 89 (_ : sourceLockParseRows lines t) 90 (_ : err "unsupported lock version" t) 91 (equal? header "arboricx.source-lock.v1")) 92 (splitOnByte 10 bytes) 93 94 sourceLockDistinct rows seen = 95 lazyList 96 (_ : ok (reverse seen) t) 97 (row rest : lazyMaybe 98 (_ : sourceLockDistinct rest (pair (pair (fst row) (fst (snd row))) seen)) 99 (previous : lazyBool 100 (_ : sourceLockDistinct rest seen) 101 (_ : err "incoherent lock snapshot" t) 102 (equal? previous (fst (snd row)))) 103 (sourceFindExternal seen (fst row))) 104 rows 105 sourceLockSelectRows rows ref entries = 106 lazyList 107 (_ : reverse entries) 108 (row rest : lazyBool 109 (_ : sourceLockSelectRows rest ref (pair (snd (snd row)) entries)) 110 (_ : sourceLockSelectRows rest ref entries) 111 (equal? ref (fst row))) 112 rows 113 sourceLockRowsFor rows ref = sourceLockSelectRows rows ref t 114 sourceLockCheckEntries entries root = 115 lazyList 116 (_ : pure (ok t t)) 117 (entry rest : onResult_ (sourceObjectGetTree root (snd entry)) 118 (problem : pure (err problem t)) 119 (_ : sourceLockCheckEntries rest root)) 120 entries 121 sourceLockCheckTrees root entries = sourceLockCheckEntries entries root 122 sourceLockVerifyRefs refs root rows groups = 123 lazyList 124 (_ : pure (ok (reverse groups) t)) 125 (refHash rest : onResult_ (sourceModuleGetManifest root (snd refHash)) 126 (problem : pure (err problem t)) 127 (entries : lazyBool 128 (_ : onOk_ (sourceLockCheckTrees root entries) (_ : 129 sourceLockVerifyRefs rest root rows (pair 130 (pair (fst refHash) (pair (snd refHash) entries)) groups))) 131 (_ : pure (err "lock export snapshot mismatch" t)) 132 (equal? entries (sourceLockRowsFor rows (fst refHash))))) 133 refs 134 sourceLockVerify root bytes = 135 lazyResult 136 (problem unused : pure (err problem t)) 137 (rows unused : lazyResult 138 (problem unused : pure (err problem t)) 139 (refs unused : lazyList 140 (_ : pure (err "lock requires a module" t)) 141 (_ _ : onResult_ (sourceLockVerifyRefs refs root rows t) 142 (problem : pure (err problem t)) 143 (groups : lazyBool 144 (_ : pure (ok groups t)) 145 (_ : pure (err "noncanonical lock" t)) 146 (equal? bytes (sourceLockEncode groups)))) 147 refs) 148 (sourceLockDistinct rows t)) 149 (sourceLockDecode bytes) 150 151 -- Gather each source ref once. Resolving an alias occurs once per update; 152 -- repeated directives share the same immutable manifest snapshot. 153 sourceLockCollect refs root groups = 154 lazyList 155 (_ : pure (ok (reverse groups) t)) 156 (ref rest : lazyMaybe 157 (_ : onResult_ (sourceModuleResolveRef root ref) 158 (problem : pure (err problem t)) 159 (hash : onResult_ (sourceModuleGetManifest root hash) 160 (problem : pure (err problem t)) 161 (entries : onOk_ (sourceLockCheckTrees root entries) (_ : 162 sourceLockCollect rest root (pair (pair ref (pair hash entries)) groups))))) 163 (_ : sourceLockCollect rest root groups) 164 (sourceFindExternal groups ref)) 165 refs 166 sourceLockUseRefs uses acc = 167 lazyList 168 (_ : ok (reverse acc) t) 169 (words rest : lazyResult 170 (problem unused : err problem t) 171 (spec unused : sourceLockUseRefs rest (pair (fst spec) acc)) 172 (sourceModuleUseShape words)) 173 uses 174 sourceLockExportRefs exports acc = 175 lazyList 176 (_ : ok (reverse acc) t) 177 (words rest : lazyResult 178 (problem unused : err problem t) 179 (spec unused : lazyBool 180 (_ : sourceLockExportRefs rest (pair (snd spec) acc)) 181 (_ : sourceLockExportRefs rest acc) 182 (equal? (fst spec) "from")) 183 (sourceModuleExportShape words)) 184 exports 185 sourceLockSourceRefs source = 186 lazyResult 187 (problem unused : err problem t) 188 (staged unused : lazyResult 189 (problem unused : err problem t) 190 (uses unused : lazyResult 191 (problem unused : err problem t) 192 (exports unused : ok (append uses exports) t) 193 (sourceLockExportRefs (fst (snd staged)) t)) 194 (sourceLockUseRefs (fst staged) t)) 195 (sourceModuleStage source) 196 sourceLockUpdate root name source = 197 lazyBool 198 (_ : lazyResult 199 (problem unused : pure (err problem t)) 200 (refs unused : onResult_ (sourceLockCollect refs root t) 201 (problem : pure (err problem t)) 202 (groups : lazyList 203 (_ : pure (err "lock requires a module" t)) 204 (_ _ : onOk_ (createDirectory root) (_ : 205 onOk_ (createDirectory (append root "/locks")) (_ : 206 onOk_ (atomicWriteBytes (sourceLockPath root name) 207 (sourceLockEncode groups)) (_ : pure (ok t t))))) 208 groups)) 209 (sourceLockSourceRefs source)) 210 (_ : pure (err "invalid lock name" t)) 211 (sourceModuleAliasValid name) 212 213 sourceLockRewriteUses uses groups = 214 lazyList 215 (_ : ok t t) 216 (words rest : lazyResult 217 (problem unused : err problem t) 218 (spec unused : lazyMaybe 219 (_ : err "unlocked module reference" t) 220 (group : lazyResult 221 (problem unused : err problem t) 222 (suffix unused : ok (append "!import " 223 (append (fst group) (append (lazyBool 224 (_ : " *\n") 225 (_ : append " as " (append (snd spec) "\n")) 226 (equal? (snd spec) "*")) suffix))) t) 227 (sourceLockRewriteUses rest groups)) 228 (sourceFindExternal groups (fst spec))) 229 (sourceModuleUseShape words)) 230 uses 231 sourceLockRewriteExports exports groups = 232 lazyList 233 (_ : ok t t) 234 (words rest : lazyResult 235 (problem unused : err problem t) 236 (spec unused : lazyResult 237 (problem unused : err problem t) 238 (suffix unused : lazyBool 239 (_ : lazyMaybe 240 (_ : err "unlocked re-export" t) 241 (group : ok (append "!export * from " 242 (append (fst group) (append "\n" suffix))) t) 243 (sourceFindExternal groups (snd spec))) 244 (_ : ok (append "!export " 245 (append (fst spec) (append "\n" suffix))) t) 246 (equal? (fst spec) "from")) 247 (sourceLockRewriteExports rest groups)) 248 (sourceModuleExportShape words)) 249 exports 250 sourceLockRewriteSource source groups = 251 lazyResult 252 (problem unused : err problem t) 253 (staged unused : lazyResult 254 (problem unused : err problem t) 255 (uses unused : lazyResult 256 (problem unused : err problem t) 257 (exports unused : ok (append uses 258 (append exports (snd (snd staged)))) t) 259 (sourceLockRewriteExports (fst (snd staged)) groups)) 260 (sourceLockRewriteUses (fst staged) groups)) 261 (sourceModuleStage source) 262 -- Immutable binding selection without moving body coordinates. Rewritten 263 -- directives are interpreted separately, never prepended to the masked body. 264 sourceLockRewriteStaged source groups = (bindResult (sourceModuleStage source) 265 (staged _ : bindResult (sourceLockRewriteSource source groups) 266 (rewritten _ : bindResult (sourceModuleStage rewritten) 267 (header _ : ok (pair (fst header) 268 (pair (fst (snd header)) (snd (snd staged)))) t)))) 269 sourceLockUniqueRefs refs seen = 270 lazyList 271 (_ : sourceLockGroupRefs (reverse seen)) 272 (ref rest : lazyMaybe 273 (_ : sourceLockUniqueRefs rest (pair (pair ref t) seen)) 274 (_ : sourceLockUniqueRefs rest seen) 275 (sourceFindExternal seen ref)) 276 refs 277 sourceLockGroupRefs groups = map fst groups 278 sourceLockBuild root name source = 279 lazyBool 280 (_ : onResult_ (readFile (sourceLockPath root name)) 281 (problem : pure (err problem t)) 282 (bytes : onResult_ (sourceLockVerify root bytes) 283 (problem : pure (err problem t)) 284 (groups : lazyResult 285 (problem unused : pure (err problem t)) 286 (refs unused : lazyBool 287 (_ : lazyResult 288 (problem unused : pure (err problem t)) 289 (staged unused : sourceModuleBuildStaged root staged) 290 (sourceLockRewriteStaged source groups)) 291 (_ : pure (err "lock source references changed; update required" t)) 292 (equal? (sourceLockGroupRefs groups) 293 (sourceLockUniqueRefs refs t))) 294 (sourceLockSourceRefs source)))) 295 (_ : pure (err "invalid lock name" t)) 296 (sourceModuleAliasValid name) 297