use alloc::{sync::Arc, vec::Vec};
use core::future::Future;
use miden_core::{
Felt, Word,
advice::{AdviceMap, AdviceStack},
crypto::merkle::InnerNodeInfo,
events::{EventId, EventName},
};
use miden_debug_types::{Location, SourceFile, SourceSpan};
use crate::ProcessorState;
pub(super) mod advice;
pub mod debug;
pub mod default;
pub mod handlers;
use handlers::{EventError, TraceError};
mod mast_forest_store;
pub use mast_forest_store::{LoadedMastForest, MastForestStore, MemMastForestStore};
#[derive(Debug, PartialEq, Eq)]
pub enum AdviceMutation {
ExtendStack { stack: AdviceStack },
ExtendMap { map: AdviceMap },
ExtendMerkleStore { inner_nodes: Vec<InnerNodeInfo> },
}
impl AdviceMutation {
pub fn extend_advice_stack(stack: AdviceStack) -> Self {
Self::ExtendStack { stack }
}
pub fn extend_advice_stack_with(elements: impl IntoIterator<Item = Felt>) -> Self {
Self::ExtendStack { stack: elements.into_iter().collect() }
}
pub fn extend_map(map: AdviceMap) -> Self {
Self::ExtendMap { map }
}
pub fn extend_merkle_store(inner_nodes: impl IntoIterator<Item = InnerNodeInfo>) -> Self {
Self::ExtendMerkleStore { inner_nodes: Vec::from_iter(inner_nodes) }
}
}
pub trait BaseHost {
fn get_label_and_source_file(
&self,
location: &Location,
) -> (SourceSpan, Option<Arc<SourceFile>>);
fn resolve_event(&self, _event_id: EventId) -> Option<&EventName> {
None
}
fn resolve_trace(&self, _trace_id: EventId) -> Option<&EventName> {
None
}
}
impl<T: BaseHost + ?Sized> BaseHost for &mut T {
fn get_label_and_source_file(
&self,
location: &Location,
) -> (SourceSpan, Option<Arc<SourceFile>>) {
(**self).get_label_and_source_file(location)
}
fn resolve_event(&self, event_id: EventId) -> Option<&EventName> {
(**self).resolve_event(event_id)
}
fn resolve_trace(&self, trace_id: EventId) -> Option<&EventName> {
(**self).resolve_trace(trace_id)
}
}
pub trait SyncHost: BaseHost {
fn get_mast_forest(&self, node_digest: &Word) -> Option<LoadedMastForest>;
fn on_event(&mut self, process: &ProcessorState<'_>)
-> Result<Vec<AdviceMutation>, EventError>;
fn on_trace(&mut self, _process: &ProcessorState<'_>) -> Result<(), TraceError> {
Ok(())
}
}
pub trait Host: BaseHost {
fn get_mast_forest(&self, node_digest: &Word)
-> impl FutureMaybeSend<Option<LoadedMastForest>>;
fn on_event(
&mut self,
process: &ProcessorState<'_>,
) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>>;
fn on_trace(
&mut self,
_process: &ProcessorState<'_>,
) -> impl FutureMaybeSend<Result<(), TraceError>> {
async move { Ok(()) }
}
}
impl<T> Host for T
where
T: SyncHost,
{
fn get_mast_forest(
&self,
node_digest: &Word,
) -> impl FutureMaybeSend<Option<LoadedMastForest>> {
let result = SyncHost::get_mast_forest(self, node_digest);
async move { result }
}
fn on_event(
&mut self,
process: &ProcessorState<'_>,
) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>> {
let result = SyncHost::on_event(self, process);
async move { result }
}
fn on_trace(
&mut self,
process: &ProcessorState<'_>,
) -> impl FutureMaybeSend<Result<(), TraceError>> {
let result = SyncHost::on_trace(self, process);
async move { result }
}
}
#[cfg(target_family = "wasm")]
pub trait FutureMaybeSend<O>: Future<Output = O> {}
#[cfg(target_family = "wasm")]
impl<T, O> FutureMaybeSend<O> for T where T: Future<Output = O> {}
#[cfg(not(target_family = "wasm"))]
pub trait FutureMaybeSend<O>: Future<Output = O> + Send {}
#[cfg(not(target_family = "wasm"))]
impl<T, O> FutureMaybeSend<O> for T where T: Future<Output = O> + Send {}
#[cfg(test)]
mod tests {
use super::{AdviceMutation, AdviceStack, Felt};
#[test]
fn extend_advice_stack_with_matches_the_typed_helper() {
let mut stack = AdviceStack::new();
stack.append_elements((1..=3u32).map(Felt::from_u32));
assert_eq!(
AdviceMutation::extend_advice_stack_with((1..=3u32).map(Felt::from_u32)),
AdviceMutation::extend_advice_stack(stack)
);
}
}