onion_vm/lambda/
runnable.rs

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