miden_processor/host/
default.rs

1use alloc::{sync::Arc, vec::Vec};
2
3use miden_core::{DebugOptions, EventId, EventName, Word, mast::MastForest};
4use miden_debug_types::{
5    DefaultSourceManager, Location, SourceFile, SourceManager, SourceManagerSync, SourceSpan,
6};
7
8use crate::{
9    AdviceMutation, AsyncHost, BaseHost, DebugError, DebugHandler, EventHandler,
10    EventHandlerRegistry, ExecutionError, MastForestStore, MemMastForestStore, ProcessState,
11    SyncHost, TraceError,
12    host::{EventError, FutureMaybeSend, debug::DefaultDebugHandler},
13};
14
15// DEFAULT HOST IMPLEMENTATION
16// ================================================================================================
17
18/// A default Host implementation that provides the essential functionality required by the VM.
19#[derive(Debug)]
20pub struct DefaultHost<
21    D: DebugHandler = DefaultDebugHandler,
22    S: SourceManager = DefaultSourceManager,
23> {
24    store: MemMastForestStore,
25    event_handlers: EventHandlerRegistry,
26    debug_handler: D,
27    source_manager: Arc<S>,
28}
29
30impl Default for DefaultHost {
31    fn default() -> Self {
32        Self {
33            store: MemMastForestStore::default(),
34            event_handlers: EventHandlerRegistry::default(),
35            debug_handler: DefaultDebugHandler::default(),
36            source_manager: Arc::new(DefaultSourceManager::default()),
37        }
38    }
39}
40
41impl<D, S> DefaultHost<D, S>
42where
43    D: DebugHandler,
44    S: SourceManager,
45{
46    /// Use the given source manager implementation instead of the default one
47    /// [`DefaultSourceManager`].
48    pub fn with_source_manager<O>(self, source_manager: Arc<O>) -> DefaultHost<D, O>
49    where
50        O: SourceManager,
51    {
52        DefaultHost::<D, O> {
53            store: self.store,
54            event_handlers: self.event_handlers,
55            debug_handler: self.debug_handler,
56            source_manager,
57        }
58    }
59
60    /// Loads a [`HostLibrary`] containing a [`MastForest`] with its list of event handlers.
61    pub fn load_library(&mut self, library: impl Into<HostLibrary>) -> Result<(), ExecutionError> {
62        let library = library.into();
63        self.store.insert(library.mast_forest);
64
65        for (event, handler) in library.handlers {
66            self.event_handlers.register(event, handler)?;
67        }
68        Ok(())
69    }
70
71    /// Adds a [`HostLibrary`] containing a [`MastForest`] with its list of event handlers.
72    /// to the host.
73    pub fn with_library(mut self, library: impl Into<HostLibrary>) -> Result<Self, ExecutionError> {
74        self.load_library(library)?;
75        Ok(self)
76    }
77
78    /// Registers a single [`EventHandler`] into this host.
79    ///
80    /// The handler can be either a closure or a free function with signature
81    /// `fn(&mut ProcessState) -> Result<(), EventHandler>`
82    pub fn register_handler(
83        &mut self,
84        event: EventName,
85        handler: Arc<dyn EventHandler>,
86    ) -> Result<(), ExecutionError> {
87        self.event_handlers.register(event, handler)
88    }
89
90    /// Un-registers a handler with the given id, returning a flag indicating whether a handler
91    /// was previously registered with this id.
92    pub fn unregister_handler(&mut self, id: EventId) -> bool {
93        self.event_handlers.unregister(id)
94    }
95
96    /// Replaces a handler with the given event, returning a flag indicating whether a handler
97    /// was previously registered with this event ID.
98    pub fn replace_handler(&mut self, event: EventName, handler: Arc<dyn EventHandler>) -> bool {
99        let event_id = event.to_event_id();
100        let existed = self.event_handlers.unregister(event_id);
101        self.register_handler(event, handler).unwrap();
102        existed
103    }
104
105    /// Replace the current [`DebugHandler`] with a custom one.
106    pub fn with_debug_handler<H: DebugHandler>(self, handler: H) -> DefaultHost<H, S> {
107        DefaultHost::<H, S> {
108            store: self.store,
109            event_handlers: self.event_handlers,
110            debug_handler: handler,
111            source_manager: self.source_manager,
112        }
113    }
114
115    /// Returns a reference to the [`DebugHandler`], useful for recovering debug information
116    /// emitted during a program execution.
117    pub fn debug_handler(&self) -> &D {
118        &self.debug_handler
119    }
120}
121
122impl<D, S> BaseHost for DefaultHost<D, S>
123where
124    D: DebugHandler,
125    S: SourceManager,
126{
127    fn get_label_and_source_file(
128        &self,
129        location: &Location,
130    ) -> (SourceSpan, Option<Arc<SourceFile>>) {
131        let maybe_file = self.source_manager.get_by_uri(location.uri());
132        let span = self.source_manager.location_to_span(location.clone()).unwrap_or_default();
133        (span, maybe_file)
134    }
135
136    fn on_debug(
137        &mut self,
138        process: &mut ProcessState,
139        options: &DebugOptions,
140    ) -> Result<(), DebugError> {
141        self.debug_handler.on_debug(process, options)
142    }
143
144    fn on_trace(&mut self, process: &mut ProcessState, trace_id: u32) -> Result<(), TraceError> {
145        self.debug_handler.on_trace(process, trace_id)
146    }
147
148    fn resolve_event(&self, event_id: EventId) -> Option<&EventName> {
149        self.event_handlers.resolve_event(event_id)
150    }
151}
152
153impl<D, S> SyncHost for DefaultHost<D, S>
154where
155    D: DebugHandler,
156    S: SourceManager,
157{
158    fn get_mast_forest(&self, node_digest: &Word) -> Option<Arc<MastForest>> {
159        self.store.get(node_digest)
160    }
161
162    fn on_event(&mut self, process: &ProcessState) -> Result<Vec<AdviceMutation>, EventError> {
163        let event_id = EventId::from_felt(process.get_stack_item(0));
164        if let Some(mutations) = self.event_handlers.handle_event(event_id, process)? {
165            // the event was handled by the registered event handlers; just return
166            return Ok(mutations);
167        }
168
169        // EventError is a `Box<dyn Error>` so we can define the error anonymously.
170        #[derive(Debug, thiserror::Error)]
171        #[error("no event handler registered")]
172        struct UnhandledEvent;
173
174        Err(UnhandledEvent.into())
175    }
176}
177
178impl<D, S> AsyncHost for DefaultHost<D, S>
179where
180    D: DebugHandler,
181    S: SourceManagerSync,
182{
183    fn get_mast_forest(&self, node_digest: &Word) -> impl FutureMaybeSend<Option<Arc<MastForest>>> {
184        let result = <Self as SyncHost>::get_mast_forest(self, node_digest);
185        async move { result }
186    }
187
188    fn on_event(
189        &mut self,
190        process: &ProcessState<'_>,
191    ) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>> {
192        let result = <Self as SyncHost>::on_event(self, process);
193        async move { result }
194    }
195}
196
197// NOOPHOST
198// ================================================================================================
199
200/// A Host which does nothing.
201pub struct NoopHost;
202
203impl BaseHost for NoopHost {
204    #[inline(always)]
205    fn get_label_and_source_file(
206        &self,
207        _location: &Location,
208    ) -> (SourceSpan, Option<Arc<SourceFile>>) {
209        (SourceSpan::UNKNOWN, None)
210    }
211}
212
213impl SyncHost for NoopHost {
214    #[inline(always)]
215    fn get_mast_forest(&self, _node_digest: &Word) -> Option<Arc<MastForest>> {
216        None
217    }
218
219    #[inline(always)]
220    fn on_event(&mut self, _process: &ProcessState<'_>) -> Result<Vec<AdviceMutation>, EventError> {
221        Ok(Vec::new())
222    }
223}
224
225impl AsyncHost for NoopHost {
226    #[inline(always)]
227    fn get_mast_forest(
228        &self,
229        _node_digest: &Word,
230    ) -> impl FutureMaybeSend<Option<Arc<MastForest>>> {
231        async { None }
232    }
233
234    #[inline(always)]
235    fn on_event(
236        &mut self,
237        _process: &ProcessState<'_>,
238    ) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>> {
239        async { Ok(Vec::new()) }
240    }
241}
242
243// HOST LIBRARY
244// ================================================================================================
245
246/// A rich library representing a [`MastForest`] which also exports
247/// a list of handlers for events it may call.
248#[derive(Default)]
249pub struct HostLibrary {
250    /// A `MastForest` with procedures exposed by this library.
251    pub mast_forest: Arc<MastForest>,
252    /// List of handlers along with their event names to call them with `emit`.
253    pub handlers: Vec<(EventName, Arc<dyn EventHandler>)>,
254}
255
256impl From<Arc<MastForest>> for HostLibrary {
257    fn from(mast_forest: Arc<MastForest>) -> Self {
258        Self { mast_forest, handlers: vec![] }
259    }
260}
261
262impl From<&Arc<MastForest>> for HostLibrary {
263    fn from(mast_forest: &Arc<MastForest>) -> Self {
264        Self {
265            mast_forest: mast_forest.clone(),
266            handlers: vec![],
267        }
268    }
269}