1use sim_lib_control::{AdmissionLimit, WorkLimit};
2
3use crate::ManagedRootSource;
4use crate::{CodeCursor, SlotFile, UnitStack, ValueWidthPolicy};
5
6pub struct Frame<P, K, R, H>
8where
9 P: ValueWidthPolicy,
10{
11 slots: SlotFile<P>,
12 operands: UnitStack<P>,
13 cursor: CodeCursor,
14 continuation: Option<K>,
15 roots: R,
16 handlers: H,
17}
18
19impl<P, K, R, H> Frame<P, K, R, H>
20where
21 P: ValueWidthPolicy,
22{
23 pub fn new(
25 slot_limit: AdmissionLimit,
26 operand_limit: WorkLimit,
27 cursor: CodeCursor,
28 continuation: Option<K>,
29 roots: R,
30 handlers: H,
31 ) -> Self {
32 Self {
33 slots: SlotFile::new(slot_limit),
34 operands: UnitStack::new(operand_limit),
35 cursor,
36 continuation,
37 roots,
38 handlers,
39 }
40 }
41
42 pub fn slots(&self) -> &SlotFile<P> {
44 &self.slots
45 }
46
47 pub fn slots_mut(&mut self) -> &mut SlotFile<P> {
49 &mut self.slots
50 }
51
52 pub fn operands(&self) -> &UnitStack<P> {
54 &self.operands
55 }
56
57 pub fn operands_mut(&mut self) -> &mut UnitStack<P> {
59 &mut self.operands
60 }
61
62 pub fn cursor(&self) -> CodeCursor {
64 self.cursor
65 }
66
67 pub fn set_cursor(&mut self, cursor: CodeCursor) {
69 self.cursor = cursor;
70 }
71
72 pub fn continuation(&self) -> Option<&K> {
74 self.continuation.as_ref()
75 }
76
77 pub fn roots(&self) -> &R {
79 &self.roots
80 }
81
82 pub fn roots_mut(&mut self) -> &mut R {
84 &mut self.roots
85 }
86
87 pub fn handlers(&self) -> &H {
89 &self.handlers
90 }
91
92 pub fn handlers_mut(&mut self) -> &mut H {
94 &mut self.handlers
95 }
96}
97
98impl<P, K, R, H> ManagedRootSource for Frame<P, K, R, H>
99where
100 P: ValueWidthPolicy,
101 P::Value: ManagedRootSource,
102 K: ManagedRootSource,
103 R: ManagedRootSource,
104 H: ManagedRootSource,
105{
106 fn visit_managed_roots(
107 &self,
108 visit: &mut dyn FnMut(sim_lib_mutation::ManagedId) -> bool,
109 ) -> bool {
110 let mut complete = true;
111 self.slots
112 .visit_values(|value| complete = complete && value.visit_managed_roots(visit));
113 if !complete {
114 return false;
115 }
116 self.operands
117 .visit_values(|value| complete = complete && value.visit_managed_roots(visit));
118 if !complete {
119 return false;
120 }
121 if let Some(continuation) = &self.continuation
122 && !continuation.visit_managed_roots(visit)
123 {
124 return false;
125 }
126 self.roots.visit_managed_roots(visit) && self.handlers.visit_managed_roots(visit)
127 }
128}
129
130#[derive(Clone, Copy, Debug, PartialEq, Eq)]
132pub enum FrameStackError {
133 DepthExhausted {
135 depth: usize,
137 limit: usize,
139 },
140}
141
142#[derive(Clone, Debug, PartialEq, Eq)]
144pub struct FrameStack<F> {
145 frames: Vec<F>,
146 limit: WorkLimit,
147}
148
149impl<F> FrameStack<F> {
150 pub fn new(limit: WorkLimit) -> Self {
152 Self {
153 frames: Vec::new(),
154 limit,
155 }
156 }
157
158 pub fn depth(&self) -> usize {
160 self.frames.len()
161 }
162
163 pub fn push(&mut self, frame: F) -> Result<(), FrameStackError> {
165 if self.frames.len() >= self.limit.0 {
166 return Err(FrameStackError::DepthExhausted {
167 depth: self.frames.len(),
168 limit: self.limit.0,
169 });
170 }
171 self.frames.push(frame);
172 Ok(())
173 }
174
175 pub fn pop(&mut self) -> Option<F> {
177 self.frames.pop()
178 }
179
180 pub fn current(&self) -> Option<&F> {
182 self.frames.last()
183 }
184
185 pub fn current_mut(&mut self) -> Option<&mut F> {
187 self.frames.last_mut()
188 }
189
190 pub fn visit_frames(&self, mut visit: impl FnMut(&F)) {
192 for frame in &self.frames {
193 visit(frame);
194 }
195 }
196}
197
198impl<F: ManagedRootSource> ManagedRootSource for FrameStack<F> {
199 fn visit_managed_roots(
200 &self,
201 visit: &mut dyn FnMut(sim_lib_mutation::ManagedId) -> bool,
202 ) -> bool {
203 for frame in &self.frames {
204 if !frame.visit_managed_roots(visit) {
205 return false;
206 }
207 }
208 true
209 }
210}
211
212#[derive(Clone, Copy, Debug, PartialEq, Eq)]
214pub enum TransferError {
215 WidthCountMismatch,
217 ZeroWidth,
219}
220
221fn validate_widths<V>(values: &[V], widths: &[usize]) -> Result<(), TransferError> {
222 if values.len() != widths.len() {
223 return Err(TransferError::WidthCountMismatch);
224 }
225 if widths.contains(&0) {
226 return Err(TransferError::ZeroWidth);
227 }
228 Ok(())
229}
230
231#[derive(Clone, Debug, PartialEq, Eq)]
233pub struct CallTransfer<V, C> {
234 pub values: Vec<V>,
236 pub widths: Vec<usize>,
238 pub target: C,
240}
241
242impl<V, C> CallTransfer<V, C> {
243 pub fn new(values: Vec<V>, widths: Vec<usize>, target: C) -> Result<Self, TransferError> {
245 validate_widths(&values, &widths)?;
246 Ok(Self {
247 values,
248 widths,
249 target,
250 })
251 }
252}
253
254#[derive(Clone, Debug, PartialEq, Eq)]
256pub struct ReturnTransfer<V> {
257 pub values: Vec<V>,
259 pub widths: Vec<usize>,
261}
262
263impl<V> ReturnTransfer<V> {
264 pub fn new(values: Vec<V>, widths: Vec<usize>) -> Result<Self, TransferError> {
266 validate_widths(&values, &widths)?;
267 Ok(Self { values, widths })
268 }
269}
270
271#[derive(Clone, Debug, PartialEq, Eq)]
273pub enum Transfer<V, C> {
274 Call(CallTransfer<V, C>),
276 Return(ReturnTransfer<V>),
278}