Instruction Set
The AVM instruction set architecture (ISA) defines the primitive operations available to AVM programs. The instruction taxonomy is organized into distinct instruction sets, each characterized by specific safety levels and operational capabilities.
The instruction architecture exhibits hierarchical organization, wherein each successive layer extends the previous layer with additional operational capabilities. While individual instruction families (e.g., ObjInstruction, TxInstruction) are defined independently, the numbered instruction sets (Instr₀, Instr₁, etc.) compose these families in a cumulative layered hierarchy where each level subsumes all capabilities from previous layers.
AVM Instruction Set Module Parameters
This module exhibits parametric polymorphism over types representing values, object behaviours, transactions, and distributed execution infrastructure (encompassing both physical machines and logical controllers).
Module Parameters
module AVM.Instruction -- Core types (Val : Set) -- Used for both Input and Output currently (ObjectId : Set) -- Machine/distribution types (MachineId : Set) -- Controller/distribution types (ControllerId : Set) -- Transaction types (TxId : Set) -- Object behaviour type -- In concrete instantiations, this is AVMProgram (List Val) (ObjectBehaviour : Set) where open import AVM.Context Val ObjectId MachineId ControllerId TxId ObjectBehaviour public
AVM Instruction Set Algebraic Datatypes
The instruction sets are formalised as inductive algebraic datatypes, wherein each data constructor represents a distinct instruction within the corresponding instruction set family.
Each instruction set datatype is indexed by a safety level parameter that characterises the security properties of instructions within the set. The safety level indexing enables compile-time enforcement of the invariant that safe programs cannot invoke unsafe operations, thereby providing static safety guarantees.
The instruction set architecture uses the following type-level signature:
ISA : Set ISA = Set -> Set
The ISA type represents an instruction signature family wherein each instruction is indexed by its return type ISA, thereby establishing ISA as a parameterised type family.
Safety Datatype
The specification defines two distinct safety levels: Safe and Unsafe. Instructions are classified as unsafe when their execution violates foundational principles of the object model encapsulation properties or introduces systemic security risks to the virtual machine execution environment.
data Safety : Set where Safe : Safety Unsafe : Safety
Object Lifecycle and Communication Instructions
The object instruction family constitutes the foundational layer of the AVM ISA hierarchy. This layer provides primitive object-oriented operations encompassing object lifecycle management (creation and destruction) and inter-object communication realized through message-passing semantics.
ObjInstruction datatype
-- Object lifecycle and communication data ObjInstruction : Safety → ISA where -- Object lifecycle createObj : String → Maybe ControllerId → ObjInstruction Safe ObjectId destroyObj : ObjectId → ObjInstruction Safe Bool -- May fail if object doesn't exist -- Message passing (may fail if object doesn't exist or rejects input) call : ObjectId → Input → ObjInstruction Safe (Maybe Output) -- Asynchronous message reception (waits for next message) receive : ObjInstruction Safe (Maybe Input)
These instructions realise the fundamental object-oriented programming model within the AVM. Objects are created through createObj, terminated via destroyObj, and interact through synchronous message-passing using the call instruction. The receive instruction allows objects to wait for incoming messages from other objects or the runtime environment and pattern match on the received message.
Runtime Introspection Instructions
The introspection instruction family constitutes the second layer of the AVM ISA hierarchy. This layer provides primitive introspection operations enabling programs to query their own execution context—the current object's identity, input, internal state, and caller information.
Introspection is distinguished from reflection: introspection examines the self (current execution context), while reflection examines others (external objects' metadata and internals).
IntrospectInstruction Datatype
Introspection instructions provide capabilities for querying and updating the current object's own execution context. All introspection operations are safe because they only access information the executing object legitimately owns.
data IntrospectInstruction : Safety → ISA where self : IntrospectInstruction Safe ObjectId input : IntrospectInstruction Safe Input getCurrentMachine : IntrospectInstruction Safe MachineId getState : IntrospectInstruction Safe (List Val) setState : List Val → IntrospectInstruction Safe ⊤ sender : IntrospectInstruction Safe (Maybe ObjectId)
Runtime Reflection Instructions
The reflection instruction family provides capabilities for examining other objects' metadata and internal state without invoking their message-passing interface. Reflection breaks object encapsulation by exposing information that objects do not voluntarily reveal through their public interface.
All reflection operations are unsafe because they violate the encapsulation principle that objects exclusively control what information they expose to external observers.
ReflectInstruction Datatype
data ReflectInstruction : Safety → ISA where reflect : ObjectId → ReflectInstruction Unsafe (Maybe ObjectMeta) scryMeta : (ObjectMeta → Bool) → ReflectInstruction Unsafe (List (ObjectId × ObjectMeta)) scryDeep : (ObjectBehaviour → ObjectMeta → Bool) → ReflectInstruction Unsafe (List RuntimeObjectWithId)
The reflect instruction retrieves metadata for a specified object identifier without invoking the object's message-passing interface. This operation violates the encapsulation principle that objects exclusively control the information they expose to external observers.
The scryMeta instruction performs predicate-based queries over the object store, selecting objects whose metadata satisfies a specified boolean predicate. The instruction returns pairs of object identifiers and corresponding metadata for all matching entities.
The scryDeep instruction extends this capability by enabling predicate evaluation over both object internal state and metadata, returning the complete object representation. Both instructions require complete store traversal, introducing computational complexity risks scaling linearly with the total object population.
Reification Instructions
Reification is the mechanism for encoding execution state as first-class data. While introspection queries the current context and reflection examines other objects, reification captures runtime state structures as values that can be stored, transmitted, or later analyzed.
Reification enables:
- Debugging: Capturing execution snapshots for post-mortem analysis
- Migration: Serializing execution state for process migration
- Checkpointing: Creating restorable execution snapshots
- Auditing: Recording execution state for compliance verification
ReifyInstruction Datatype
- Reified execution context (safe subset of State)
record ReifiedContext : Set where constructor mkReifiedContext field contextSelf : ObjectId contextInput : Input contextSender : Maybe ObjectId contextMachine : MachineId contextController : ControllerId
- Reified transaction state
record ReifiedTxState : Set where constructor mkReifiedTxState field txStateId : Maybe TxId txStateWrites : List (ObjectId × Input) txStateCreates : List ObjectId txStateDestroys : List ObjectId txStateObserved : List ObjectId
- Reified constraint store (for FD layer)
record ReifiedConstraints : Set where constructor mkReifiedConstraints field -- Variable domains: list of (variable id, current domain values) constraintVars : List (ℕ × List Val) -- Posted constraints (simplified representation) constraintCount : ℕ
data ReifyInstruction : Safety → ISA where -- Safe: reify own execution context reifyContext : ReifyInstruction Safe ReifiedContext -- Unsafe: reify transaction state (exposes pending writes) reifyTxState : ReifyInstruction Unsafe (Maybe ReifiedTxState) -- Unsafe: reify constraint store (exposes solver state) reifyConstraints : ReifyInstruction Unsafe ReifiedConstraints
The reifyContext instruction captures the current execution frame as a first-class value. This is safe because it only accesses information already available through individual introspection instructions.
The reifyTxState instruction captures the current transaction's pending state including uncommitted writes, creates, and destroys. This is unsafe because it exposes tentative state that may be rolled back.
The reifyConstraints instruction captures the constraint solver's internal state including variable domains and constraint counts. This is unsafe because it exposes solver internals that programs should not depend on.
Instr₀: The Minimal Instruction Set
The foundational instruction layers are composed to form the minimal instruction set, designated Instr₀.
This constitutes the foundational instruction set in the AVM ISA hierarchy, encompassing the base object lifecycle operations, runtime introspection, reflection, and reification capabilities.
data Instr₀ : Safety → ISA where Obj : ∀ {s A} → ObjInstruction s A → Instr₀ s A Introspect : ∀ {s A} → IntrospectInstruction s A → Instr₀ s A Reflect : ∀ {s A} → ReflectInstruction s A → Instr₀ s A Reify : ∀ {s A} → ReifyInstruction s A → Instr₀ s A
open import Background.InteractionTrees
TxInstruction datatype
This is the third layer of the AVM ISA. It provides the fundamental transactional operations for managing atomic execution contexts.
data TxInstruction : Safety → ISA where beginTx : Maybe ControllerId → TxInstruction Safe TxId commitTx : TxId → TxInstruction Safe Bool -- May fail if conflicts abortTx : TxId → TxInstruction Safe ⊤
Instr₁ instruction set, adds transactional support
Programs that can roll back changes are possible via TxInstruction. With this feature, we can define our second instruction set, Instr₁:
data Instr₁ : Safety → ISA where Obj : ∀ {s A} → ObjInstruction s A → Instr₁ s A Introspect : ∀ {s A} → IntrospectInstruction s A → Instr₁ s A Reflect : ∀ {s A} → ReflectInstruction s A → Instr₁ s A Reify : ∀ {s A} → ReifyInstruction s A → Instr₁ s A Tx : ∀ {s A} → TxInstruction s A → Instr₁ s A
PureInstruction datatype
This is the fourth layer of the AVM ISA. This step adds means to call pure functions, register new pure functions, and update existing pure functions. Thus, think of this as a capability to extend the any instruction set with deterministic computation. For example adding arbitrary arithmetic operations to the instruction set.
data PureInstruction : Safety → ISA where -- Call a registered pure function by identifier callPure : String → List Val → PureInstruction Safe (Maybe Val) -- Register new pure function (unsafe - extends the function set) registerPure : String → (List Val → Maybe Val) → PureInstruction Unsafe Bool -- Update function definition for a given function identifier updatePure : String → (List Val → Maybe Val) → PureInstruction Safe Bool
Instr₂ instruction set, adds pure function computation
With the ability to call pure functions, we can define our third instruction set, Instr₂, which adds pure function computation to the transactional instruction set:
data Instr₂ : Safety → ISA where Obj : ∀ {s A} → ObjInstruction s A → Instr₂ s A Introspect : ∀ {s A} → IntrospectInstruction s A → Instr₂ s A Reflect : ∀ {s A} → ReflectInstruction s A → Instr₂ s A Reify : ∀ {s A} → ReifyInstruction s A → Instr₂ s A Tx : ∀ {s A} → TxInstruction s A → Instr₂ s A Pure : ∀ {s A} → PureInstruction s A → Instr₂ s A
Distribution Layer: Machine and Controller Instructions
This is the fifth layer of the AVM ISA, which provides instructions for managing distributed execution across physical machines and logical controllers.
AVM programs execute in a distributed environment with two orthogonal concepts: physical machines (where computation and storage occur) and logical controllers (who order transactions and own objects). This separation enables independent reasoning about data consistency, locality, and authority.
We split the distribution layer into two instruction families to maintain clear separation of concerns, enable independent testing, and support distinct policy enforcement for physical versus logical operations.
MachineInstruction datatype
Machines are physical nodes that host computation and object data. Programs can query which machine holds an object's data and move execution or data objects between machines. Machine operations deal with physical resource location and object data migration.
data MachineInstruction : Safety → ISA where -- Query physical machine location of object data getMachine : ObjectId → MachineInstruction Safe (Maybe MachineId) -- Move execution context (process) to another machine teleport : MachineId → MachineInstruction Safe Bool -- Move object data to another machine (changes physical location) moveObject : ObjectId → MachineId → MachineInstruction Safe Bool -- Bring object replica to local machine for local access fetch : ObjectId → MachineInstruction Safe Bool
Safety constraints: teleport is invalid during active transactions. Attempting to teleport while a transaction is in progress should result in an error.
ControllerInstruction datatype
Controllers are logical authorities that order transactions and own object consistent state. Each object records which controller created it, which controller currently owns it. Programs can query controller ownership and transfer objects between controllers without moving their physical location. Controller operations deal with logical resource location and object data consistency.
data ControllerInstruction : Safety → ISA where -- Query controller identity and ownership getCurrentController : ControllerInstruction Safe (Maybe ControllerId) getController : ObjectId → ControllerInstruction Safe (Maybe ControllerId) -- Transfer object ownership to another controller (changes logical authority) transferObject : ObjectId → ControllerId → ControllerInstruction Safe Bool -- Freeze: synchronize all replicas through the controller for strong consistency -- When multiple machines have fetched the same object, freeze reconciles their state -- Returns: nothing (no controller), just true (success), just false (object missing/unreachable) freeze : ObjectId → ControllerInstruction Safe (Maybe Bool)
Authority requirements: transferObject requires proper authorization. The current controller must have authority to transfer the object.
Instr₃ instruction set, adds distributed operations
With machine and controller instructions, we can now define our fourth instruction set, Instr₃. This instruction set adds distributed computing capabilities to the pure function instruction set.
data Instr₃ : Safety → ISA where Obj : ∀ {s A} → ObjInstruction s A → Instr₃ s A Introspect : ∀ {s A} → IntrospectInstruction s A → Instr₃ s A Reflect : ∀ {s A} → ReflectInstruction s A → Instr₃ s A Reify : ∀ {s A} → ReifyInstruction s A → Instr₃ s A Tx : ∀ {s A} → TxInstruction s A → Instr₃ s A Pure : ∀ {s A} → PureInstruction s A → Instr₃ s A Machine : ∀ {s A} → MachineInstruction s A → Instr₃ s A Controller : ∀ {s A} → ControllerInstruction s A → Instr₃ s A
Finite Domain Constraint Programming Layer
This is the sixth layer of the AVM ISA, which introduces finite domain (FD) instructions that enable constraint-based programming where computation proceeds through constraint propagation and search over symbolic variables with call-time choice semantics.
Variables are created with finite domains, domains are narrowed through constraint propagation, and search proceeds by labeling variables with concrete values. When labeling leads to constraint failure (domain emptying), transaction rollback (abortTx) provides the backtracking mechanism to explore alternative search paths.
Supporting Types for Constraint Programming
- Variable identifiers for constraint variables
record VarId : Set where constructor mkVarId field varId : ℕ
- Finite domain: a set of possible values
Domain : Set Domain = List Val
- Relational constraints between variables and values
data Constraint : Set where -- Equality: var₁ = var₂ Eq : VarId → VarId → Constraint -- Inequality: var₁ ≠ var₂ Neq : VarId → VarId → Constraint -- Ordering constraints between variables -- Less than or equal: var₁ ≤ var₂ Leq : VarId → VarId → Constraint -- Less than: var₁ < var₂ Lt : VarId → VarId → Constraint -- Greater than or equal: var₁ ≥ var₂ Geq : VarId → VarId → Constraint -- Greater than: var₁ > var₂ Gt : VarId → VarId → Constraint -- All-different: all variables must take distinct values AllDiff : List VarId → Constraint -- Value constraints: compare a variable to a concrete value -- var = value ValEq : VarId → Val → Constraint -- var ≤ value ValLeq : VarId → Val → Constraint -- var < value ValLt : VarId → Val → Constraint -- var ≥ value ValGeq : VarId → Val → Constraint -- var > value ValGt : VarId → Val → Constraint
FDInstruction datatype
The FD instruction family provides instructions for creating, narrowing, and posting constraints on constraint variables.
data FDInstruction : Safety → ISA where -- Create a fresh symbolic variable with an initial finite domain newVar : Domain → FDInstruction Safe VarId -- Narrow the domain of an existing variable (intersection); false if emptied -- TODO: investigate if this is really needed. narrow : VarId → Domain → FDInstruction Safe Bool -- Post a relational constraint (e.g., equality/inequality/distinctness) -- Triggers constraint propagation to narrow related variable domains post : Constraint → FDInstruction Safe Bool -- Labeling: select value from variable's domain (search step with call-time choice) -- Transaction abort (abortTx) provides backtracking when constraints fail label : VarId → FDInstruction Safe Val
Experimental Instruction Families
The following instruction families support intent-based programming and multi-party coordination. These are experimental features for prototyping advanced AVM capabilities.
Nondeterminism Instructions
Nondeterminism instructions enable preference-directed selection and constraint validation at transaction commit time. These instructions are suited for multi-party intent matching where constraints accumulate during execution and are evaluated atomically when the transaction commits.
Nondeterministic constraints (NondetConstraint) differ from finite domain constraints (Constraint) in their evaluation semantics: nondeterministic constraints represent assertions validated atomically at commit time, whereas finite domain constraints are symbolic relations between variables that trigger incremental propagation.
data NondetConstraint : Set where -- Assert that a boolean condition must hold at transaction commit Assert : Bool → NondetConstraint data NondetInstruction : Safety → ISA where -- Choose a value nondeterministically from available options -- Runtime may use preferences, weights, or solver guidance choose : List Val → NondetInstruction Safe Val -- Assert constraint that must hold at transaction commit -- All accumulated constraints are validated atomically when commitTx executes require : NondetConstraint → NondetInstruction Safe ⊤
Choosing Between FD and NonDet Layers
The FD and NonDet layers serve complementary purposes with incompatible execution models.
Finite Domain (Call-Time Choice)
-
Execution Model:
-
Suitable for:
- Single-agent CSP solving (TODO: add examples of N-Queens, Sudoku, scheduling)
- Search algorithms requiring systematic exploration
- Problems benefiting from incremental constraint propagation
- Resource allocation with backtracking
Nondeterminism (Commit-Time Validation)
-
Execution Model:
-
Suitable for:
- Intent matching and multi-party coordination
- Preference-directed selection with solver guidance
The Instruction datatype
The Instruction datatype combines all instructions so far defined, including experimental ones, and provides ergonomic pattern synonyms for a flat instruction namespace.
-- Union datatype combining all instruction families data Instruction : Safety → ISA where Obj : ∀ {s A} → ObjInstruction s A → Instruction s A Introspect : ∀ {s A} → IntrospectInstruction s A → Instruction s A Reflect : ∀ {s A} → ReflectInstruction s A → Instruction s A Reify : ∀ {s A} → ReifyInstruction s A → Instruction s A Tx : ∀ {s A} → TxInstruction s A → Instruction s A Pure : ∀ {s A} → PureInstruction s A → Instruction s A Machine : ∀ {s A} → MachineInstruction s A → Instruction s A Controller : ∀ {s A} → ControllerInstruction s A → Instruction s A FD : ∀ {s A} → FDInstruction s A → Instruction s A Nondet : ∀ {s A} → NondetInstruction s A → Instruction s A
Pattern Synonyms for convenience
Pattern synonyms provide a flat namespace for common instructions, eliminating the need for nested constructors when writing AVM programs. These patterns can also be used for pattern matching on instructions. It is a matter of using Agda here to describe the instruction set and pattern matching on it.
Also, it can be seen as the list of all instructions in the instruction set.
-- Object instruction patterns pattern obj-create behaviorName mcid = Obj (createObj behaviorName mcid) pattern obj-destroy oid = Obj (destroyObj oid) pattern obj-call oid inp = Obj (call oid inp) pattern obj-receive = Obj receive -- Introspection instruction patterns (self-examination) pattern get-self = Introspect self pattern get-input = Introspect input pattern get-current-machine = Introspect getCurrentMachine pattern get-state = Introspect getState pattern set-state newState = Introspect (setState newState) pattern get-sender = Introspect sender -- Reflection instruction patterns (examining others - unsafe) pattern obj-reflect oid = Reflect (reflect oid) pattern obj-scry-meta pred = Reflect (scryMeta pred) pattern obj-scry-deep pred = Reflect (scryDeep pred) -- Reification instruction patterns (capturing state as data) pattern do-reify-context = Reify reifyContext pattern do-reify-tx-state = Reify reifyTxState pattern do-reify-constraints = Reify reifyConstraints -- Transaction instruction patterns pattern tx-begin mcid = Tx (beginTx mcid) pattern tx-commit tid = Tx (commitTx tid) pattern tx-abort tid = Tx (abortTx tid) -- Pure function instruction patterns pattern call-pure name args = Pure (callPure name args) pattern register-pure name fn = Pure (registerPure name fn) pattern pure-update-pure name fn = Pure (updatePure name fn) -- Machine instruction patterns (physical location and process migration) pattern get-machine oid = Machine (getMachine oid) pattern do-teleport mid = Machine (teleport mid) pattern move-object oid mid = Machine (moveObject oid mid) pattern fetch-object oid = Machine (fetch oid) -- Controller instruction patterns (logical authority and ownership) pattern get-current-controller = Controller getCurrentController pattern get-controller oid = Controller (getController oid) pattern transfer-object oid cid = Controller (transferObject oid cid) pattern freeze-object oid = Controller (freeze oid)
The Instruction type provides the full AVM instruction set in a single
datatype:
AVMProgram : Set → Set AVMProgram = ITree (Instruction Safe)
Object Behaviour Instantiation Note
In the AVM operational model, the ObjectBehaviour module parameter is
concretely instantiated as AVMProgram (List Val) in implementations. This
establishes that runtime objects are pairs of (ObjectBehaviour × ObjectMeta) -
executable AVM programs paired with runtime metadata.
This design combines compositionality (instruction families as separate types)
with ergonomics (pattern synonyms for flat naming). Programs can use either the
layered approach (Instr₀, Instr₁, etc.) for compositional reasoning or the
unified Instruction type for convenience.
Instruction Set Operational Semantics
The AVM specification provides multiple instruction sets, systematically organized by operational capability and safety classification. This section establishes comprehensive operational semantics for all instruction types within the ISA hierarchy. Each instruction specification includes its associated safety level classification and return type signature.
The instruction set organization by instruction family follows this taxonomy:
- ObjInstruction: Object instructions: Object lifecycle and communication
- IntrospectInstruction: Introspection instructions: Self-examination of current execution context
- ReflectInstruction: Reflection instructions: Examining other objects' metadata and internals (unsafe)
- ReifyInstruction: Reification instructions: Capturing execution state as first-class data
- TxInstruction: Transaction instructions: Atomic execution contexts
- PureInstruction: Pure function instructions: Deterministic computation via function registry
- MachineInstruction: Machine instructions: Physical location and process migration
- ControllerInstruction: Controller instructions: Logical authority and ownership transfer
Object Lifecycle Operations
Object lifecycle instructions provide primitive operations for managing object creation and destruction within the persistent object store.
createObj
createObj : String → Maybe ControllerId → ObjInstruction Safe ObjectId
Creates a new runtime object within the persistent store by referencing a behavior name. The first eqString parameter specifies the behavior name that will be resolved by the interpreter to an ObjectBehaviour (an AVM program). The second Maybe ControllerId parameter optionally specifies the controller that should own the object:
- just controllerId: The object is created with the specified controller as
both
creatingControllerandcurrentControllerfields in ObjectMeta - nothing: If within a transaction, the object is created with the transaction's controller. If outside a transaction, the object is created without a controller (both controller fields are nothing)
The instruction returns a fresh ObjectId that uniquely identifies the newly created runtime object within the global object namespace. Object creation exhibits transactional semantics: if the enclosing transaction context aborts, the object creation is rolled back and the runtime object does not persist to the store.
destroyObj
destroyObj : ObjectId → ObjInstruction Safe Bool
Marks the runtime object identified by the given ObjectId for destruction. Returns true if destruction succeeds, false if the runtime object does not exist. The runtime object (both behavior and metadata) is removed from the store, and subsequent references to this ObjectId will fail. Destruction is transactional: the object remains accessible within the current transaction until committed.
Object Interaction
Object interaction is achieved through pure message-passing, preserving object encapsulation. Message passing is the only way to interact with objects in the AVM.
call
call : ObjectId → Input → ObjInstruction Safe (Maybe Output)
Performs synchronous message passing to the object identified by the given ObjectId. Sends the input and blocks until the target object produces an output. Returns nothing if the object does not exist or rejects the input, otherwise returns just the output produced by the target object.
receive
receive : ObjInstruction Safe (Maybe Input)
Receives the next available message for the current object. This instruction enables asynchronous message reception, allowing objects to retrieve incoming messages from other objects or the runtime system.
The blocking behavior is platform-specific: runtime implementations may choose to make this instruction blocking (waiting until a message arrives) or non-blocking (returning immediately). The return type Maybe Input accommodates both: - Blocking implementations: always return just a message (blocking until one arrives) - Non-blocking implementations: return just a message if available, or nothing if the message queue is empty
Consult your runtime's documentation for its specific message reception semantics.
This differs from input (see introspection below), which only exposes the message that triggered the current activation. receive dequeues the next message (and may block waiting), while input is a pure read of the current call context that neither waits nor consumes the queue.
Introspection (Self-Examination)
Introspection instructions query the current object's own execution context. These are safe operations because they only access information the executing object legitimately owns.
self
self : IntrospectInstruction Safe ObjectId
Returns the ObjectId of the currently executing object. This instruction is essential for recursion and self-reference, allowing an object to pass its own identifier to other objects or invoke itself.
input
input : IntrospectInstruction Safe Input
Returns the input being processed by the current object. This instruction provides access to the message sent to the current object.
getCurrentMachine
getCurrentMachine : IntrospectInstruction Safe MachineId
Returns the identifier of the physical machine currently executing this program. This instruction enables programs to reason about their execution location, which is independent of controller identity. Machine information is useful for data locality optimizations and understanding cross-machine communication costs.
getState
getState : IntrospectInstruction Safe (List Val)
Returns the current internal state of the executing object. The state is a list
of values that the object maintains across invocations. Initially, all objects
have an empty state []. Objects update their state using the setState
instruction. This enables objects to maintain explicit state rather than
deriving state from input history.
setState
setState : List Val → IntrospectInstruction Safe ⊤
Updates the internal state of the currently executing object. The provided list of values replaces the current state entirely. State changes are persisted when the enclosing transaction commits (if within a transaction) or immediately (if outside a transaction). This instruction allows objects to maintain and evolve their internal state explicitly.
sender
sender : IntrospectInstruction Safe (Maybe ObjectId)
Returns the ObjectId of the calling object when invoked from within a call instruction. Returns nothing for top-level execution contexts or when no caller exists. This instruction enables objects to verify the origin of received messages and implement access control policies based on caller identity.
Reflection (Examining Others)
Reflection instructions examine other objects' metadata and internal state, breaking object encapsulation. All reflection operations are unsafe because they violate the principle that objects exclusively control what information they expose.
reflect (Unsafe)
reflect : ObjectId → ReflectInstruction Unsafe (Maybe ObjectMeta)
Retrieves metadata about the object identified by the given ObjectId. Returns nothing if the object does not exist, otherwise returns just the object's metadata. Marked as unsafe because it bypasses object encapsulation.
scryMeta (Unsafe)
scryMeta : (ObjectMeta → Bool) → ReflectInstruction Unsafe (List (ObjectId × ObjectMeta))
Queries the store for objects whose metadata satisfies the given predicate. Returns pairs of object identifiers and metadata for all matching objects. This instruction traverses the entire store, applying the predicate to each object's metadata. Typical queries include finding all objects created by a specific controller, objects on a particular machine, or objects with a specific current controller. Marked unsafe because enumeration scales with total object count.
scryDeep (Unsafe)
scryDeep : (ObjectBehaviour → ObjectMeta → Bool) → ReflectInstruction Unsafe (List RuntimeObjectWithId)
Queries the store for runtime objects (object behaviours paired with metadata) that satisfy the given predicate. Returns complete runtime object data for all matches. This instruction breaks encapsulation by exposing raw ObjectBehaviour values. Use cases include deep inspection for debugging, auditing, or migration. Marked unsafe for both encapsulation violation and unbounded computation.
Reification (Capturing State as Data)
Reification instructions encode execution state as first-class data values that can be stored, transmitted, or analyzed. While introspection queries context and reflection examines others, reification captures runtime structures as values.
reifyContext
reifyContext : ReifyInstruction Safe ReifiedContext
Captures the current execution frame as a first-class value containing the current object ID, input, sender, machine, and controller. This is safe because it only packages information already available through individual introspection instructions.
reifyTxState (Unsafe)
reifyTxState : ReifyInstruction Unsafe (Maybe ReifiedTxState)
Captures the current transaction's pending state as a first-class value, including the transaction ID, uncommitted writes, pending creates and destroys, and observed objects. Returns nothing if no transaction is active. Marked unsafe because it exposes tentative state that may be rolled back, potentially leaking information about uncommitted operations.
reifyConstraints (Unsafe)
reifyConstraints : ReifyInstruction Unsafe ReifiedConstraints
Captures the constraint solver's internal state as a first-class value, including variable domains and constraint counts. Marked unsafe because it exposes solver internals that programs should not depend upon for correctness.
Transaction Control
Transaction control instructions manage atomic execution contexts. All state modifications within a transaction are tentative until committed.
beginTx
beginTx : Maybe ControllerId → TxInstruction Safe TxId
Initiates a new transactional context with an optional controller parameter and returns a fresh transaction identifier. The controller determines the execution context for the transaction:
- just controllerId: Immediately locks the transaction to the specified controller. All objects accessed must belong to this controller.
- nothing: Defers controller selection. The transaction controller is resolved from the first object accessed (via operations like call, destroyObj, transferObject, etc.).
All subsequent state modifications are logged to the transaction's write-set until the transaction is either committed or aborted. Transactions provide atomicity: either all changes succeed or none do. The single-controller invariant ensures all objects in a transaction belong to the same controller.
commitTx
commitTx : TxId → TxInstruction Safe Bool
Attempts to commit the transaction identified by the given TxId. Returns true if the commit succeeds, persisting all logged changes to the store. Returns false if the transaction cannot be committed due to conflicts with concurrent transactions or if the transaction was already finalized.
abortTx
abortTx : TxId → TxInstruction Safe ⊤
Aborts the transaction identified by the given TxId, discarding all tentative state changes in its write-set. The store reverts to its state before beginTx was called. This operation always succeeds and returns unit.
Pure Function Instructions
Pure function instructions provide deterministic computation capabilities through an extensible function registry.
callPure
callPure : String → List Val → PureInstruction Safe (Maybe Val)
Invokes a registered pure function by identifier with the given arguments.
Returns the function result or nothing if the function doesn't exist or the
arguments don't match the expected arity.
registerPure (Unsafe)
registerPure : String → (List Val → Maybe Val) → PureInstruction Unsafe Bool
Registers a new pure function in the function registry. Marked as unsafe because it extends the global function set, potentially affecting system-wide computation.
updatePure
updatePure : String → (List Val → Maybe Val) → PureInstruction Safe Bool
Updates the function definition of a registered pure function identified by the given string name. This instruction replaces the existing function definition in the pure function registry with the new function provided. The first parameter is the function identifier (name), and the second parameter is the new function definition. Returns true if the update succeeds (the function exists and was updated), false if the function does not exist in the registry or the update fails. This instruction enables dynamic modification of pure function implementations while maintaining deterministic computation semantics.
Pure function instructions modify the execution environment (the
pureFunctions field of State), not the object store. These changes take
effect immediately and affect all subsequent execution system-wide.
Machine Instructions
Machine instructions manage physical resource location and process migration in distributed AVM deployments. These operations deal with where computation executes and where object data physically resides.
getMachine
getMachine : ObjectId → MachineInstruction Safe (Maybe MachineId)
Returns the physical machine where the specified object's data resides, or nothing if the object doesn't exist. The machine location is independent of controller ownership. This information is useful for data locality optimization and understanding cross-machine communication costs.
teleport
teleport : MachineId → MachineInstruction Safe Bool
Moves the execution context (process) to the specified physical machine. Returns true if teleportation succeeds, false if the target machine is unreachable. This changes where computation happens, but does not change the controller identity or object ownership.
Safety constraint: This instruction is invalid during active transactions. The interpreter must reject teleportation attempts within a transaction boundary to maintain transaction integrity. This is to preserve the transactional atomicity guarantees.
moveObject
moveObject : ObjectId → MachineId → MachineInstruction Safe Bool
Moves an object's data to a different physical machine. Returns true if the move succeeds, false if the target machine is unreachable. This changes the object's physical storage location but does not change its controller ownership. Machine migration enables room for data locality optimisation and load balancing.
fetch
fetch : ObjectId → MachineInstruction Safe Bool
Brings a replica of the specified object to the local machine for local access. The object retains its original identity (same ObjectId) and remains opaque—interaction still occurs through the call instruction. Returns true if the replica is successfully created or updated locally, false if the object does not exist.
Multiple AVM programs on different machines can fetch the same object, creating independent replicas. These replicas may diverge (eventual consistency) until reconciled via freeze. The fetch operation does not change the object's controller ownership or its authoritative location—it creates a local working copy for efficient access.
Controller Instructions
Controller instructions manage logical authority and ownership for distributed AVM deployments. Controllers order transactions and own objects. These operations deal with which controller has authority over objects and transaction ordering. These operations are independent of the physical machine executing the code.
getCurrentController
getCurrentController : ControllerInstruction Safe (Maybe ControllerId)
Returns the transaction controller identifier if executing within a transaction, or nothing if executing outside transaction scope.
getController
getController : ObjectId → ControllerInstruction Safe (Maybe ControllerId)
Returns the controller responsible for the specified object, or nothing if the object doesn't exist. This queries the object's logical ownership, not its physical location. The controller determines transaction ordering for the object.
transferObject
transferObject : ObjectId → ControllerId → ControllerInstruction Safe Bool
Transfers logical ownership of an object to another controller. This changes which controller orders transactions for the object but does not move the object's data between machines. Returns true if the transfer succeeds, false if the transfer is unauthorized or the target controller is unreachable.
Safety constraint: The current controller must have authority to transfer the object.
freeze
freeze : ObjectId → ControllerInstruction Safe (Maybe Bool)
Synchronizes all replicas of an object through the controller for strong consistency. When multiple machines have fetched the same object (creating local replicas), their states may diverge. The freeze operation reconciles these divergent replicas by pushing all pending changes to the controller and ensuring all replicas see a consistent view.
Returns: - nothing if the object has no controller assigned (cannot freeze) - just true if the freeze operation succeeds and replicas are synchronized - just false if the object does not exist or the controller is unreachable
After freeze completes, all replicas are synchronized. Subsequent fetch operations on other machines will naturally create new replicas that may again diverge, maintaining the eventually consistent model until the next freeze.
Finite Domain Constraint Programming Instructions
Finite domain (FD) instructions enable constraint-based programming where computation proceeds through constraint propagation and search over symbolic variables. These instructions support declarative problem-solving where solutions emerge from posting constraints and labeling variables.
newVar
newVar : Domain → FDInstruction Safe VarId
Creates a fresh constraint variable with the specified finite domain. The Domain is a list of possible values the variable can take. Returns a unique variable identifier for use in subsequent constraint operations. Variables created within a transaction are local to that transaction's constraint store.
narrow
narrow : VarId → Domain → FDInstruction Safe Bool
Narrows the domain of an existing constraint variable by intersecting it with the provided domain. Returns true if the narrowing succeeds (the intersection is non-empty), false if the intersection would empty the domain (constraint failure). Domain narrowing is a fundamental operation in constraint propagation.
post
post : Constraint → FDInstruction Safe Bool
Posts a relational constraint to the constraint store. Constraints relate variables through:
- Equality/Inequality: Eq (=), Neq (≠)
- Ordering: Leq (≤), Lt (<), Geq (≥), Gt (>)
- Global constraints: AllDiff (all-different)
- Value constraints: ValEq (=), ValLeq (≤), ValLt (<), ValGeq (≥), ValGt (>)
Returns true if the constraint is consistent with the current constraint store, false if posting the constraint would lead to immediate failure. Constraint posting triggers propagation to narrow the variable domains.
label
label : VarId → FDInstruction Safe Val
Selects a value from the variable's current domain using call-time choice—the value is chosen immediately when label executes. This is the search step in constraint solving. If subsequent constraint propagation fails, transaction rollback (abortTx) backtracks to explore alternative values. Returns the selected value, or fails immediately if the domain is empty.
References to other modules
This page references the following modules:
- AVM.Context
- Symbols: ObjError, IntrospectError, ReflectError, ReifyError, TxError, MachineError, ControllerError, PureError, FDError, NondetError, BaseError, TxLayerError, PureLayerError, AVMError, EventType, Result, ObjectMeta, Store, FunctionEntry, State, LogEntry, Success, mkMeta, mkStore, mkFunctionEntry, ErrObjectNotFound, ErrObjectAlreadyDestroyed, ErrObjectAlreadyExists, ErrInvalidInput, ErrObjectRejectedCall, ErrMetadataCorruption, ErrContextUnavailable, ErrMetadataNotFound, ErrMetadataInconsistent, ErrStoreCorruption, ErrScryPredicateFailed, ErrReflectionDenied, ErrReifyContextFailed, ErrNoTransactionToReify, ErrTxStateAccessDenied, ErrConstraintStoreUnavailable, ErrTxConflict, ErrTxNotFound, ErrTxAlreadyCommitted, ErrTxAlreadyAborted, ErrNoActiveTx, ErrInvalidDuringTx, ErrMachineUnreachable, ErrInvalidMachineTransfer, ErrTeleportDuringTx, ErrControllerUnreachable, ErrUnauthorizedTransfer, ErrCrossControllerTx, ErrObjectNotAvailable, ErrObjectNotConsistent, ErrFreezeFailed, ErrObjectHasNoController, ErrFunctionNotFound, ErrFunctionAlreadyRegistered, ErrVersionConflict, ErrNotImplemented, obj-error, introspect-error, reflect-error, reify-error, base-error, tx-error, tx-layer-error, pure-error, pure-layer-error, machine-error, controller-error, fd-error, nondet-error, err-object-not-found, err-object-destroyed, err-object-exists, err-invalid-input, err-object-rejected, err-metadata-corruption, err-context-unavailable, err-metadata-not-found, err-metadata-inconsistent, err-store-corruption, err-scry-predicate-failed, err-reflection-denied, err-reify-context-failed, err-no-transaction-to-reify, err-tx-state-access-denied, err-constraint-store-unavailable, err-tx-conflict, err-tx-not-found, err-tx-committed, err-tx-aborted, err-no-active-tx, err-invalid-during-tx, err-function-not-found, err-function-registered, err-version-conflict, err-machine-unreachable, err-invalid-machine-transfer, err-teleport-during-tx, err-controller-unreachable, err-unauthorized-transfer, err-cross-controller-tx, err-object-not-available, err-object-not-consistent, err-freeze-failed, err-object-has-no-controller, err-fd-not-implemented, err-nondet-not-implemented, ObjectCreated, ObjectDestroyed, ObjectCalled, MessageReceived, ObjectMoved, ExecutionMoved, ObjectFetched, ObjectTransferred, ObjectFrozen, FunctionUpdated, TransactionStarted, TransactionCommitted, TransactionAborted, ErrorOccurred, mkLogEntry, mkSuccess, success, failure, ObjectStore, MetaStore, StateStore, RuntimeObject, RuntimeObjectWithId, TxWrite, Hash, PureFunctions, Trace, BaseResult, TxResult, PureResult, AVMResult
- Background.BasicTypes
- Symbols: ×, +, ⊥, Bool, ≡, Dec, Maybe, ℕ, List, ∈, Σ, ⊤, ↔, RawMonad, ,, ,Σ, inl, inr, tt, true, false, refl, yes, no, nothing, just, zero, suc, [], ∷, here, there, mk↔, fst, snd, ∃, ∃-syntax, ⊥-elim, ¬, not, sym, trans, cong, just≢nothing, just-injective, map-maybe, caseMaybe, length, ++-assoc, ++-right-id, map, foldr, null, head, filter, elem, concat, hasDuplicates, concatMap, all, any, find, lookup, filterMap, FinSet, Pred, case_of_, ∧, ∨, ||, if_then_else_, ≢, begin_, ≡⟨⟩, ≡⟨⟩_, _∎, >>=ᴹ, +ℕ, *ℕ, ∸, ≥, ≤, ≤?, <?, ≟ℕ, ==ℕ, ++, ∈Pred, ⊆, ∘, lsuc
- Background.InteractionTrees
- examples.Common.Equality
- Symbols: eqString, eqNat, eqBool, isReachableController, isReachableMachine
- examples.PingPong.Main
- Symbols: Message, Input, Output, ObjectBehaviour, Val, VInt, VString, VList, NodeId, ObjectId, MachineId, ControllerId, TxId, MessageType, PingPongMsg, Ping, Pong, mkMsg, VPingPongMsg, createPing, createPong, startPingPong, pingPongExample
Symbol disambiguation log
The following references had multiple matches and were disambiguated:
String: choseexamples.Common.Equality.eqStringfrom ['examples.Common.Equality.eqString', 'examples.PingPong.Main.VString']
Module References
Referenced By
This module is referenced by:
- AVM.Interpreter
- Symbols: AVMProgram, Controller, ControllerInstruction, FD, ISA, Instruction, Instr₀, Instr₁, Instr₂, Introspect, IntrospectInstruction, Machine, MachineInstruction, Nondet, Obj, ObjInstruction, Pure, PureInstruction, Reflect, ReflectInstruction, Reify, ReifyInstruction, Safe, Safety, Tx, TxInstruction, abortTx, beginTx, call, callPure, commitTx, createObj, destroyObj, fetch, freeze, getController, getCurrentController, getCurrentMachine, getMachine, getState, input, mkReifiedConstraints, mkReifiedContext, mkReifiedTxState, moveObject, reflect, registerPure, reifyConstraints, reifyContext, reifyTxState, scryDeep, scryMeta, self, sender, setState, teleport, transferObject, updatePure
- Background.Objects
- Symbols: AVMProgram, getState, setState
- Background.StatelessObjects
- examples.Battleship.Game
- Symbols: AVMProgram, obj-call, obj-create, tx-abort, tx-begin, tx-commit
- examples.Battleship.PlayerBoard
- Symbols: AVMProgram, Introspect, getState, input, setState
- examples.Battleship.Runner
- Symbols: AVMProgram, obj-call, obj-create
- examples.Common.InterpreterSetup
- Symbols: AVMProgram
- examples.PingPong.Main
- Symbols: AVMProgram, obj-call, obj-create
- examples.PingPong.Runner
- Symbols: AVMProgram, Introspect, Obj, Tx, beginTx, call, commitTx, input, obj-call, obj-create, self
References
This module references:
- AVM.Context
- Imports: ObjectMeta, RuntimeObjectWithId
- Background.BasicTypes
- Background.InteractionTrees
- Imports: ITree
?>