1use crate::Error;
2
3use alloc::borrow::ToOwned;
4use alloc::vec::Vec;
5
6use const_interpreter_loop::run_const_span;
7use function_ref::FunctionRef;
8use value_stack::Stack;
9
10use crate::core::reader::types::{FuncType, ResultType};
11use crate::execution::assert_validated::UnwrapValidatedExt;
12use crate::execution::hooks::{EmptyHookSet, HookSet};
13use crate::execution::store::Store;
14use crate::execution::value::Value;
15use crate::value::InteropValueList;
16use crate::{Result as CustomResult, RuntimeError, ValidationInfo};
17
18pub(crate) mod assert_validated;
19pub mod const_interpreter_loop;
20pub mod function_ref;
21pub mod hooks;
22mod interpreter_loop;
23pub(crate) mod linear_memory;
24pub(crate) mod locals;
25pub mod registry;
26pub mod store;
27pub mod value;
28pub mod value_stack;
29
30pub const DEFAULT_MODULE: &str = "__interpreter_default__";
32
33#[derive(Debug)]
34pub struct RuntimeInstance<'b, T = (), H = EmptyHookSet>
35where
36 H: HookSet + core::fmt::Debug,
37{
38 pub hook_set: H,
39 pub store: Store<'b, T>,
40}
41
42impl<T: Default> Default for RuntimeInstance<'_, T, EmptyHookSet> {
43 fn default() -> Self {
44 Self::new(T::default())
45 }
46}
47
48impl<'b, T> RuntimeInstance<'b, T, EmptyHookSet> {
49 pub fn new(user_data: T) -> Self {
50 Self::new_with_hooks(user_data, EmptyHookSet)
51 }
52
53 pub fn new_with_default_module(
54 user_data: T,
55 validation_info: &'_ ValidationInfo<'b>,
56 ) -> CustomResult<Self> {
57 let mut instance = Self::new_with_hooks(user_data, EmptyHookSet);
58 instance.add_module(DEFAULT_MODULE, validation_info)?;
59 Ok(instance)
60 }
61
62 pub fn new_named(
63 user_data: T,
64 module_name: &str,
65 validation_info: &'_ ValidationInfo<'b>,
66 ) -> CustomResult<Self> {
68 let mut instance = Self::new_with_hooks(user_data, EmptyHookSet);
69 instance.add_module(module_name, validation_info)?;
70 Ok(instance)
71 }
72}
73
74impl<'b, T, H> RuntimeInstance<'b, T, H>
75where
76 H: HookSet + core::fmt::Debug,
77{
78 pub fn add_module(
79 &mut self,
80 module_name: &str,
81 validation_info: &'_ ValidationInfo<'b>,
82 ) -> CustomResult<()> {
83 self.store.add_module(module_name, validation_info)
84 }
85
86 pub fn new_with_hooks(user_data: T, hook_set: H) -> Self {
87 RuntimeInstance {
88 hook_set,
89 store: Store::new(user_data),
90 }
91 }
92
93 pub fn get_function_by_name(
94 &self,
95 module_name: &str,
96 function_name: &str,
97 ) -> Result<FunctionRef, RuntimeError> {
98 FunctionRef::new_from_name(module_name, function_name, &self.store)
99 .map_err(|_| RuntimeError::FunctionNotFound)
100 }
101
102 pub fn get_function_by_index(
103 &self,
104 module_addr: usize,
105 function_idx: usize,
106 ) -> Result<FunctionRef, RuntimeError> {
107 let module_inst = self
108 .store
109 .modules
110 .get(module_addr)
111 .ok_or(RuntimeError::ModuleNotFound)?;
112 let func_addr = *module_inst
113 .func_addrs
114 .get(function_idx)
115 .ok_or(RuntimeError::FunctionNotFound)?;
116
117 Ok(FunctionRef { func_addr })
118 }
119
120 pub fn invoke_typed<Params: InteropValueList, Returns: InteropValueList>(
122 &mut self,
123 function_ref: &FunctionRef,
124 params: Params,
125 ) -> Result<Returns, RuntimeError> {
127 let FunctionRef { func_addr } = *function_ref;
128 self.store
129 .invoke(func_addr, params.into_values())
130 .map(|values| Returns::from_values(values.into_iter()))
131 }
132
133 pub fn invoke(
135 &mut self,
136 function_ref: &FunctionRef,
137 params: Vec<Value>,
138 ) -> Result<Vec<Value>, RuntimeError> {
139 let FunctionRef { func_addr } = *function_ref;
140 self.store.invoke(func_addr, params)
141 }
142
143 pub fn add_host_function_typed<Params: InteropValueList, Returns: InteropValueList>(
147 &mut self,
148 module_name: &str,
149 name: &str,
150 host_func: fn(&mut T, Vec<Value>) -> Vec<Value>,
151 ) -> Result<FunctionRef, Error> {
152 let host_func_ty = FuncType {
153 params: ResultType {
154 valtypes: Vec::from(Params::TYS),
155 },
156 returns: ResultType {
157 valtypes: Vec::from(Returns::TYS),
158 },
159 };
160 self.add_host_function(module_name, name, host_func_ty, host_func)
161 }
162
163 pub fn add_host_function(
164 &mut self,
165 module_name: &str,
166 name: &str,
167 host_func_ty: FuncType,
168 host_func: fn(&mut T, Vec<Value>) -> Vec<Value>,
169 ) -> Result<FunctionRef, Error> {
170 let func_addr = self.store.alloc_host_func(host_func_ty, host_func);
171 self.store.registry.register(
172 module_name.to_owned().into(),
173 name.to_owned().into(),
174 store::ExternVal::Func(func_addr),
175 )?;
176 Ok(FunctionRef { func_addr })
177 }
178
179 pub fn user_data(&self) -> &T {
180 &self.store.user_data
181 }
182
183 pub fn user_data_mut(&mut self) -> &mut T {
184 &mut self.store.user_data
185 }
186}
187
188pub fn host_function_wrapper<Params: InteropValueList, Results: InteropValueList>(
205 params: Vec<Value>,
206 f: impl FnOnce(Params) -> Results,
207) -> Vec<Value> {
208 let params = Params::from_values(params.into_iter());
209 let results = f(params);
210 results.into_values()
211}