onion_vm/lambda/scheduler/
scheduler.rs

1use std::sync::Arc;
2
3use arc_gc::gc::GC;
4
5use crate::{
6    lambda::runnable::{Runnable, RuntimeError, StepResult},
7    types::{
8        object::{OnionObject, OnionObjectCell},
9        pair::OnionPair,
10    },
11};
12
13pub struct Scheduler {
14    pub(crate) runnable_stack: Vec<Box<dyn Runnable>>,
15}
16
17impl Scheduler {
18    pub fn new(runnable_stack: Vec<Box<dyn Runnable>>) -> Self {
19        Scheduler { runnable_stack }
20    }
21}
22
23impl Runnable for Scheduler {
24    fn step(&mut self, gc: &mut GC<OnionObjectCell>) -> StepResult {
25        if let Some(runnable) = self.runnable_stack.last_mut() {
26            match runnable.step(gc) {
27                StepResult::Continue => StepResult::Continue,
28                v @ StepResult::SpawnRunnable(_) => return v,
29                StepResult::NewRunnable(new_runnable) => {
30                    self.runnable_stack.push(new_runnable);
31                    StepResult::Continue
32                }
33                StepResult::ReplaceRunnable(new_runnable) => {
34                    self.runnable_stack.last_mut().map(|r| *r = new_runnable);
35                    StepResult::Continue
36                }
37                StepResult::Return(ref result) => {
38                    self.runnable_stack.pop();
39                    if let Some(top_runnable) = self.runnable_stack.last_mut() {
40                        match top_runnable.receive(&StepResult::Return(result.clone()), gc) {
41                            Ok(_) => {}
42                            Err(RuntimeError::CustomValue(ref e)) => {
43                                return StepResult::Return(
44                                    OnionPair::new_static(
45                                        &OnionObject::Boolean(false).stabilize(),
46                                        &e,
47                                    )
48                                    .into(),
49                                );
50                            }
51                            Err(e) => {
52                                return StepResult::Return(
53                                    OnionPair::new_static(
54                                        &OnionObject::Boolean(false).stabilize(),
55                                        &OnionObject::String(Arc::from(e.to_string())).stabilize(),
56                                    )
57                                    .into(),
58                                );
59                            }
60                        };
61                        StepResult::Continue
62                    } else {
63                        //self.result = *result;
64                        StepResult::Return(
65                            OnionPair::new_static(
66                                &OnionObject::Boolean(true).stabilize(),
67                                result.as_ref(),
68                            )
69                            .into(),
70                        )
71                    }
72                }
73                StepResult::Error(ref error) => {
74                    if let RuntimeError::Pending = error {
75                        // 如果是 Pending 状态,继续等待
76                        return StepResult::Error(RuntimeError::Pending);
77                    }
78                    return StepResult::Return(
79                        OnionPair::new_static(
80                            &OnionObject::Boolean(false).stabilize(),
81                            &match error {
82                                RuntimeError::CustomValue(v) => v.as_ref().clone(),
83                                _ => OnionObject::Undefined(Some(error.to_string().into()))
84                                    .stabilize(),
85                            },
86                        )
87                        .into(),
88                    );
89                }
90            }
91        } else {
92            StepResult::Error(RuntimeError::DetailedError(
93                "No runnable in stack".into(),
94            ))
95        }
96    }
97    fn receive(
98        &mut self,
99        step_result: &StepResult,
100        gc: &mut GC<OnionObjectCell>,
101    ) -> Result<(), RuntimeError> {
102        if let Some(runnable) = self.runnable_stack.last_mut() {
103            runnable.receive(&step_result, gc)
104        } else {
105            Err(RuntimeError::DetailedError(
106                "No runnable in stack".into(),
107            ))
108        }
109    }
110
111    fn format_context(&self) -> String {
112        if self.runnable_stack.is_empty() {
113            return "Scheduler: No active runnables.".to_string();
114        }
115
116        // 我们将从栈顶(最近的调用)开始,一直到栈底
117        // 所以我们倒序遍历 `runnable_stack`
118        let contexts: Vec<String> = self
119            .runnable_stack
120            .iter()
121            .rev() // .rev() is crucial for correct stack trace order
122            .enumerate() // Use enumerate to add frame numbers
123            .map(|(index, runnable)| {
124                let header = format!("--- Frame #{} ---", index);
125                let inner_context = runnable.format_context();
126                format!("{}\n{}", header, inner_context)
127            })
128            .collect();
129
130        // 将所有帧的上下文用换行符连接起来
131        contexts.join("\n\n") // Use double newline to separate frames
132    }
133}