miden_debug_engine/exec/
host.rs1use std::{collections::VecDeque, num::NonZeroU32, sync::Arc};
2
3use miden_assembly::SourceManager;
4use miden_core::{
5 Word,
6 events::{EventId, EventName},
7};
8use miden_debug_types::{Location, SourceFile, SourceSpan};
9use miden_mast_package::Package;
10use miden_processor::{
11 BaseHost, ExecutionError, FutureMaybeSend, Host, LoadedMastForest, MastForestStore,
12 MemMastForestStore, ProcessorState,
13 advice::AdviceMutation,
14 event::{EventError, EventHandler, EventHandlerRegistry},
15};
16
17use super::advice::clone_advice_mutations;
18use crate::Event;
19
20pub struct DebuggerHost<S: SourceManager + ?Sized> {
24 store: MemMastForestStore,
25 event_handlers: EventHandlerRegistry,
26 #[allow(clippy::type_complexity)]
27 on_assert_failed: Option<Box<dyn FnMut(&ProcessorState<'_>, u32)>>,
28 source_manager: Arc<S>,
29 event_replay: VecDeque<Vec<AdviceMutation>>,
30 event_recording: Option<Vec<Vec<AdviceMutation>>>,
31}
32impl<S> DebuggerHost<S>
33where
34 S: SourceManager + ?Sized,
35{
36 pub fn new(source_manager: Arc<S>) -> Self {
38 Self {
39 store: Default::default(),
40 event_handlers: EventHandlerRegistry::default(),
41 on_assert_failed: None,
42 source_manager,
43 event_replay: VecDeque::new(),
44 event_recording: None,
45 }
46 }
47
48 pub fn set_event_replay(&mut self, events: VecDeque<Vec<AdviceMutation>>) {
54 self.event_replay = events;
55 }
56
57 pub fn with_event_advice_mutations_recording(mut self) -> Self {
67 self.event_recording = Some(Vec::new());
68 self
69 }
70
71 pub fn take_recorded_event_mutations(&mut self) -> Vec<Vec<AdviceMutation>> {
76 self.event_recording.as_mut().map(core::mem::take).unwrap_or_default()
77 }
78
79 pub fn register_assert_failed_tracer<F>(&mut self, callback: F)
81 where
82 F: FnMut(&ProcessorState<'_>, u32) + 'static,
83 {
84 self.on_assert_failed = Some(Box::new(callback));
85 }
86
87 pub fn handle_assert_failed(
92 &mut self,
93 process: &ProcessorState<'_>,
94 err_code: Option<NonZeroU32>,
95 ) {
96 if let Some(handler) = self.on_assert_failed.as_mut() {
97 handler(process, err_code.map(|nz| nz.get()).unwrap_or_default());
98 }
99 }
100
101 pub fn load_package(&mut self, package: Arc<Package>) {
103 let mast = package.mast_forest().clone();
104 let debug_info = package.debug_info();
105 self.store
106 .insert_loaded(LoadedMastForest::with_package_debug_info(mast, debug_info));
107 }
108
109 pub fn load_mast_forest(&mut self, forest: LoadedMastForest) {
111 self.store.insert_loaded(forest);
112 }
113
114 pub fn register_event_handler(
116 &mut self,
117 event: EventName,
118 handler: Arc<dyn EventHandler>,
119 ) -> Result<(), ExecutionError> {
120 self.event_handlers.register(event, handler)
121 }
122}
123
124impl<S> BaseHost for DebuggerHost<S>
125where
126 S: SourceManager + ?Sized,
127{
128 fn get_label_and_source_file(
129 &self,
130 location: &Location,
131 ) -> (SourceSpan, Option<Arc<SourceFile>>) {
132 let maybe_file = self.source_manager.get_by_uri(location.uri());
133 let span = self.source_manager.location_to_span(location.clone()).unwrap_or_default();
134 (span, maybe_file)
135 }
136
137 fn resolve_event(&self, event_id: EventId) -> Option<&EventName> {
138 self.event_handlers.resolve_event(event_id)
139 }
140}
141
142impl<S> Host for DebuggerHost<S>
143where
144 S: SourceManager + ?Sized,
145{
146 fn get_mast_forest(
147 &self,
148 node_digest: &Word,
149 ) -> impl FutureMaybeSend<Option<LoadedMastForest>> {
150 std::future::ready(self.store.get(node_digest))
151 }
152
153 fn on_event(
154 &mut self,
155 process: &ProcessorState<'_>,
156 ) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>> {
157 let event_id = EventId::from_felt(process.get_stack_item(0));
158 let is_builtin_event = Event::from(event_id).has_builtin_handler();
159 let replay_mutations = self.event_replay.pop_front();
160 let is_replaying = replay_mutations.is_some();
161
162 if let Some(mutations) = replay_mutations {
163 if !is_builtin_event {
164 return std::future::ready(Ok(mutations));
166 }
167
168 if is_builtin_event {
171 assert!(
172 mutations.is_empty(),
173 "debug events must not be associated with mutations from replay"
174 );
175 }
176 }
177
178 let result = match self.event_handlers.handle_event(event_id, process) {
179 Ok(Some(mutations)) => Ok(mutations),
180 Ok(None) => {
181 #[derive(Debug, thiserror::Error)]
182 #[error("no event handler registered")]
183 struct UnhandledEvent;
184
185 Err(UnhandledEvent.into())
186 }
187 Err(err) => Err(err),
188 };
189
190 if !is_replaying
191 && let (Some(log), Ok(mutations)) = (self.event_recording.as_mut(), &result)
192 {
193 log.push(clone_advice_mutations(mutations));
194 }
195 std::future::ready(result)
196 }
197}