nodes.tri (10943B)
1 !import "prelude" !Local 2 !import "binary" !Local 3 !import "arboricx.common" !Local 4 5 -- Indexed Arboricx node section reader. 6 -- 7 -- Node records in the indexed format are just length-prefixed payloads: 8 -- u32 payloadLength || payload 9 -- A payload is one of: 10 -- 0x00 11 -- 0x01 || childIndex:u32be 12 -- 0x02 || leftIndex:u32be || rightIndex:u32be 13 -- Child indices must point strictly backward in the node array. 14 15 readNodeRecord = (bs : 16 bindResult (readBytes 4 bs) 17 (payloadLength afterPayloadLength : 18 bindResult (readBytes (u32BEBytesToNat payloadLength) afterPayloadLength) 19 (payload afterPayload : 20 ok payload afterPayload))) 21 22 nodePayloadKind = (nodePayload : bytesHead nodePayload) 23 24 nodePayloadHasTag? = (tag nodePayload : 25 triage 26 false 27 (actualTag : equal? actualTag tag) 28 (_ _ : false) 29 (nodePayloadKind nodePayload)) 30 31 nodePayloadLeaf? = (nodePayload : 32 bytesEq? [(0)] nodePayload) 33 34 nodePayloadStem? = (nodePayload : 35 and? 36 (nodePayloadHasTag? nodePayloadStemTag nodePayload) 37 (equal? (bytesLength nodePayload) 5)) 38 39 nodePayloadFork? = (nodePayload : 40 and? 41 (nodePayloadHasTag? nodePayloadForkTag nodePayload) 42 (equal? (bytesLength nodePayload) 9)) 43 44 nodePayloadValid? = (nodePayload : 45 or? 46 (nodePayloadLeaf? nodePayload) 47 (or? 48 (nodePayloadStem? nodePayload) 49 (nodePayloadFork? nodePayload))) 50 51 nodeU32FromBytes4 = (b0 b1 b2 b3 : 52 u32BEBytesToNat 53 (pair b0 54 (pair b1 55 (pair b2 56 (pair b3 t))))) 57 58 withNodePayloadStemIndex = (nodePayload shortK indexK : 59 matchList 60 (shortK t) 61 (tag r0 : 62 matchList 63 (shortK t) 64 (b0 r1 : 65 matchList 66 (shortK t) 67 (b1 r2 : 68 matchList 69 (shortK t) 70 (b2 r3 : 71 matchList 72 (shortK t) 73 (b3 _ : 74 indexK (nodeU32FromBytes4 b0 b1 b2 b3)) 75 r3) r2) r1) r0) nodePayload) 76 77 withNodePayloadForkIndices = (nodePayload shortK indicesK : 78 matchList 79 (shortK t) 80 (tag r0 : 81 matchList 82 (shortK t) 83 (l0 r1 : 84 matchList 85 (shortK t) 86 (l1 r2 : 87 matchList 88 (shortK t) 89 (l2 r3 : 90 matchList 91 (shortK t) 92 (l3 r4 : 93 matchList 94 (shortK t) 95 (r0b r5 : 96 matchList 97 (shortK t) 98 (r1b r6 : 99 matchList 100 (shortK t) 101 (r2b r7 : 102 matchList 103 (shortK t) 104 (r3b _ : 105 indicesK 106 (nodeU32FromBytes4 l0 l1 l2 l3) 107 (nodeU32FromBytes4 r0b r1b r2b r3b)) r7) r6) r5) r4) r3) r2) r1) r0) nodePayload) 108 109 nodePayloadStemChildIndex = (nodePayload : 110 withNodePayloadStemIndex nodePayload (_ : 0) (index : index)) 111 112 nodePayloadForkLeftIndex = (nodePayload : 113 withNodePayloadForkIndices nodePayload (_ : 0) (left right : left)) 114 115 nodePayloadForkRightIndex = (nodePayload : 116 withNodePayloadForkIndices nodePayload (_ : 0) (left right : right)) 117 118 nodeRecordsHaveInvalidPayload? = y (self nodeRecords : 119 matchList 120 false 121 (nodePayload rest : 122 or? 123 (not? (nodePayloadValid? nodePayload)) 124 (self rest)) 125 nodeRecords) 126 127 nodePayloadChildIndices = (nodePayload : 128 matchList 129 t 130 (tag rest : 131 lazyBool 132 (_ : 133 withNodePayloadStemIndex 134 nodePayload 135 (_ : t) 136 (childIndex : pair childIndex t)) 137 (_ : 138 lazyBool 139 (_ : 140 withNodePayloadForkIndices 141 nodePayload 142 (_ : t) 143 (leftIndex rightIndex : 144 pair leftIndex (pair rightIndex t))) 145 (_ : t) 146 (equal? tag nodePayloadForkTag)) 147 (equal? tag nodePayloadStemTag)) 148 nodePayload) 149 150 -- True iff index n names an element before limit in records. 151 -- For topologically sorted indexed bundles, every child of record i must 152 -- satisfy childIndex < i, so searching only the prefix [0, i) validates both 153 -- bounds and acyclicity. 154 nodeIndexInPrefix? = y (self records n i limit : 155 matchList 156 false 157 (_ rest : 158 matchBool 159 false 160 (matchBool 161 true 162 (self rest n (succ i) limit) 163 (equal? i n)) 164 (equal? i limit)) 165 records) 166 167 nodeChildIndicesInPrefix? = y (self childIndices records limit : 168 matchList 169 true 170 (childIndex rest : 171 matchBool 172 (self rest records limit) 173 false 174 (nodeIndexInPrefix? records childIndex 0 limit)) 175 childIndices) 176 177 nodePayloadIndicesValid? = (nodePayload i records : 178 nodeChildIndicesInPrefix? 179 (nodePayloadChildIndices nodePayload) 180 records 181 i) 182 183 nodeRecordsValidIndicesFrom? = y (self allRecords remainingRecords i : 184 matchList 185 true 186 (nodePayload rest : 187 matchBool 188 (self allRecords rest (succ i)) 189 false 190 (nodePayloadIndicesValid? nodePayload i allRecords)) 191 remainingRecords) 192 193 nodeRecordsValidIndices? = (nodeRecords i : 194 nodeRecordsValidIndicesFrom? nodeRecords nodeRecords i) 195 196 validateNodeRecords = (nodeRecords rest : 197 matchBool 198 (err errInvalidNodePayload rest) 199 (matchBool 200 (ok nodeRecords rest) 201 (err errMissingNode rest) 202 (nodeRecordsValidIndices? nodeRecords 0)) 203 (nodeRecordsHaveInvalidPayload? nodeRecords)) 204 205 readNodeRecords_ = y (self bs nodeCount i acc : 206 matchBool 207 (ok (reverse acc) bs) 208 (bindResult (readNodeRecord bs) 209 (nodeRecord afterNodeRecord : 210 self afterNodeRecord nodeCount (succ i) (pair nodeRecord acc))) 211 (equal? i nodeCount)) 212 213 readNodeRecords = (nodeCount bs : 214 readNodeRecords_ bs nodeCount 0 t) 215 216 readNodesSection = (bs : 217 bindResult (readBytes 8 bs) 218 (nodeCount afterNodeCount : 219 bindResult (readNodeRecords (u64BEBytesToNat nodeCount) afterNodeCount) 220 (nodeRecords afterNodeRecords : 221 bindResult (validateNodeRecords nodeRecords afterNodeRecords) 222 (validNodeRecords afterValidNodeRecords : 223 ok (pair nodeCount validNodeRecords) afterValidNodeRecords)))) 224 225 readNodesSectionComplete = (bs : 226 bindResult (readNodesSection bs) 227 (nodesSection afterNodesSection : 228 matchBool 229 (ok nodesSection afterNodesSection) 230 (err errUnexpectedBytes afterNodesSection) 231 (bytesNil? afterNodesSection))) 232 233 readArboricxNodesSection = (bs : 234 bindResult (readArboricxContainer bs) 235 (container afterContainer : 236 matchPair 237 (_ directory : 238 bindResult (sectionBytesOrErr arboricxNodesSectionId directory bs afterContainer) 239 (nodesBytes _ : 240 bindResult (readNodesSectionComplete nodesBytes) 241 (nodesSection _ : ok nodesSection afterContainer))) 242 container)) 243 244 nodesSectionCount = (nodesSection : 245 matchPair 246 (nodeCount _ : nodeCount) 247 nodesSection) 248 249 nodesSectionRecords = (nodesSection : 250 matchPair 251 (_ nodeRecords : nodeRecords) 252 nodesSection) 253 254 nodeBuiltTreeIndex = (entry : 255 matchPair 256 (index _ : index) 257 entry) 258 259 nodeBuiltTreeValue = (entry : 260 matchPair 261 (_ tree : tree) 262 entry) 263 264 nodeTreeByIndex_ = (self builtTrees targetIndex : 265 lazyList 266 (_ : err errMissingNode t) 267 (entry rest : 268 lazyBool 269 (_ : ok (nodeBuiltTreeValue entry) t) 270 (_ : self rest targetIndex) 271 (equal? (nodeBuiltTreeIndex entry) targetIndex)) 272 builtTrees) 273 274 nodeTreeByIndex = (builtTrees targetIndex : 275 y nodeTreeByIndex_ builtTrees targetIndex) 276 277 nodePayloadToTreeFromBuilt = (builtTrees nodePayload : 278 matchList 279 (err errInvalidNodePayload t) 280 (tag rest : 281 lazyBool 282 (_ : ok t t) 283 (_ : 284 lazyBool 285 (_ : 286 withNodePayloadStemIndex 287 nodePayload 288 (_ : err errInvalidNodePayload t) 289 (childIndex : 290 lazyResult 291 (code after : err code after) 292 (child _ : ok (t child) t) 293 (nodeTreeByIndex builtTrees childIndex))) 294 (_ : 295 lazyBool 296 (_ : 297 withNodePayloadForkIndices 298 nodePayload 299 (_ : err errInvalidNodePayload t) 300 (leftIndex rightIndex : 301 lazyResult 302 (code after : err code after) 303 (left _ : 304 lazyResult 305 (code after : err code after) 306 (right _ : ok (pair left right) t) 307 (nodeTreeByIndex builtTrees rightIndex)) 308 (nodeTreeByIndex builtTrees leftIndex))) 309 (_ : err errInvalidNodePayload t) 310 (equal? tag nodePayloadForkTag)) 311 (equal? tag nodePayloadStemTag)) 312 (equal? tag 0)) 313 nodePayload) 314 315 nodeBuildState = (targetIndex i builtTrees : 316 pair targetIndex (pair i builtTrees)) 317 318 nodeBuildStateTargetIndex = (state : 319 matchPair 320 (targetIndex _ : targetIndex) 321 state) 322 323 nodeBuildStateI = (state : 324 matchPair 325 (_ rest : 326 matchPair 327 (i _ : i) 328 rest) 329 state) 330 331 nodeBuildStateBuiltTrees = (state : 332 matchPair 333 (_ rest : 334 matchPair 335 (_ builtTrees : builtTrees) 336 rest) 337 state) 338 339 nodeIndexToTree_ = (self remainingRecords state : 340 ((nodeIndex : 341 ((i : 342 ((builtTrees : 343 lazyList 344 (_ : err errMissingNode t) 345 (nodePayload rest : 346 lazyResult 347 (code after : err code after) 348 (tree _ : 349 lazyBool 350 (_ : ok tree t) 351 (_ : 352 self 353 rest 354 (nodeBuildState 355 nodeIndex 356 (succ i) 357 (pair (pair i tree) builtTrees))) 358 (equal? i nodeIndex)) 359 (nodePayloadToTreeFromBuilt builtTrees nodePayload)) 360 remainingRecords) 361 (nodeBuildStateBuiltTrees state))) 362 (nodeBuildStateI state))) 363 (nodeBuildStateTargetIndex state))) 364 365 nodeIndexToTree = (nodeRecords nodeIndex : 366 y nodeIndexToTree_ nodeRecords (nodeBuildState nodeIndex 0 t)) 367 368 readArboricxTreeFromIndex = (rootIndexBytes bs : 369 bindResult (readArboricxNodesSection bs) 370 (nodesSection afterContainer : 371 bindResult (nodeIndexToTree (nodesSectionRecords nodesSection) (u32BEBytesToNat rootIndexBytes)) 372 (tree _ : ok tree afterContainer))) 373 374 readArboricxExecutableFromIndex = readArboricxTreeFromIndex