sim_lib_control/
condition.rs1use sim_kernel::{
2 Cx, Error, Ref, Result, Symbol,
3 control::{ControlCapture, capture, default_control_result_shape},
4};
5
6use crate::ContinuationValue;
7
8#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct Condition {
14 kind: Symbol,
15 payload: Ref,
16}
17
18impl Condition {
19 pub fn new(kind: Symbol, payload: Ref) -> Self {
21 Self { kind, payload }
22 }
23
24 pub fn kind(&self) -> &Symbol {
26 &self.kind
27 }
28
29 pub fn payload(&self) -> &Ref {
31 &self.payload
32 }
33}
34
35#[derive(Clone, Debug, PartialEq, Eq)]
40pub struct ConditionHandler {
41 kind: Symbol,
42 prompt: Ref,
43 continuation: Ref,
44 multishot: bool,
45}
46
47impl ConditionHandler {
48 pub fn new(kind: Symbol, prompt: Ref, continuation: Ref) -> Self {
51 Self {
52 kind,
53 prompt,
54 continuation,
55 multishot: false,
56 }
57 }
58
59 pub fn multishot(mut self) -> Self {
62 self.multishot = true;
63 self
64 }
65
66 pub fn kind(&self) -> &Symbol {
68 &self.kind
69 }
70
71 pub fn prompt(&self) -> &Ref {
73 &self.prompt
74 }
75
76 pub fn continuation(&self) -> &Ref {
78 &self.continuation
79 }
80}
81
82#[derive(Clone, Debug, Default, PartialEq, Eq)]
87pub struct ConditionStack {
88 handlers: Vec<ConditionHandler>,
89}
90
91impl ConditionStack {
92 pub fn new() -> Self {
94 Self::default()
95 }
96
97 pub fn push(&mut self, handler: ConditionHandler) {
99 self.handlers.push(handler);
100 }
101
102 pub fn pop(&mut self) -> Option<ConditionHandler> {
104 self.handlers.pop()
105 }
106
107 pub fn signal(&self, cx: &mut Cx, condition: Condition) -> Result<ContinuationValue> {
113 let handler = self.nearest_handler(condition.kind())?;
114 let mut request = ControlCapture::new(
115 handler.prompt().clone(),
116 handler.continuation().clone(),
117 condition.payload().clone(),
118 default_control_result_shape(),
119 );
120 if handler.multishot {
121 request = request.multishot();
122 }
123 let capture_result = capture(cx, request)?;
124 Ok(ContinuationValue::new(
125 handler.continuation().clone(),
126 capture_result,
127 handler.multishot,
128 ))
129 }
130
131 pub fn nearest_handler(&self, kind: &Symbol) -> Result<&ConditionHandler> {
134 self.handlers
135 .iter()
136 .rev()
137 .find(|handler| handler.kind() == kind)
138 .ok_or_else(|| Error::Eval(format!("no condition handler for {kind}")))
139 }
140}
141
142pub fn signal_condition(
145 cx: &mut Cx,
146 stack: &ConditionStack,
147 condition: Condition,
148) -> Result<ContinuationValue> {
149 stack.signal(cx, condition)
150}