onion_vm/lambda/
runnable.rs

1use std::fmt::Display;
2
3use arc_gc::gc::GC;
4use serde_json::Value;
5
6use crate::types::object::{OnionObjectCell, OnionStaticObject};
7
8#[derive(Clone, Debug)]
9pub enum RuntimeError {
10    StepError(Box<String>),
11    DetailedError(Box<String>),
12    InvalidType(Box<String>),
13    InvalidOperation(Box<String>),
14    CustomValue(Box<OnionStaticObject>),
15    BrokenReference,
16    BorrowError(Box<String>),
17}
18
19impl Display for RuntimeError {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        match self {
22            RuntimeError::StepError(msg) => write!(f, "Step Error: {}", msg),
23            RuntimeError::DetailedError(msg) => write!(f, "Detailed Error: {}", msg),
24            RuntimeError::InvalidType(msg) => write!(f, "Invalid type: {}", msg),
25            RuntimeError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
26            RuntimeError::BrokenReference => write!(f, "Broken reference encountered"),
27            RuntimeError::BorrowError(msg) => write!(f, "Borrow error: {}", msg),
28            RuntimeError::CustomValue(value) => write!(f, "Custom value error: {}", value),
29        }
30    }
31}
32
33pub enum StepResult {
34    Continue,
35    NewRunnable(Box<dyn Runnable>),
36    ReplaceRunnable(Box<dyn Runnable>),
37    Return(Box<OnionStaticObject>),
38    SetSelfObject(Box<OnionStaticObject>),
39    Error(RuntimeError),
40}
41
42impl StepResult {
43    pub fn unwrap_error(self) -> RuntimeError {
44        match self {
45            StepResult::Error(error) => error,
46            _ => RuntimeError::StepError(
47                "Expected an error, but got a different result"
48                    .to_string()
49                    .into(),
50            ),
51        }
52    }
53}
54
55#[macro_export]
56macro_rules! unwrap_step_result {
57    ($result:expr) => {
58        match $result {
59            Ok(value) => value,
60            Err(error) => return StepResult::Error(error),
61        }
62    };
63}
64
65#[allow(unused_variables)]
66pub trait Runnable: Send + Sync + 'static {
67    fn step(&mut self, gc: &mut GC<OnionObjectCell>) -> StepResult;
68    fn receive(
69        &mut self,
70        step_result: &StepResult,
71        gc: &mut GC<OnionObjectCell>,
72    ) -> Result<(), RuntimeError> {
73        Err(RuntimeError::DetailedError(
74            "receive not implemented".to_string().into(),
75        ))
76    }
77    fn copy_with_gc(&self, gc: &mut GC<OnionObjectCell>) -> Box<dyn Runnable> {
78        panic!("copy_with_gc is not implemented for this Runnable")
79    }
80    fn copy(&self) -> Box<dyn Runnable>;
81
82    fn format_context(&self) -> Result<Value, RuntimeError>;
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn check_step_result_size() {
91        println!("Size of StepResult: {}", std::mem::size_of::<StepResult>());
92    }
93}