Skip to main content

vihaco_module/
host.rs

1// SPDX-FileCopyrightText: 2026 The vihaco Authors
2// SPDX-License-Identifier: MIT
3
4use 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    /// Get the current program counter.
15    fn pc(&self) -> u32;
16
17    /// Get a mutable reference to the program counter.
18    fn pc_mut(&mut self) -> &mut u32;
19
20    /// Get the instruction at the given program counter without advancing it.
21    fn get_instruction(&self, pc: u32) -> Result<&Self::Instruction>;
22
23    /// Peek the current instruction without advancing the program counter.
24    fn peek_instruction(&self) -> Result<&Self::Instruction> {
25        let pc = self.pc();
26        self.get_instruction(pc)
27    }
28
29    /// Get the current instruction and advance the program counter by 1.
30    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}