1use crate::resumable::RunState;
2use alloc::borrow::ToOwned;
3use alloc::vec::Vec;
4
5use const_interpreter_loop::run_const_span;
6use function_ref::FunctionRef;
7use value_stack::Stack;
8
9use crate::core::reader::types::{FuncType, ResultType};
10use crate::execution::assert_validated::UnwrapValidatedExt;
11use crate::execution::hooks::{EmptyHookSet, HookSet};
12use crate::execution::store::Store;
13use crate::execution::value::Value;
14use crate::interop::InteropValueList;
15use crate::{RuntimeError, ValidationInfo};
16
17pub(crate) mod assert_validated;
18pub mod const_interpreter_loop;
19pub mod error;
20pub mod function_ref;
21pub mod hooks;
22pub mod interop;
23mod interpreter_loop;
24pub(crate) mod linear_memory;
25pub(crate) mod little_endian;
26pub mod registry;
27pub mod resumable;
28pub mod store;
29pub mod value;
30pub mod value_stack;
31
32pub const DEFAULT_MODULE: &str = "__interpreter_default__";
34
35pub struct RuntimeInstance<'b, T = (), H = EmptyHookSet>
36where
37 H: HookSet + core::fmt::Debug,
38{
39 pub hook_set: H,
40 pub store: Store<'b, T>,
41}
42
43impl<T: Default> Default for RuntimeInstance<'_, T, EmptyHookSet> {
44 fn default() -> Self {
45 Self::new(T::default())
46 }
47}
48
49impl<'b, T> RuntimeInstance<'b, T, EmptyHookSet> {
50 pub fn new(user_data: T) -> Self {
51 Self::new_with_hooks(user_data, EmptyHookSet)
52 }
53
54 pub fn new_with_default_module(
55 user_data: T,
56 validation_info: &'_ ValidationInfo<'b>,
57 ) -> Result<Self, RuntimeError> {
58 let mut instance = Self::new_with_hooks(user_data, EmptyHookSet);
59 instance.add_module(DEFAULT_MODULE, validation_info)?;
60 Ok(instance)
61 }
62
63 pub fn new_named(
64 user_data: T,
65 module_name: &str,
66 validation_info: &'_ ValidationInfo<'b>,
67 ) -> Result<Self, RuntimeError> {
69 let mut instance = Self::new_with_hooks(user_data, EmptyHookSet);
70 instance.add_module(module_name, validation_info)?;
71 Ok(instance)
72 }
73}
74
75impl<'b, T, H> RuntimeInstance<'b, T, H>
76where
77 H: HookSet + core::fmt::Debug,
78{
79 pub fn add_module(
80 &mut self,
81 module_name: &str,
82 validation_info: &'_ ValidationInfo<'b>,
83 ) -> Result<(), RuntimeError> {
84 self.store.add_module(module_name, validation_info, None)
85 }
86
87 pub fn new_with_hooks(user_data: T, hook_set: H) -> Self {
88 RuntimeInstance {
89 hook_set,
90 store: Store::new(user_data),
91 }
92 }
93
94 pub fn get_function_by_name(
95 &self,
96 module_name: &str,
97 function_name: &str,
98 ) -> Result<FunctionRef, RuntimeError> {
99 FunctionRef::new_from_name(module_name, function_name, &self.store)
100 .map_err(|_| RuntimeError::FunctionNotFound)
101 }
102
103 pub fn get_function_by_index(
104 &self,
105 module_addr: usize,
106 function_idx: usize,
107 ) -> Result<FunctionRef, RuntimeError> {
108 let module_inst = self
109 .store
110 .modules
111 .get(module_addr)
112 .ok_or(RuntimeError::ModuleNotFound)?;
113 let func_addr = *module_inst
114 .func_addrs
115 .get(function_idx)
116 .ok_or(RuntimeError::FunctionNotFound)?;
117
118 Ok(FunctionRef { func_addr })
119 }
120
121 pub fn invoke_typed<Params: InteropValueList, Returns: InteropValueList>(
123 &mut self,
124 function_ref: &FunctionRef,
125 params: Params,
126 ) -> Result<Returns, RuntimeError> {
128 self.invoke(function_ref, params.into_values())
129 .map(|values| Returns::try_from_values(values.into_iter()).unwrap_validated())
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
140 .invoke(func_addr, params, None)
141 .map(|run_state| match run_state {
142 RunState::Finished(values) => values,
143 _ => unreachable!("non metered invoke call"),
144 })
145 }
146
147 pub fn invoke_resumable(
148 &mut self,
149 function_ref: &FunctionRef,
150 params: Vec<Value>,
151 fuel: u32,
152 ) -> Result<RunState, RuntimeError> {
153 let FunctionRef { func_addr } = *function_ref;
154 self.store.invoke(func_addr, params, Some(fuel))
155 }
156
157 pub fn add_host_function_typed<Params: InteropValueList, Returns: InteropValueList>(
161 &mut self,
162 module_name: &str,
163 name: &str,
164 host_func: fn(&mut T, Vec<Value>) -> Vec<Value>,
165 ) -> Result<FunctionRef, RuntimeError> {
166 let host_func_ty = FuncType {
167 params: ResultType {
168 valtypes: Vec::from(Params::TYS),
169 },
170 returns: ResultType {
171 valtypes: Vec::from(Returns::TYS),
172 },
173 };
174 self.add_host_function(module_name, name, host_func_ty, host_func)
175 }
176
177 pub fn add_host_function(
178 &mut self,
179 module_name: &str,
180 name: &str,
181 host_func_ty: FuncType,
182 host_func: fn(&mut T, Vec<Value>) -> Vec<Value>,
183 ) -> Result<FunctionRef, RuntimeError> {
184 let func_addr = self.store.alloc_host_func(host_func_ty, host_func);
185 self.store.registry.register(
186 module_name.to_owned().into(),
187 name.to_owned().into(),
188 store::ExternVal::Func(func_addr),
189 )?;
190 Ok(FunctionRef { func_addr })
191 }
192
193 pub fn user_data(&self) -> &T {
194 &self.store.user_data
195 }
196
197 pub fn user_data_mut(&mut self) -> &mut T {
198 &mut self.store.user_data
199 }
200}
201
202pub fn host_function_wrapper<Params: InteropValueList, Results: InteropValueList>(
219 params: Vec<Value>,
220 f: impl FnOnce(Params) -> Results,
221) -> Vec<Value> {
222 let params =
223 Params::try_from_values(params.into_iter()).expect("Params match the actual parameters");
224 let results = f(params);
225 results.into_values()
226}