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