tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

932049708c30961bba6c8820fec50edb08bb58e60ba2e811476436972b104e50.tri (15173B)


      1 !import prelude *
      2 !import binary *
      3 !import arboricx_common *
      4 !import arboricx_nodes *
      5 !export *
      6 
      7 readManifestMagic = (bs :
      8   expectBytes arboricxManifestMagic bs)
      9 
     10 -- Read a u32 BE length, then that many raw bytes.
     11 -- Returns the payload bytes and remaining input.
     12 readLengthPrefixedString = (bs :
     13   bindResult (readBytes 4 bs)
     14     (lengthBytes afterLengthBytes :
     15       bindResult (readBytes (u32BEBytesToNat lengthBytes) afterLengthBytes)
     16         (payload afterPayload :
     17           ok payload afterPayload)))
     18 
     19 -- Helper: read a single capability string (length-prefixed string)
     20 readCapability = (bs :
     21   readLengthPrefixedString bs)
     22 
     23 -- Helper worker: read N capability strings (counts up from 0)
     24 readCapabilities_ = y (self bs count i acc :
     25   matchBool
     26     (ok (reverse acc) bs)
     27     (bindResult (readCapability bs)
     28       (cap afterCap :
     29         self afterCap count (succ i) (pair cap acc)))
     30     (equal? i count))
     31 
     32 -- Helper: read N capabilities
     33 readCapabilities = (count bs :
     34   readCapabilities_ bs count 0 t)
     35 
     36 -- Helper: read a single root entry (4-byte u32 BE index + length-prefixed role)
     37 readRootEntry = (bs :
     38   bindResult (readBytes 4 bs)
     39     (indexRaw afterIndex :
     40       bindResult (readLengthPrefixedString afterIndex)
     41         (role afterRole :
     42           ok (pair indexRaw role) afterRole)))
     43 
     44 -- Helper worker: read N root entries (counts up from 0)
     45 readRoots_ = y (self bs count i acc :
     46   matchBool
     47     (ok (reverse acc) bs)
     48     (bindResult (readRootEntry bs)
     49       (root afterRoot :
     50         self afterRoot count (succ i) (pair root acc)))
     51     (equal? i count))
     52 
     53 -- Helper: read N roots
     54 readRoots = (count bs :
     55   readRoots_ bs count 0 t)
     56 
     57 -- Helper: read a single export entry
     58 readExportEntry = (bs :
     59   bindResult (readLengthPrefixedString bs)
     60     (name afterName :
     61       bindResult (readBytes 4 afterName)
     62         (rootIndexRaw afterRootIndex :
     63           bindResult (readLengthPrefixedString afterRootIndex)
     64             (kind afterKind :
     65               bindResult (readLengthPrefixedString afterKind)
     66                 (abi afterAbi :
     67                   ok (pair name (pair rootIndexRaw (pair kind abi))) afterAbi)))))
     68 
     69 -- Helper worker: read N export entries (counts up from 0)
     70 readExports_ = y (self bs count i acc :
     71   matchBool
     72     (ok (reverse acc) bs)
     73     (bindResult (readExportEntry bs)
     74       (exp afterExp :
     75         self afterExp count (succ i) (pair exp acc)))
     76     (equal? i count))
     77 
     78 -- Helper: read N exports
     79 readExports = (count bs :
     80   readExports_ bs count 0 t)
     81 
     82 -- Main core manifest parser.
     83 -- Reads: magic, version, core strings, capabilities, closure, roots, exports.
     84 readManifestCore = (bs :
     85   bindResult (readManifestMagic bs)
     86     (_ afterMagic :
     87       bindResult (readBytes 2 afterMagic)
     88         (majorVersion afterMajor :
     89           bindResult (readBytes 2 afterMajor)
     90             (minorVersion afterMinor :
     91               bindResult (readLengthPrefixedString afterMinor)
     92                 (schema afterSchema :
     93                   bindResult (readLengthPrefixedString afterSchema)
     94                     (bundleType afterBundleType :
     95                       bindResult (readLengthPrefixedString afterBundleType)
     96                         (treeCalculus afterTreeCalculus :
     97                           bindResult (readLengthPrefixedString afterTreeCalculus)
     98                             (treeHashAlgorithm afterTreeHashAlgorithm :
     99                               bindResult (readLengthPrefixedString afterTreeHashAlgorithm)
    100                                 (treeHashDomain afterTreeHashDomain :
    101                                   bindResult (readLengthPrefixedString afterTreeHashDomain)
    102                                     (treeNodePayload afterTreeNodePayload :
    103                                       bindResult (readLengthPrefixedString afterTreeNodePayload)
    104                                         (runtimeSemantics afterRuntimeSemantics :
    105                                           bindResult (readLengthPrefixedString afterRuntimeSemantics)
    106                                             (runtimeEvaluation afterRuntimeEvaluation :
    107                                               bindResult (readLengthPrefixedString afterRuntimeEvaluation)
    108                                                 (runtimeAbi afterRuntimeAbi :
    109                                                   bindResult (readBytes 4 afterRuntimeAbi)
    110                                                     (capCountRaw afterCapCountRaw :
    111                                                       bindResult (readCapabilities (u32BEBytesToNat capCountRaw) afterCapCountRaw)
    112                                                         (capabilities afterCapabilities :
    113                                                           bindResult (readBytes 1 afterCapabilities)
    114                                                             (closureByte afterClosureByte :
    115                                                               bindResult (readBytes 4 afterClosureByte)
    116                                                                 (rootCountRaw afterRootCountRaw :
    117                                                                   bindResult (readRoots (u32BEBytesToNat rootCountRaw) afterRootCountRaw)
    118                                                                     (roots afterRoots :
    119                                                                       bindResult (readBytes 4 afterRoots)
    120                                                                         (exportCountRaw afterExportCountRaw :
    121                                                                           bindResult (readExports (u32BEBytesToNat exportCountRaw) afterExportCountRaw)
    122                                                                             (exports afterExports :
    123                                                                               ok
    124                                                                                 (pair schema
    125                                                                                   (pair bundleType
    126                                                                                     (pair treeCalculus
    127                                                                                       (pair treeHashAlgorithm
    128                                                                                         (pair treeHashDomain
    129                                                                                           (pair treeNodePayload
    130                                                                                             (pair runtimeSemantics
    131                                                                                               (pair runtimeEvaluation
    132                                                                                                 (pair runtimeAbi
    133                                                                                                   (pair capabilities
    134                                                                     (pair closureByte (pair roots exports)))))))))))) afterExports))))))))))))))))))))
    135 
    136 -- Metadata tag constants (u16 values)
    137 tagPackage    = [(0) (1)]
    138 tagVersion    = [(0) (2)]
    139 tagDescription = [(0) (3)]
    140 tagLicense    = [(0) (4)]
    141 tagCreatedBy  = [(0) (5)]
    142 
    143 -- Read a single TLV entry: u16 tag + u32 length + value bytes.
    144 -- Returns the pair (tag, value) and remaining input.
    145 readTLV = (bs :
    146   bindResult (readBytes 2 bs)
    147     (tag afterTag :
    148       bindResult (readBytes 4 afterTag)
    149         (tlvLenRaw afterTlvLenRaw :
    150           bindResult (readBytes (u32BEBytesToNat tlvLenRaw) afterTlvLenRaw)
    151             (tlvValue afterTlvValue :
    152               ok (pair tag tlvValue) afterTlvValue))))
    153 
    154 -- Worker: read N TLV entries (counts up from 0)
    155 readTLVs_ = y (self bs count i acc :
    156   matchBool
    157     (ok (reverse acc) bs)
    158     (bindResult (readTLV bs)
    159       (tlv afterTlv :
    160         self afterTlv count (succ i) (pair tlv acc)))
    161     (equal? i count))
    162 
    163 -- Read a count followed by that many TLV entries.
    164 readTLVList = (count bs :
    165   readTLVs_ bs count 0 t)
    166 
    167 -- Skip N extension TLV entries (counts up from 0)
    168 skipTLVs_ = y (self bs count i :
    169   matchBool
    170     (ok unit bs)
    171     (bindResult (readTLV bs)
    172       (_ afterTlv :
    173         self afterTlv count (succ i)))
    174     (equal? i count))
    175 
    176 -- Full manifest parser: core fields + metadata TLV list + extension TLV list.
    177 readManifest = (bs :
    178   bindResult (readManifestCore bs)
    179     (coreManifest afterCore :
    180       bindResult (readBytes 4 afterCore)
    181         (metaCountRaw afterMetaCountRaw :
    182           bindResult (readTLVList (u32BEBytesToNat metaCountRaw) afterMetaCountRaw)
    183             (metadataFields afterMetadataFields :
    184               bindResult (readBytes 4 afterMetadataFields)
    185                 (extCountRaw afterExtCountRaw :
    186                   bindResult (skipTLVs_ afterExtCountRaw (u32BEBytesToNat extCountRaw) 0)
    187                     (afterExtensions _ :
    188                       ok
    189                         (pair coreManifest (pair metadataFields afterExtensions))
    190                         afterExtensions))))))
    191 
    192 -- Lookup a metadata value by tag from a TLV list.
    193 -- Returns nothing if not found, just value if found.
    194 lookupMetadata_ = y (self tlvs tag :
    195   matchList
    196     nothing
    197     (tlv rest :
    198       matchBool
    199         (just (matchPair (_ value : value) tlv))
    200         (self rest tag)
    201         (bytesEq? (matchPair (tlvTag _ : tlvTag) tlv) tag))
    202     tlvs)
    203 
    204 lookupMetadata = (tlvs tag :
    205   lookupMetadata_ tlvs tag)
    206 
    207 -- Get export name from an export entry (pair name (pair rootIndex (pair kind abi)))
    208 exportName = (exp :
    209   matchPair
    210     (name _ : name)
    211     exp)
    212 
    213 exportRoot = (exp :
    214   matchPair
    215     (_ payload :
    216       matchPair
    217         (root _ : root)
    218         payload)
    219     exp)
    220 
    221 -- Check if an export name matches a given byte string.
    222 exportNameEq? = (nameBytes exp :
    223   bytesEq? nameBytes (exportName exp))
    224 
    225 -- Find first export matching a name, or nothing.
    226 findExportByName_ = y (self exports name :
    227   matchList
    228     nothing
    229     (exp rest :
    230       matchBool
    231         (just exp)
    232         (self rest name)
    233         (exportNameEq? name exp))
    234     exports)
    235 
    236 findExportByName = (exports name :
    237   findExportByName_ exports name)
    238 
    239 -- Get list of all export names from a list of exports.
    240 getExportNames_ = y (self acc exports :
    241   matchList
    242     (reverse acc)
    243     (exp rest :
    244       self (pair (exportName exp) acc) rest)
    245     exports)
    246 
    247 getExportNames = (exports :
    248   getExportNames_ t exports)
    249 
    250 mainExportName = "main"
    251 
    252 maybeExportToResult = (maybeExport :
    253   triage
    254     (err errMissingSection t)
    255     (export : ok export t)
    256     (_ _ : err errMissingSection t)
    257     maybeExport)
    258 
    259 selectSingleExport = (exports :
    260   matchList
    261     (err errMissingSection t)
    262     (export rest :
    263       matchBool
    264         (ok export t)
    265         (err errMissingSection t)
    266         (emptyList? rest))
    267     exports)
    268 
    269 selectDefaultExport = (exports :
    270   triage
    271     (selectSingleExport exports)
    272     (export : ok export t)
    273     (_ _ : err errMissingSection t)
    274     (findExportByName exports mainExportName))
    275 
    276 -- Select an export: explicit name if provided, otherwise "main", otherwise
    277 -- the sole export if the bundle has exactly one export.
    278 selectExport = (exports nameBytes :
    279   matchBool
    280     (selectDefaultExport exports)
    281     (maybeExportToResult (findExportByName exports nameBytes))
    282     (emptyList? nameBytes))
    283 
    284 selectExportOpt = (exports optNameBytes :
    285   selectExport exports optNameBytes)
    286 
    287 -- Expected core string values (raw UTF-8 bytes, not decoded to Unicode characters).
    288 expectedSchema = "arboricx.bundle.manifest.v1"
    289 expectedBundleType = "tree-calculus-executable-object"
    290 expectedTreeCalculus = "tree-calculus.v1"
    291 expectedTreeHashAlgorithm = "indexed"
    292 expectedTreeHashDomain = "arboricx.indexed.node.v1"
    293 expectedTreeNodePayload = "arboricx.indexed.payload.v1"
    294 expectedRuntimeSemantics = "tree-calculus.v1"
    295 expectedRuntimeEvaluation = "normal-order"
    296 expectedRuntimeAbi = "arboricx.abi.tree.v1"
    297 
    298 -- Manifest core field accessors.
    299 -- readManifestCore returns: (pair schema (pair bundleType (... (pair closureByte (pair roots exports)))))
    300 pairFirst = (p : matchPair (a _ : a) p)
    301 pairSecond = (p : matchPair (_ b : b) p)
    302 
    303 manifestSchema = (core : pairFirst core)
    304 manifestBundleType = (core : pairFirst (pairSecond core))
    305 manifestTreeCalculus = (core : pairFirst (pairSecond (pairSecond core)))
    306 manifestTreeHashAlgorithm = (core : pairFirst (pairSecond (pairSecond (pairSecond core))))
    307 manifestTreeHashDomain = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond core)))))
    308 manifestTreeNodePayload = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core))))))
    309 manifestRuntimeSemantics = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core)))))))
    310 manifestRuntimeEvaluation = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core))))))))
    311 manifestRuntimeAbi = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core)))))))))
    312 manifestCapabilities = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core))))))))))
    313 manifestClosureByte = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core)))))))))))
    314 manifestRoots = (core : pairFirst (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core))))))))))))
    315 manifestExports = (core : pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond (pairSecond core))))))))))))
    316 
    317 -- Helper: compare a manifest field against an expected byte string.
    318 manifestFieldMatch? = (actual expected : bytesEq? actual expected)
    319 
    320 -- Validate core manifest fields against expected values.
    321 validateManifestCore = (core rest :
    322   matchBool
    323     (ok core rest)
    324     (err errManifestValidationFailed rest)
    325     (and?
    326       (manifestFieldMatch? (manifestSchema core) expectedSchema)
    327       (and?
    328         (manifestFieldMatch? (manifestBundleType core) expectedBundleType)
    329         (and?
    330           (manifestFieldMatch? (manifestTreeCalculus core) expectedTreeCalculus)
    331           (and?
    332             (manifestFieldMatch? (manifestTreeHashAlgorithm core) expectedTreeHashAlgorithm)
    333             (and?
    334               (manifestFieldMatch? (manifestTreeHashDomain core) expectedTreeHashDomain)
    335               (and?
    336                 (manifestFieldMatch? (manifestTreeNodePayload core) expectedTreeNodePayload)
    337                 (and?
    338                   (manifestFieldMatch? (manifestRuntimeSemantics core) expectedRuntimeSemantics)
    339                   (and?
    340                     (manifestFieldMatch? (manifestRuntimeEvaluation core) expectedRuntimeEvaluation)
    341                     (and?
    342                       (manifestFieldMatch? (manifestRuntimeAbi core) expectedRuntimeAbi)
    343                       (and?
    344                         (bytesEq? (manifestClosureByte core) [(0)])
    345                         (and?
    346                           (not? (emptyList? (manifestRoots core)))
    347                           (not? (emptyList? (manifestExports core)))))))))))))))