miden_processor/host/
default.rs

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