Skip to main content

miden_processor/host/
default.rs

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