stack_assembly/stack.rs
1use crate::{Effect, Value};
2
3/// # The operand stack
4///
5/// StackAssembly's evaluation model is based on an implicit stack which
6/// stores all operands.
7///
8/// Aside from this, the stack is an important communication channel between
9/// script and host. Please refer to [`Eval`]'s [`stack`] field for more
10/// information on that.
11///
12/// [`Eval`]: crate::Eval
13/// [`stack`]: struct.Eval.html#structfield.stack
14#[derive(Debug)]
15pub struct Stack {
16 /// # The values on the stack
17 pub values: Vec<Value>,
18}
19
20impl Stack {
21 /// # Push a value to top of the stack
22 pub fn push(&mut self, value: impl Into<Value>) {
23 self.values.push(value.into());
24 }
25
26 /// # Pop a value from the top of the stack
27 ///
28 /// Return [`StackUnderflow`], if no value is available on the stack, which
29 /// provides an automatic conversion to [`Effect`].
30 pub fn pop(&mut self) -> Result<Value, StackUnderflow> {
31 self.values.pop().ok_or(StackUnderflow)
32 }
33
34 /// # Access the stack as a slice of `i32` values
35 pub fn to_i32_slice(&self) -> &[i32] {
36 bytemuck::cast_slice(&self.values)
37 }
38
39 /// # Access the stack as a slice of `u32` values
40 pub fn to_u32_slice(&self) -> &[u32] {
41 bytemuck::cast_slice(&self.values)
42 }
43}
44
45/// # Tried to pop a value from an empty stack
46///
47/// See [`Stack::pop`].
48#[derive(Debug)]
49pub struct StackUnderflow;
50
51impl From<StackUnderflow> for Effect {
52 fn from(StackUnderflow: StackUnderflow) -> Self {
53 Effect::StackUnderflow
54 }
55}