Skip to main content

ergo_runtime/compute/
mod.rs

1use std::collections::HashMap;
2
3use crate::common::{PrimitiveKind, Value, ValueType};
4
5pub mod implementations;
6pub mod registry;
7
8#[derive(Debug, Clone, PartialEq)]
9pub enum Cadence {
10    Continuous,
11    Event,
12}
13
14#[derive(Debug, Clone, PartialEq)]
15pub enum Cardinality {
16    Single,
17    Multiple,
18}
19
20#[derive(Debug, Clone)]
21pub struct InputSpec {
22    pub name: String,
23    pub value_type: ValueType,
24    pub required: bool,
25    pub cardinality: Cardinality,
26}
27
28#[derive(Debug, Clone)]
29pub struct OutputSpec {
30    pub name: String,
31    pub value_type: ValueType,
32}
33
34#[derive(Debug, Clone)]
35pub struct ParameterSpec {
36    pub name: String,
37    pub value_type: ValueType,
38    pub default: Option<Value>,
39    pub required: bool,
40    pub bounds: Option<String>,
41}
42
43#[derive(Debug, Clone)]
44pub struct ExecutionSpec {
45    pub deterministic: bool,
46    pub cadence: Cadence,
47    pub may_error: bool,
48}
49
50#[derive(Debug, Clone)]
51pub struct ErrorSpec {
52    pub allowed: bool,
53    pub types: Vec<ErrorType>,
54    pub deterministic: bool,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
58#[non_exhaustive]
59pub enum ErrorType {
60    DivisionByZero,
61    NonFiniteResult,
62    InvalidParameter,
63}
64
65#[derive(Debug, Clone)]
66pub struct StateSpec {
67    pub allowed: bool,
68    pub resettable: bool,
69    pub description: Option<String>,
70}
71
72#[derive(Debug, Clone, Default)]
73pub struct PrimitiveState {
74    pub data: HashMap<String, Value>,
75}
76
77/// Errors that can occur during compute primitive execution.
78///
79/// These represent semantic failures in computation, not infrastructure failures.
80/// They map to `ErrKind::SemanticError` and are non-retryable.
81///
82/// See: B.2 in PHASE_INVARIANTS.md
83#[derive(Debug, Clone, PartialEq, Eq)]
84#[non_exhaustive]
85pub enum ComputeError {
86    /// B.2: Division by zero is undefined.
87    DivisionByZero,
88    /// B.2: Result overflowed to infinity or produced NaN.
89    NonFiniteResult,
90    /// Parameter value violated primitive constraints.
91    InvalidParameter { parameter: String, reason: String },
92}
93
94impl std::fmt::Display for ComputeError {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        match self {
97            ComputeError::DivisionByZero => write!(f, "division by zero"),
98            ComputeError::NonFiniteResult => write!(f, "non-finite result"),
99            ComputeError::InvalidParameter { parameter, reason } => {
100                write!(f, "invalid parameter '{}': {}", parameter, reason)
101            }
102        }
103    }
104}
105
106impl std::error::Error for ComputeError {}
107
108#[derive(Debug, Clone)]
109pub struct ComputePrimitiveManifest {
110    pub id: String,
111    pub version: String,
112    pub kind: PrimitiveKind,
113    pub inputs: Vec<InputSpec>,
114    pub outputs: Vec<OutputSpec>,
115    pub parameters: Vec<ParameterSpec>,
116    pub execution: ExecutionSpec,
117    pub errors: ErrorSpec,
118    pub state: StateSpec,
119    pub side_effects: bool,
120}
121
122/// A compute primitive that transforms inputs and parameters into outputs.
123///
124/// State must be declared and resettable per manifest validation
125/// (`CMP-9`, `state.allowed => state.resettable`); undeclared per-instance
126/// mutability would violate determinism and is detected at runtime by
127/// capture/replay. Structural enforcement on top (derive macros, marker
128/// traits, newtype wrappers) was considered and rejected; see
129/// `docs/ledger/decisions/rejected-structural-enforcement-of-statelessness.md`.
130pub trait ComputePrimitive {
131    fn manifest(&self) -> &ComputePrimitiveManifest;
132
133    fn compute(
134        &self,
135        inputs: &HashMap<String, Value>,
136        parameters: &HashMap<String, Value>,
137        state: Option<&mut PrimitiveState>,
138    ) -> Result<HashMap<String, Value>, ComputeError>;
139}
140
141pub use implementations::{
142    add, and, append, const_bool, const_number, divide, eq, gt, len, lt, mean, multiply, negate,
143    neq, not, or, safe_divide, select, subtract, sum, window, Add, And, Append, ConstBool,
144    ConstNumber, Divide, Eq, Gt, Len, Lt, Mean, Multiply, Negate, Neq, Not, Or, SafeDivide, Select,
145    Subtract, Sum, Window,
146};
147pub use registry::PrimitiveRegistry;
148
149#[cfg(test)]
150mod tests;