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