use alloc::{sync::Arc, vec::Vec};
use miden_core::{
Word,
events::{EventId, EventName},
mast::MastForest,
operations::DebugOptions,
};
use miden_debug_types::{DefaultSourceManager, Location, SourceFile, SourceManager, SourceSpan};
use super::{
FutureMaybeSend,
debug::DefaultDebugHandler,
handlers::{EventError, EventHandler, EventHandlerRegistry},
};
use crate::{
DebugError, DebugHandler, ExecutionError, Host, MastForestStore, MemMastForestStore,
ProcessorState, TraceError, advice::AdviceMutation,
};
#[derive(Debug)]
pub struct DefaultHost<
D: DebugHandler = DefaultDebugHandler,
S: SourceManager = DefaultSourceManager,
> {
store: MemMastForestStore,
event_handlers: EventHandlerRegistry,
debug_handler: D,
source_manager: Arc<S>,
}
impl Default for DefaultHost {
fn default() -> Self {
Self {
store: MemMastForestStore::default(),
event_handlers: EventHandlerRegistry::default(),
debug_handler: DefaultDebugHandler::default(),
source_manager: Arc::new(DefaultSourceManager::default()),
}
}
}
impl<D, S> DefaultHost<D, S>
where
D: DebugHandler,
S: SourceManager,
{
pub fn with_source_manager<O>(self, source_manager: Arc<O>) -> DefaultHost<D, O>
where
O: SourceManager,
{
DefaultHost::<D, O> {
store: self.store,
event_handlers: self.event_handlers,
debug_handler: self.debug_handler,
source_manager,
}
}
pub fn load_library(&mut self, library: impl Into<HostLibrary>) -> Result<(), ExecutionError> {
let library = library.into();
self.store.insert(library.mast_forest);
for (event, handler) in library.handlers {
self.event_handlers.register(event, handler)?;
}
Ok(())
}
pub fn with_library(mut self, library: impl Into<HostLibrary>) -> Result<Self, ExecutionError> {
self.load_library(library)?;
Ok(self)
}
pub fn register_handler(
&mut self,
event: EventName,
handler: Arc<dyn EventHandler>,
) -> Result<(), ExecutionError> {
self.event_handlers.register(event, handler)
}
pub fn unregister_handler(&mut self, id: EventId) -> bool {
self.event_handlers.unregister(id)
}
pub fn replace_handler(&mut self, event: EventName, handler: Arc<dyn EventHandler>) -> bool {
let event_id = event.to_event_id();
let existed = self.event_handlers.unregister(event_id);
self.register_handler(event, handler).unwrap();
existed
}
pub fn with_debug_handler<H: DebugHandler>(self, handler: H) -> DefaultHost<H, S> {
DefaultHost::<H, S> {
store: self.store,
event_handlers: self.event_handlers,
debug_handler: handler,
source_manager: self.source_manager,
}
}
pub fn debug_handler(&self) -> &D {
&self.debug_handler
}
}
impl<D, S> Host for DefaultHost<D, S>
where
D: DebugHandler,
S: SourceManager,
{
fn get_label_and_source_file(
&self,
location: &Location,
) -> (SourceSpan, Option<Arc<SourceFile>>) {
let maybe_file = self.source_manager.get_by_uri(location.uri());
let span = self.source_manager.location_to_span(location.clone()).unwrap_or_default();
(span, maybe_file)
}
fn get_mast_forest(&self, node_digest: &Word) -> impl FutureMaybeSend<Option<Arc<MastForest>>> {
let result = self.store.get(node_digest);
async move { result }
}
fn on_event(
&mut self,
process: &ProcessorState<'_>,
) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>> {
let event_id = EventId::from_felt(process.get_stack_item(0));
let result = match self.event_handlers.handle_event(event_id, process) {
Ok(Some(mutations)) => {
Ok(mutations)
},
Ok(None) => {
#[derive(Debug, thiserror::Error)]
#[error("no event handler registered")]
struct UnhandledEvent;
Err(UnhandledEvent.into())
},
Err(e) => Err(e),
};
async move { result }
}
fn on_debug(
&mut self,
process: &ProcessorState,
options: &DebugOptions,
) -> Result<(), DebugError> {
self.debug_handler.on_debug(process, options)
}
fn on_trace(&mut self, process: &ProcessorState, trace_id: u32) -> Result<(), TraceError> {
self.debug_handler.on_trace(process, trace_id)
}
fn resolve_event(&self, event_id: EventId) -> Option<&EventName> {
self.event_handlers.resolve_event(event_id)
}
}
pub struct NoopHost;
impl Host for NoopHost {
#[inline(always)]
fn get_label_and_source_file(
&self,
_location: &Location,
) -> (SourceSpan, Option<Arc<SourceFile>>) {
(SourceSpan::UNKNOWN, None)
}
#[inline(always)]
fn get_mast_forest(
&self,
_node_digest: &Word,
) -> impl FutureMaybeSend<Option<Arc<MastForest>>> {
async { None }
}
#[inline(always)]
fn on_event(
&mut self,
_process: &ProcessorState<'_>,
) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>> {
async { Ok(Vec::new()) }
}
}
#[derive(Default)]
pub struct HostLibrary {
pub mast_forest: Arc<MastForest>,
pub handlers: Vec<(EventName, Arc<dyn EventHandler>)>,
}
impl From<Arc<MastForest>> for HostLibrary {
fn from(mast_forest: Arc<MastForest>) -> Self {
Self { mast_forest, handlers: vec![] }
}
}
impl From<&Arc<MastForest>> for HostLibrary {
fn from(mast_forest: &Arc<MastForest>) -> Self {
Self {
mast_forest: mast_forest.clone(),
handlers: vec![],
}
}
}