use alloc::sync::Arc;
use core::ops::ControlFlow;
use miden_core::{mast::MastForest, program::Kernel};
use crate::{
ExecutionError, FastProcessor, Stopper,
continuation_stack::{Continuation, ContinuationStack},
};
#[derive(Debug)]
pub struct ResumeContext {
pub(crate) current_forest: Arc<MastForest>,
pub(crate) continuation_stack: ContinuationStack,
pub(crate) kernel: Kernel,
}
impl ResumeContext {
pub fn continuation_stack(&self) -> &ContinuationStack {
&self.continuation_stack
}
pub fn current_forest(&self) -> &Arc<MastForest> {
&self.current_forest
}
pub fn kernel(&self) -> &Kernel {
&self.kernel
}
}
pub struct NeverStopper;
impl Stopper for NeverStopper {
type Processor = FastProcessor;
#[inline(always)]
fn should_stop(
&self,
processor: &FastProcessor,
continuation_stack: &ContinuationStack,
_continuation_after_stop: impl FnOnce() -> Option<Continuation>,
) -> ControlFlow<BreakReason> {
check_if_max_cycles_exceeded(processor)?;
check_if_continuation_stack_too_large(processor, continuation_stack)
}
}
pub struct StepStopper;
impl Stopper for StepStopper {
type Processor = FastProcessor;
#[inline(always)]
fn should_stop(
&self,
processor: &FastProcessor,
continuation_stack: &ContinuationStack,
continuation_after_stop: impl FnOnce() -> Option<Continuation>,
) -> ControlFlow<BreakReason> {
check_if_max_cycles_exceeded(processor)?;
check_if_continuation_stack_too_large(processor, continuation_stack)?;
ControlFlow::Break(BreakReason::Stopped(continuation_after_stop()))
}
}
#[inline(always)]
fn check_if_max_cycles_exceeded(processor: &FastProcessor) -> ControlFlow<BreakReason> {
if processor.clk > processor.options.max_cycles() as usize {
ControlFlow::Break(BreakReason::Err(ExecutionError::CycleLimitExceeded(
processor.options.max_cycles(),
)))
} else {
ControlFlow::Continue(())
}
}
#[inline(always)]
fn check_if_continuation_stack_too_large(
processor: &FastProcessor,
continuation_stack: &ContinuationStack,
) -> ControlFlow<BreakReason> {
if continuation_stack.len() > processor.options.max_num_continuations() {
ControlFlow::Break(BreakReason::Err(ExecutionError::Internal(
"continuation stack size exceeded the allowed maximum",
)))
} else {
ControlFlow::Continue(())
}
}
#[derive(Debug)]
pub enum BreakReason {
Err(ExecutionError),
Stopped(Option<Continuation>),
}