1use std::{collections::BTreeMap, num::NonZeroU32, sync::Arc};
2
3use miden_assembly::SourceManager;
4use miden_core::Word;
5use miden_debug_types::{Location, SourceFile, SourceSpan};
6use miden_processor::{
7 AdviceProvider, BaseHost, EventHandlerRegistry, ExecutionError, MastForest, MastForestStore,
8 MemMastForestStore, ProcessState, RowIndex, SyncHost,
9};
10
11use super::{TraceEvent, TraceHandler};
12
13#[derive(Default)]
17pub struct DebuggerHost<S: SourceManager> {
18 _adv_provider: AdviceProvider,
19 store: MemMastForestStore,
20 tracing_callbacks: BTreeMap<u32, Vec<Box<TraceHandler>>>,
21 _event_handlers: EventHandlerRegistry,
22 on_assert_failed: Option<Box<TraceHandler>>,
23 source_manager: Arc<S>,
24}
25impl<S> DebuggerHost<S>
26where
27 S: SourceManager,
28{
29 pub fn new(_adv_provider: AdviceProvider, source_manager: S) -> Self {
31 Self {
32 _adv_provider,
33 store: Default::default(),
34 tracing_callbacks: Default::default(),
35 _event_handlers: EventHandlerRegistry::default(),
36 on_assert_failed: None,
37 source_manager: Arc::new(source_manager),
38 }
39 }
40
41 pub fn register_trace_handler<F>(&mut self, event: TraceEvent, callback: F)
43 where
44 F: FnMut(RowIndex, TraceEvent) + 'static,
45 {
46 let key = match event {
47 TraceEvent::AssertionFailed(None) => u32::MAX,
48 ev => ev.into(),
49 };
50 self.tracing_callbacks.entry(key).or_default().push(Box::new(callback));
51 }
52
53 pub fn register_assert_failed_tracer<F>(&mut self, callback: F)
55 where
56 F: FnMut(RowIndex, TraceEvent) + 'static,
57 {
58 self.on_assert_failed = Some(Box::new(callback));
59 }
60
61 pub fn load_mast_forest(&mut self, forest: Arc<MastForest>) {
63 self.store.insert(forest);
64 }
65}
66
67impl<S> BaseHost for DebuggerHost<S>
68where
69 S: SourceManager,
70{
71 fn get_label_and_source_file(
72 &self,
73 location: &Location,
74 ) -> (SourceSpan, Option<Arc<SourceFile>>) {
75 let maybe_file = self.source_manager.get_by_uri(location.uri());
76 let span = self.source_manager.location_to_span(location.clone()).unwrap_or_default();
77 (span, maybe_file)
78 }
79
80 fn on_trace(
81 &mut self,
82 process: &mut ProcessState,
83 trace_id: u32,
84 ) -> Result<(), ExecutionError> {
85 let event = TraceEvent::from(trace_id);
86 let clk = process.clk();
87 if let Some(handlers) = self.tracing_callbacks.get_mut(&trace_id) {
88 for handler in handlers.iter_mut() {
89 handler(clk, event);
90 }
91 }
92 Ok(())
93 }
94
95 fn on_assert_failed(&mut self, process: &ProcessState, err_code: miden_core::Felt) {
96 let clk = process.clk();
97 if let Some(handler) = self.on_assert_failed.as_mut() {
98 handler(clk, TraceEvent::AssertionFailed(NonZeroU32::new(err_code.as_int() as u32)));
100 }
101 }
102}
103
104impl<S> SyncHost for DebuggerHost<S>
105where
106 S: SourceManager,
107{
108 fn get_mast_forest(&self, node_digest: &Word) -> Option<Arc<MastForest>> {
109 self.store.get(node_digest)
110 }
111
112 fn on_event(
113 &mut self,
114 _process: &ProcessState,
115 ) -> Result<Vec<miden_processor::AdviceMutation>, miden_processor::EventError> {
116 Ok(Vec::new())
117 }
118}