1use eyre::Result;
5
6use vihaco_abi::frame::Frame;
7use vihaco_bytecode::ConstantId;
8
9use crate::module::FunctionInfo;
10
11pub trait ProgramCounter {
12 type Instruction;
13
14 fn pc(&self) -> u32;
16
17 fn pc_mut(&mut self) -> &mut u32;
19
20 fn get_instruction(&self, pc: u32) -> Result<&Self::Instruction>;
22
23 fn peek_instruction(&self) -> Result<&Self::Instruction> {
25 let pc = self.pc();
26 self.get_instruction(pc)
27 }
28
29 fn next_instruction(&mut self) -> Result<&Self::Instruction> {
31 let pc = self.pc();
32 if let Some(v) = self.pc_mut().checked_add(1) {
33 *self.pc_mut() = v;
34 }
35 self.get_instruction(pc)
36 }
37}
38
39pub trait StackMemory {
40 type Value;
41 fn stack(&self) -> &Vec<Self::Value>;
42 fn stack_mut(&mut self) -> &mut Vec<Self::Value>;
43 fn stack_push<T: Into<Self::Value>>(&mut self, v: T);
44 fn stack_pop(&mut self) -> Result<Self::Value>;
45 fn stack_get(&self, pos: usize) -> Result<&Self::Value>;
46 fn stack_get_mut(&mut self, pos: usize) -> Result<&mut Self::Value>;
47 fn stack_len(&self) -> usize;
48 fn stack_is_empty(&self) -> bool {
49 self.stack_len() == 0
50 }
51 fn stack_top(&self) -> Result<&Self::Value> {
52 if self.stack_is_empty() {
53 Err(eyre::eyre!("stack underflow"))
54 } else {
55 self.stack_get(self.stack_len() - 1)
56 }
57 }
58 fn stack_top_mut(&mut self) -> Result<&mut Self::Value> {
59 let len = self.stack_len();
60 if len == 0 {
61 Err(eyre::eyre!("stack underflow"))
62 } else {
63 self.stack_get_mut(len - 1)
64 }
65 }
66}
67
68pub trait StackFrame {
69 fn get_frame(&self) -> Result<&Frame>;
70 fn get_frame_mut(&mut self) -> Result<&mut Frame>;
71 fn push_frame(&mut self, frame: Frame);
72 fn pop_frame(&mut self) -> Result<Frame>;
73}
74
75pub trait FrameMemory: StackFrame + StackMemory {
76 fn frame_base(&self) -> Result<usize> {
77 self.get_frame().map(|f| f.base)
78 }
79
80 fn get_local(&self, index: usize) -> Result<&Self::Value> {
81 let base = self.frame_base()?;
82 self.stack_get(base + index)
83 }
84
85 fn get_local_mut(&mut self, index: usize) -> Result<&mut Self::Value> {
86 let base = self.frame_base()?;
87 self.stack_get_mut(base + index)
88 }
89}
90
91pub trait GetProgramInfo {
92 type Type;
93 type Value;
94
95 fn get_function(&self, index: usize) -> Result<FunctionInfo<Self::Type>>;
96 fn get_string(&self, index: usize) -> Result<&String>;
97 fn get_constant(&self, id: ConstantId) -> Result<&Self::Value>;
98}
99
100pub trait Stdout {
101 type Output: std::io::Read + std::io::Write;
102 fn stdout(&self) -> &Self::Output;
103 fn stdout_mut(&mut self) -> &mut Self::Output;
104}