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::new(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::SetSelfObject(ref self_object) => {
74                    if let Some(top_runnable) = self.runnable_stack.last_mut() {
75                        match top_runnable
76                            .receive(&StepResult::SetSelfObject(self_object.clone()), gc)
77                        {
78                            Ok(_) => {}
79                            Err(RuntimeError::CustomValue(ref e)) => {
80                                return StepResult::Return(
81                                    OnionPair::new_static(
82                                        &OnionObject::Boolean(false).stabilize(),
83                                        &e,
84                                    )
85                                    .into(),
86                                )
87                            }
88                            Err(e) => {
89                                return StepResult::Return(
90                                    OnionPair::new_static(
91                                        &OnionObject::Boolean(false).stabilize(),
92                                        &OnionObject::String(Arc::new(e.to_string())).stabilize(),
93                                    )
94                                    .into(),
95                                )
96                            }
97                        }
98                    }
99                    StepResult::Continue
100                }
101                StepResult::Error(ref error) => {
102                    if let RuntimeError::Pending = error {
103                        // 如果是 Pending 状态,继续等待
104                        return StepResult::Error(RuntimeError::Pending);
105                    }
106                    return StepResult::Return(
107                        OnionPair::new_static(
108                            &OnionObject::Boolean(false).stabilize(),
109                            &match error {
110                                RuntimeError::CustomValue(ref v) => v.as_ref().clone(),
111                                _ => OnionObject::Undefined(Some(error.to_string().into()))
112                                    .stabilize(),
113                            },
114                        )
115                        .into(),
116                    );
117                }
118            }
119        } else {
120            StepResult::Error(RuntimeError::DetailedError(
121                "No runnable in stack".to_string().into(),
122            ))
123        }
124    }
125    fn receive(
126        &mut self,
127        step_result: &StepResult,
128        gc: &mut GC<OnionObjectCell>,
129    ) -> Result<(), RuntimeError> {
130        if let Some(runnable) = self.runnable_stack.last_mut() {
131            runnable.receive(&step_result, gc)
132        } else {
133            Err(RuntimeError::DetailedError(
134                "No runnable in stack".to_string().into(),
135            ))
136        }
137    }
138
139    fn copy(&self) -> Box<dyn Runnable> {
140        Box::new(Scheduler {
141            runnable_stack: self.runnable_stack.iter().map(|r| r.copy()).collect(),
142        })
143    }
144
145    fn format_context(&self) -> Result<serde_json::Value, RuntimeError> {
146        let mut stack_json_array = serde_json::Value::Array(vec![]);
147        for runnable in &self.runnable_stack {
148            let frame_json = runnable.format_context()?;
149            stack_json_array.as_array_mut().unwrap().push(frame_json);
150        }
151        // {type: "Scheduler", frames: frame_json_array}
152        Ok(serde_json::json!({
153            "type": "Scheduler",
154            "frames": stack_json_array
155        }))
156    }
157}