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