pub(super) const MAX_SIMULATED_POPS: usize = 1024;
#[derive(Default)]
pub(super) struct EntryStack {
required_entry_depth: usize,
stack: Vec<Option<usize>>,
}
impl EntryStack {
pub(super) fn required_entry_depth(&self) -> usize {
self.required_entry_depth
}
pub(super) fn stack(&self) -> &[Option<usize>] {
&self.stack
}
pub(super) fn ensure_available(&mut self, count: usize) {
let count = count.min(MAX_SIMULATED_POPS);
while self.stack.len() < count {
self.stack.insert(0, None);
self.required_entry_depth += 1;
}
}
pub(super) fn pop_count(&mut self, count: usize) {
self.ensure_available(count);
for _ in 0..count {
self.stack.pop();
}
}
pub(super) fn push(&mut self, value: Option<usize>) {
self.stack.push(value);
}
pub(super) fn push_all(&mut self, values: Vec<Option<usize>>) {
self.stack.extend(values);
}
pub(super) fn top_literal(&self) -> Option<usize> {
self.stack.last().copied().flatten()
}
pub(super) fn value_from_top(&self, depth: usize) -> Option<usize> {
depth
.checked_add(1)
.and_then(|needed| self.stack.len().checked_sub(needed))
.and_then(|pos| self.stack.get(pos).copied())
.flatten()
}
pub(super) fn remove_from_top(&mut self, depth: usize) -> Option<Option<usize>> {
depth
.checked_add(1)
.and_then(|needed| self.stack.len().checked_sub(needed))
.map(|pos| self.stack.remove(pos))
}
pub(super) fn reverse_top(&mut self, count: usize) {
let count = count.min(self.stack.len());
let start = self.stack.len() - count;
self.stack[start..].reverse();
}
pub(super) fn mark_top_unknown(&mut self) {
if let Some(top) = self.stack.last_mut() {
*top = None;
}
}
}
pub(super) struct StackEffect {
pub(super) pops: usize,
pub(super) pushes: Vec<Option<usize>>,
}