sim_lib_control/
restart.rs1use sim_kernel::{
2 Cx, Error, Ref, Result, Symbol,
3 control::{ControlResume, default_control_result_shape, resume},
4};
5
6use crate::{ContinuationValue, ControlResultValue};
7
8#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct Restart {
15 name: Symbol,
16 continuation: ContinuationValue,
17}
18
19impl Restart {
20 pub fn new(name: Symbol, continuation: ContinuationValue) -> Self {
22 Self { name, continuation }
23 }
24
25 pub fn name(&self) -> &Symbol {
27 &self.name
28 }
29
30 pub fn continuation(&self) -> &ContinuationValue {
32 &self.continuation
33 }
34
35 pub fn invoke(&self, cx: &mut Cx, value: Ref) -> Result<ControlResultValue> {
38 let result = resume(
39 cx,
40 ControlResume::new(
41 self.continuation.continuation().clone(),
42 value,
43 default_control_result_shape(),
44 ),
45 )?;
46 Ok(ControlResultValue::new(result))
47 }
48}
49
50#[derive(Clone, Debug, Default, PartialEq, Eq)]
54pub struct RestartStack {
55 restarts: Vec<Restart>,
56}
57
58impl RestartStack {
59 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn push(&mut self, restart: Restart) {
66 self.restarts.push(restart);
67 }
68
69 pub fn pop(&mut self) -> Option<Restart> {
71 self.restarts.pop()
72 }
73
74 pub fn invoke(&self, cx: &mut Cx, name: &Symbol, value: Ref) -> Result<ControlResultValue> {
79 self.nearest_restart(name)?.invoke(cx, value)
80 }
81
82 pub fn nearest_restart(&self, name: &Symbol) -> Result<&Restart> {
85 self.restarts
86 .iter()
87 .rev()
88 .find(|restart| restart.name() == name)
89 .ok_or_else(|| Error::Eval(format!("no restart named {name}")))
90 }
91}
92
93pub fn invoke_restart(
96 cx: &mut Cx,
97 stack: &RestartStack,
98 name: &Symbol,
99 value: Ref,
100) -> Result<ControlResultValue> {
101 stack.invoke(cx, name, value)
102}