# tricu Host ABI This document specifies the first host-facing ABI for self-hosted Arboricx execution. The ABI is intentionally small. A host language should only need to implement Tree Calculus construction/reduction plus a tiny set of canonical payload codecs. Higher-level execution policy lives in Tree Calculus. ## Goals - Keep host-language implementations small and auditable. - Preserve canonical Tree Calculus representations for payloads. - Provide a stable tagged envelope so hosts do not need per-application result conventions. - Reuse the existing `ok` / `err` result protocol. - Support typed execution wrappers for common return types. ## Non-goals - This ABI does not remove the need for host codecs entirely. - This ABI does not define every possible application protocol. - This ABI does not require auto-detecting arbitrary result types. ## Outer result protocol Host ABI runners return the existing tricu result shape from `lib/binary.tri`: ```tricu ok value rest = pair true (pair value rest) err code rest = pair false (pair code rest) ``` On success, `value` is a host ABI value. On failure, `code` is a canonical Tree Calculus number. The host may report the numeric code and optionally inspect `rest` for debugging. ## Host ABI value shape A host ABI value is: ```tricu pair tag payload ``` The `tag` says how the host should interpret `payload`. The payload is always the canonical/raw Tree Calculus representation for that type. The ABI envelope tags the payload; it does not replace or recursively wrap canonical Tree Calculus data. ## Tags Initial tags: ```tricu hostTreeTag = 0 hostStringTag = 1 hostNumberTag = 2 hostBoolTag = 3 hostListTag = 4 hostBytesTag = 5 ``` Planned/error tag, if needed later: ```tricu hostErrorTag = 6 ``` The first implementation keeps errors in the outer `err` result protocol rather than returning `hostError` inside `ok`. ## Constructors The ABI constructors are: ```tricu hostTree value hostString bytes hostNumber n hostBool b hostList xs hostBytes bytes ``` Each constructor returns: ```tricu pair tag payload ``` Examples: ```tricu hostString "hello" hostNumber 42 hostBool true hostList [1 2 3] hostTree (t t t) ``` ## Payload conventions Payloads use existing canonical tricu encodings: | ABI value | Payload | | --- | --- | | `hostTree` | arbitrary raw Tree Calculus value | | `hostString` | canonical string/byte-list representation | | `hostNumber` | canonical tricu number | | `hostBool` | canonical tricu bool (`false = t`, `true = t t`) | | `hostList` | canonical tricu list (`t` empty, `pair head tail` cons) | | `hostBytes` | canonical byte list | `hostList` payloads are raw canonical lists, **not** lists of host ABI values. ## Accessors / matching The first ABI should expose simple accessors: ```tricu hostValueTag hostValue hostValuePayload hostValue ``` A host can decode the envelope by destructuring the pair directly, but these helpers make the ABI explicit and testable. ## Validation predicates Typed runners should validate that the raw application result can be interpreted as the requested type before wrapping it. Initial predicates: ```tricu hostNumber? value hostBool? value hostList? value hostString? value hostBytes? value ``` These predicates are structural checks over canonical encodings. They are not general semantic type inference. Important ambiguity note: Tree Calculus encodings are not globally disjoint. For example, `t` is also `false`, `0`, and `[]`. Typed runners intentionally interpret values according to the requested type. ## Error behavior Typed ABI runners return an error if the application result does not match the requested type. Initial error code: ```tricu errHostCodecFailed = 14 ``` Example: ```tricu runArboricxToString bundle args ``` returns: ```tricu ok (hostString resultBytes) rest ``` if `resultBytes` is string-like, otherwise: ```tricu err errHostCodecFailed result ``` where `result` is the raw application result that failed validation. ## Execution wrappers The base self-hosted Arboricx runners are defined in `lib/arboricx.tri`: ```tricu runArboricxArgs bundleBytes args runArboricxArgsByName nameBytes bundleBytes args ``` Host ABI wrappers layer typed output envelopes on top: ```tricu runArboricxToTree bundleBytes args runArboricxToString bundleBytes args runArboricxToNumber bundleBytes args runArboricxToBool bundleBytes args runArboricxToList bundleBytes args runArboricxToBytes bundleBytes args ``` Named-export variants: ```tricu runArboricxByNameToTree nameBytes bundleBytes args runArboricxByNameToString nameBytes bundleBytes args runArboricxByNameToNumber nameBytes bundleBytes args runArboricxByNameToBool nameBytes bundleBytes args runArboricxByNameToList nameBytes bundleBytes args runArboricxByNameToBytes nameBytes bundleBytes args ``` ## Host usage For a bundle whose default export is an unapplied function: ```tricu append "hello " ``` A host that expects a string result evaluates: ```tricu runArboricxToString bundleBytes ["james"] ``` On success, the result is: ```tricu ok (hostString "hello james") rest ``` The host then: 1. unwraps `ok`, 2. checks `hostStringTag`, 3. decodes the canonical string payload. ## Implementation reference - Tree constructors, numbers, strings, and lists: `src/Research.hs` - Result protocol: `lib/binary.tri` - Arboricx parser/executor: `lib/arboricx.tri` - Host ABI implementation: `lib/host-abi.tri` or `lib/arboricx.tri`, depending on final organization ## First-pass invariants Tests should cover these invariants: 1. Each constructor stores the correct tag and payload. 2. `hostValueTag` and `hostValuePayload` destructure values correctly. 3. `runArboricxToTree` always wraps successful raw results as `hostTree`. 4. `runArboricxToString` wraps string-like results as `hostString`. 5. `runArboricxToNumber` wraps number-like results as `hostNumber`. 6. `runArboricxToBool` wraps canonical booleans as `hostBool`. 7. A typed runner returns `errHostCodecFailed` when validation fails. 8. Named-export typed runners select the requested export before wrapping.