AVM Runtime
This module defines the execution environment and runtime infrastructure for the AVM. It provides the state representation, error types, result types, and observability mechanisms used by the interpreter.
{-# OPTIONS --without-K --type-in-type --guardedness --exact-split #-} open import Foundation.BasicTypes
Module Parameters
module AVM.Runtime -- Core types (Val : Set) (ObjectId : Set) (freshObjectId : ℕ → ObjectId) -- Machine/distribution types (MachineId : Set) -- Controller/distribution types (ControllerId : Set) (ControllerVersion : Set) -- Transaction types (TxId : Set) (freshTxId : ℕ → TxId) -- Object model type (Object : Set) where
Message Types
Message passing is the only way to communicate between objects. The representation of messages is left abstract by design.
The general I-O object model (φ : I* ⇀ O) permits distinct input type I and output type O. The current implementation uses the same type (Val) for both Input and Output for simplicity. Future refinements may parameterize modules by separate Input and Output types to support heterogeneous communication (e.g., Input = Command, Output = Response).
Message : Set Message = Val Input : Set Input = Message Output : Set Output = Message
Object Metadata
Extrinsic metadata managed by the AVM includes the object's identifier, accumulated input history, physical location, and controller assignments. Objects reside on machines (physical nodes) and are owned by controllers (logical authorities that order transactions). Each object tracks its current machine location, which controller created it, which controller currently owns it, and version numbers for distributed consistency.
record ObjectMeta : Set where constructor mkMeta field objectId : ObjectId history : List Input -- Accumulated inputs -- Physical location machine : MachineId -- Where object data resides -- Simplified controller tracking creatingController : ControllerId -- Who created (immutable) currentController : ControllerId -- Who controls now -- Version tracking for distribution createdAtVersion : ControllerVersion modifiedAtVersion : ControllerVersion
Store: Persistent Object Database
The AVM provides a view of the store of all objects. The store separates intrinsic object behaviors from their runtime metadata. This view is partial because an object may not yet exist in the store or may not be available.
ObjectStore
ObjectStore : Set ObjectStore = ObjectId → Maybe Object
MetaStore
MetaStore : Set MetaStore = ObjectId → Maybe ObjectMeta
Store Record
record Store : Set where constructor mkStore field objects : ObjectStore -- Immutable behaviors metadata : MetaStore -- Mutable runtime state
The Store abstraction separates the persistent object database from ephemeral execution state. This separation distinguishes what persists across transactions (the store) from what exists only during execution (transaction overlays and execution context).
Transactional Semantics
Transactions provide atomicity. State modifications within a transaction remain tentative until committed; abortion discards all changes. The AVM maintains a transaction log recording pending object writes, creations, destructions, and cross-controller transfers.
TxWrite
A transaction write pairs an object identifier with an input message. The transaction log accumulates these pairs in order. Multiple writes to the same object within a transaction preserve ordering, enabling sequential object behavior within atomic boundaries.
TxWrite : Set TxWrite = ObjectId × Input
Pure Functions
A collection of pure functions indexed by name. Each function takes a list of
arguments and may return a value (or fail with nothing if the arguments are
invalid).
PureFunctions : Set PureFunctions = String -- function name -> Maybe ( -- lookup result List Val -- fun. arguments -> Maybe Val -- fun. result )
Execution State
The AVM maintains a global execution state that captures all information needed for transactional computation. Each instruction execution operates as a state transition: given the current state and an instruction, the interpreter produces a result value, an updated state, and an execution trace.
record State : Set where field -- Current execution location machineId : MachineId -- Physical machine executing this program -- Current controller identity controllerId : ControllerId currentVersion : ControllerVersion -- Object storage (separated) store : Store -- Combined store with objects and metadata -- Pure function collection (can be extended over time) -- Think of this as a library for programs to use. pureFunctions : PureFunctions -- Transaction context (overlay) txLog : List TxWrite -- Tentative writes: (objectId , input) creates : List (ObjectId × Object × ObjectMeta) -- Pending creates destroys : List ObjectId -- Pending destroys observed : List (ObjectId × ControllerVersion) -- Observed versions (for commit-time validation) pendingTransfers : List (ObjectId × ControllerId) -- Pending object moves tx : Maybe TxId -- Active transaction id (if any) -- Current execution frame self : ObjectId -- Current object being processed input : Input -- Current input being processed traceMode : Bool -- Debug tracing flag
The State record organizes fields into five logical groups:
- Physical execution context:
machineIdidentifies the physical machine where this program is currently executing. This is independent of logical controller identity and enables reasoning about data locality and cross-machine communication costs.
- Controller context:
controllerIdidentifies the executing controller (logical authority), andcurrentVersiontracks its protocol version. These fields enable distributed consistency checking across controller boundaries.
- Persistent storage:
storeholds the object database (both behaviors and metadata), andpureFunctionsmaintains the extensible pure function registry. These components persist across instruction executions.
- Transactional overlay:
txLogaccumulates uncommitted writes (object-input pairs),createsanddestroystrack pending object lifecycle changes,observedrecords object versions for conflict detection,pendingTransfersqueues cross-controller object moves, andtxholds the active transaction identifier (ornothingif no transaction is active).
- Execution frame:
selfidentifies the currently executing object,inputholds the message being processed, andtraceModeenables debug logging when set totrue.
Layered Error Types
Instructions may fail during execution. Each instruction family defines its own error domain, and these domains compose to form layered error types matching the instruction set hierarchy. This design provides type-level guarantees about which errors can occur at each layer.
Object Errors
Object lifecycle and interaction operations fail when objects are missing, destroyed, or reject inputs.
data ObjError : Set where ErrObjectNotFound : ObjectId → ObjError ErrObjectAlreadyDestroyed : ObjectId → ObjError ErrObjectAlreadyExists : ObjectId → ObjError ErrInvalidInput : ObjectId → Input → ObjError ErrObjectRejectedCall : ObjectId → Input → ObjError ErrMetadataCorruption : ObjectId → ObjError
Introspection Errors
Introspection operations fail when the object store is corrupted.
data IntrospectError : Set where ErrStoreCorruption : String → IntrospectError
Transaction Errors
Transaction operations fail due to conflicts, missing transactions, or invalid nesting.
data TxError : Set where ErrTxConflict : TxId → TxError ErrTxNotFound : TxId → TxError ErrTxAlreadyCommitted : TxId → TxError ErrTxAlreadyAborted : TxId → TxError ErrNoActiveTx : TxError ErrInvalidDuringTx : String → TxError
Distribution Errors
Distribution operations fail when controllers or machines are unreachable, transfers are unauthorized, or version mismatches occur.
data DistribError : Set where -- Controller errors ErrControllerUnreachable : ControllerId → DistribError ErrUnauthorizedTransfer : ObjectId → ControllerId → DistribError ErrVersionMismatch : ControllerVersion → ControllerVersion → DistribError ErrCrossControllerTx : ObjectId → ControllerId → DistribError -- Machine errors ErrMachineUnreachable : MachineId → DistribError ErrInvalidMachineTransfer : ObjectId → MachineId → DistribError
Pure Function Errors
Pure function operations fail when functions are missing or already registered.
data PureError : Set where ErrFunctionNotFound : String → PureError ErrFunctionAlreadyRegistered : String → PureError
Composed Error Types
Error types compose in layers matching the instruction set hierarchy. Each layer includes errors from previous layers plus domain-specific errors.
Base Layer Error (Instr₀)
The base layer combines object and introspection errors.
data BaseError : Set where obj-error : ObjError → BaseError introspect-error : IntrospectError → BaseError
Transaction Layer Error (Instr₁)
The transaction layer adds transaction errors to base errors.
data TxLayerError : Set where base-error : BaseError → TxLayerError tx-error : TxError → TxLayerError
Pure Function Layer Error (Instr₂)
The pure function layer adds pure computation errors to transactional errors.
data PureLayerError : Set where tx-layer-error : TxLayerError → PureLayerError pure-error : PureError → PureLayerError
Full AVM Error
The full error type includes all instruction errors plus distribution errors.
data AVMError : Set where pure-layer-error : PureLayerError → AVMError distrib-error : DistribError → AVMError
Error Pattern Synonyms
Pattern synonyms eliminate verbose nested constructor applications when constructing or matching errors.
Object Error Patterns
pattern err-object-not-found oid = pure-layer-error (tx-layer-error (base-error (obj-error (ErrObjectNotFound oid)))) pattern err-object-destroyed oid = pure-layer-error (tx-layer-error (base-error (obj-error (ErrObjectAlreadyDestroyed oid)))) pattern err-object-exists oid = pure-layer-error (tx-layer-error (base-error (obj-error (ErrObjectAlreadyExists oid)))) pattern err-invalid-input oid inp = pure-layer-error (tx-layer-error (base-error (obj-error (ErrInvalidInput oid inp)))) pattern err-object-rejected oid inp = pure-layer-error (tx-layer-error (base-error (obj-error (ErrObjectRejectedCall oid inp)))) pattern err-metadata-corruption oid = pure-layer-error (tx-layer-error (base-error (obj-error (ErrMetadataCorruption oid))))
Introspection Error Patterns
pattern err-store-corruption msg = pure-layer-error (tx-layer-error (base-error (introspect-error (ErrStoreCorruption msg))))
Transaction Error Patterns
pattern err-tx-conflict tid = pure-layer-error (tx-layer-error (tx-error (ErrTxConflict tid))) pattern err-tx-not-found tid = pure-layer-error (tx-layer-error (tx-error (ErrTxNotFound tid))) pattern err-tx-committed tid = pure-layer-error (tx-layer-error (tx-error (ErrTxAlreadyCommitted tid))) pattern err-tx-aborted tid = pure-layer-error (tx-layer-error (tx-error (ErrTxAlreadyAborted tid))) pattern err-no-active-tx = pure-layer-error (tx-layer-error (tx-error ErrNoActiveTx)) pattern err-invalid-during-tx msg = pure-layer-error (tx-layer-error (tx-error (ErrInvalidDuringTx msg)))
Pure Function Error Patterns
pattern err-function-not-found name = pure-layer-error (pure-error (ErrFunctionNotFound name)) pattern err-function-registered name = pure-layer-error (pure-error (ErrFunctionAlreadyRegistered name))
Distribution Error Patterns
-- Controller error patterns pattern err-controller-unreachable cid = distrib-error (ErrControllerUnreachable cid) pattern err-unauthorized-transfer oid cid = distrib-error (ErrUnauthorizedTransfer oid cid) pattern err-version-mismatch v1 v2 = distrib-error (ErrVersionMismatch v1 v2) pattern err-cross-controller-tx oid cid = distrib-error (ErrCrossControllerTx oid cid) -- Machine error patterns pattern err-machine-unreachable mid = distrib-error (ErrMachineUnreachable mid) pattern err-invalid-machine-transfer oid mid = distrib-error (ErrInvalidMachineTransfer oid mid)
Observability and Tracing
State transitions generate observable events. The interpreter records object creation, destruction, message passing, transaction boundaries, and controller operations in a chronological log. Each log entry pairs an event type with a timestamp and executing controller identifier. This mechanism supports debugging, auditing, and formal verification of execution histories.
EventType
data EventType : Set where -- Object lifecycle events ObjectCreated : ObjectId → Val → EventType ObjectDestroyed : ObjectId → EventType -- Object interaction events ObjectCalled : ObjectId → Input → Maybe Output → EventType -- Machine events ObjectMoved : ObjectId → MachineId → MachineId → EventType ExecutionMoved : MachineId → MachineId → EventType -- Controller events (ownership changes) ObjectTransferred : ObjectId → ControllerId → ControllerId → EventType ControllerSwitched : ControllerId → ControllerVersion → EventType -- Transaction events TransactionStarted : TxId → EventType TransactionCommitted : TxId → EventType TransactionAborted : TxId → EventType -- Error events ErrorOccurred : AVMError → EventType
LogEntry
record LogEntry : Set where constructor mkLogEntry field timestamp : ℕ eventType : EventType executingController : ControllerId
Trace
Trace : Set Trace = List LogEntry
Result Types
Instruction execution produces either success or failure. The Result type encodes this dichotomy: successful executions yield a value, updated state, and trace; failures yield only an error. This design threads state and trace information through the interpreter while enabling early termination on errors.
Success Record
Successful execution returns three components: the instruction's result value, the modified execution state, and the trace of events generated. A record structure provides named field access, eliminating tuple projections.
record Success (A : Set) : Set where constructor mkSuccess field value : A state : State trace : Trace open Success public
Result Datatype
A polymorphic sum type distinguishes success from failure. The type parameter
A specifies the result value type, while parameter E specifies the error
type. The success constructor wraps a Success record; the failure
constructor wraps an error value.
data Result (A : Set) (E : Set) : Set where success : Success A → Result A E failure : E → Result A E
Layer-Specific Result Types
Each instruction layer has a precise result type reflecting its error domain.
BaseResult : Set → Set BaseResult A = Result A BaseError TxResult : Set → Set TxResult A = Result A TxLayerError PureResult : Set → Set PureResult A = Result A PureLayerError AVMResult : Set → Set AVMResult A = Result A AVMError
The Result type makes explicit that:
- Success returns a record with named fields:
value,state, andtrace - Failure returns only an error value of the specified error type
- Named fields eliminate nested tuple projections and improve code clarity
Module References
Referenced By
This module is referenced by:
- AVM.Examples
- AVM.Instruction
- Symbols: Input, ObjectMeta, Output
- AVM.Interpreter
- Symbols: AVMResult, ControllerSwitched, EventType, ExecutionMoved, Input, LogEntry, ObjectCalled, ObjectCreated, ObjectDestroyed, ObjectMeta, ObjectMoved, ObjectTransferred, Output, State, Trace, TransactionAborted, TransactionCommitted, TransactionStarted, err-controller-unreachable, err-cross-controller-tx, err-invalid-during-tx, err-invalid-input, err-machine-unreachable, err-metadata-corruption, err-no-active-tx, err-object-not-found, err-tx-conflict, failure, mkLogEntry, mkMeta, mkSuccess, success
- AVM.Objects
- AVM.SmallExample
- Symbols: AVMResult, ObjectMeta, PureFunctions, State, Store, mkMeta, mkStore
References
This module references: