onion_vm/lambda/
runnable.rs

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