1use crate::addrs::GlobalAddr;
2use crate::core::reader::types::global::GlobalType;
3use crate::resumable::{ResumableRef, RunState};
4use alloc::borrow::{Cow, ToOwned};
5use alloc::vec::Vec;
6
7use const_interpreter_loop::run_const_span;
8use function_ref::FunctionRef;
9use store::addrs::ModuleAddr;
10use store::ExternVal;
11use store::HaltExecutionError;
12use value_stack::Stack;
13
14use crate::core::reader::types::{FuncType, ResultType};
15use crate::execution::assert_validated::UnwrapValidatedExt;
16use crate::execution::config::Config;
17use crate::execution::store::Store;
18use crate::execution::value::Value;
19use crate::interop::InteropValueList;
20use crate::{RuntimeError, ValidationInfo};
21
22pub(crate) mod assert_validated;
23pub mod config;
24pub mod const_interpreter_loop;
25pub mod error;
26pub mod function_ref;
27pub mod interop;
28mod interpreter_loop;
29pub(crate) mod little_endian;
30pub mod registry;
31pub mod resumable;
32pub mod store;
33pub mod value;
34pub mod value_stack;
35
36pub const DEFAULT_MODULE: &str = "__interpreter_default__";
38
39pub struct RuntimeInstance<'b, T: Config = ()> {
40 pub store: Store<'b, T>,
41}
42
43impl<T: Config + Default> Default for RuntimeInstance<'_, T> {
44 fn default() -> Self {
45 Self::new(T::default())
46 }
47}
48
49impl<'b, T: Config> RuntimeInstance<'b, T> {
50 pub fn new(user_data: T) -> Self {
51 RuntimeInstance {
52 store: Store::new(user_data),
53 }
54 }
55
56 pub fn new_with_default_module(
58 user_data: T,
59 validation_info: &'_ ValidationInfo<'b>,
60 ) -> Result<(Self, ModuleAddr), RuntimeError> {
61 let mut instance = Self::new(user_data);
62 let module_addr = instance.add_module(DEFAULT_MODULE, validation_info)?;
63 Ok((instance, module_addr))
64 }
65
66 pub fn new_named(
68 user_data: T,
69 module_name: &str,
70 validation_info: &'_ ValidationInfo<'b>,
71 ) -> Result<(Self, ModuleAddr), RuntimeError> {
73 let mut instance = Self::new(user_data);
74 let module_addr = instance.add_module(module_name, validation_info)?;
75 Ok((instance, module_addr))
76 }
77
78 pub fn add_module(
80 &mut self,
81 module_name: &str,
82 validation_info: &'_ ValidationInfo<'b>,
83 ) -> Result<ModuleAddr, RuntimeError> {
84 self.store.add_module(module_name, validation_info, None)
85 }
86
87 pub fn get_function_by_name(
88 &self,
89 module_name: &str,
90 function_name: &str,
91 ) -> Result<FunctionRef, RuntimeError> {
92 FunctionRef::new_from_name(module_name, function_name, &self.store)
93 .map_err(|_| RuntimeError::FunctionNotFound)
94 }
95
96 pub fn get_function_by_index(
97 &self,
98 module_addr: ModuleAddr,
99 function_idx: usize,
100 ) -> Result<FunctionRef, RuntimeError> {
101 let module_inst = self.store.modules.get(module_addr);
102 let func_addr = *module_inst
103 .func_addrs
104 .get(function_idx)
105 .ok_or(RuntimeError::FunctionNotFound)?;
106
107 Ok(FunctionRef { func_addr })
108 }
109
110 pub fn invoke_typed<Params: InteropValueList, Returns: InteropValueList>(
112 &mut self,
113 function_ref: &FunctionRef,
114 params: Params,
115 ) -> Result<Returns, RuntimeError> {
117 self.invoke(function_ref, params.into_values())
118 .map(|values| Returns::try_from_values(values.into_iter()).unwrap_validated())
119 }
120
121 pub fn invoke(
123 &mut self,
124 function_ref: &FunctionRef,
125 params: Vec<Value>,
126 ) -> Result<Vec<Value>, RuntimeError> {
127 let FunctionRef { func_addr } = *function_ref;
128 self.store
129 .invoke(func_addr, params, None)
130 .map(|run_state| match run_state {
131 RunState::Finished(values) => values,
132 _ => unreachable!("non metered invoke call"),
133 })
134 }
135
136 pub fn create_resumable(
140 &self,
141 function_ref: &FunctionRef,
142 params: Vec<Value>,
143 fuel: u32,
144 ) -> Result<ResumableRef, RuntimeError> {
145 let FunctionRef { func_addr } = *function_ref;
146 self.store.create_resumable(func_addr, params, Some(fuel))
147 }
148
149 pub fn resume(&mut self, resumable_ref: ResumableRef) -> Result<RunState, RuntimeError> {
152 self.store.resume(resumable_ref)
153 }
154
155 pub fn access_fuel_mut<R>(
174 &mut self,
175 resumable_ref: &mut ResumableRef,
176 f: impl FnOnce(&mut Option<u32>) -> R,
177 ) -> Result<R, RuntimeError> {
178 self.store.access_fuel_mut(resumable_ref, f)
179 }
180
181 pub fn add_host_function_typed<Params: InteropValueList, Returns: InteropValueList>(
185 &mut self,
186 module_name: &str,
187 name: &str,
188 host_func: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
189 ) -> Result<FunctionRef, RuntimeError> {
190 let host_func_ty = FuncType {
191 params: ResultType {
192 valtypes: Vec::from(Params::TYS),
193 },
194 returns: ResultType {
195 valtypes: Vec::from(Returns::TYS),
196 },
197 };
198 self.add_host_function(module_name, name, host_func_ty, host_func)
199 }
200
201 pub fn add_host_function(
202 &mut self,
203 module_name: &str,
204 name: &str,
205 host_func_ty: FuncType,
206 host_func: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
207 ) -> Result<FunctionRef, RuntimeError> {
208 let func_addr = self.store.func_alloc(host_func_ty, host_func);
209 self.store.registry.register(
210 module_name.to_owned().into(),
211 name.to_owned().into(),
212 store::ExternVal::Func(func_addr),
213 )?;
214 Ok(FunctionRef { func_addr })
215 }
216
217 pub fn user_data(&self) -> &T {
218 &self.store.user_data
219 }
220
221 pub fn user_data_mut(&mut self) -> &mut T {
222 &mut self.store.user_data
223 }
224
225 pub fn global_type(&self, global_addr: GlobalAddr) -> GlobalType {
227 self.store.global_type(global_addr)
228 }
229
230 pub fn global_read(&self, global_addr: GlobalAddr) -> Value {
232 self.store.global_read(global_addr)
233 }
234
235 pub fn global_write(
241 &mut self,
242 global_addr: GlobalAddr,
243 val: Value,
244 ) -> Result<(), RuntimeError> {
245 self.store.global_write(global_addr, val)
246 }
247
248 pub fn lookup_export(
250 &self,
251 module_name: Cow<'static, str>,
252 name: Cow<'static, str>,
253 ) -> Result<ExternVal, RuntimeError> {
254 self.store.registry.lookup(module_name, name).copied()
255 }
256}
257
258pub fn host_function_wrapper<Params: InteropValueList, Results: InteropValueList>(
276 params: Vec<Value>,
277 f: impl FnOnce(Params) -> Result<Results, HaltExecutionError>,
278) -> Result<Vec<Value>, HaltExecutionError> {
279 let params =
280 Params::try_from_values(params.into_iter()).expect("Params match the actual parameters");
281 f(params).map(Results::into_values)
282}