miden_processor/fast/
sys_ops.rs

1use miden_core::{Felt, mast::MastForest, sys_events::SystemEvent};
2
3use super::{ExecutionError, FastProcessor, ONE};
4use crate::{
5    AsyncHost, BaseHost, ErrorContext, FMP_MIN,
6    operations::sys_ops::sys_event_handlers::handle_system_event, system::FMP_MAX,
7};
8
9impl FastProcessor {
10    /// Analogous to `Process::op_assert`.
11    #[inline(always)]
12    pub fn op_assert(
13        &mut self,
14        err_code: Felt,
15        op_idx: usize,
16        host: &mut impl BaseHost,
17        program: &MastForest,
18        err_ctx: &impl ErrorContext,
19    ) -> Result<(), ExecutionError> {
20        if self.stack_get(0) != ONE {
21            let process = &mut self.state(op_idx);
22            host.on_assert_failed(process, err_code);
23            let err_msg = program.resolve_error_message(err_code);
24            return Err(ExecutionError::failed_assertion(
25                process.clk(),
26                err_code,
27                err_msg,
28                err_ctx,
29            ));
30        }
31        self.decrement_stack_size();
32        Ok(())
33    }
34
35    /// Analogous to `Process::op_fmpadd`.
36    pub fn op_fmpadd(&mut self) {
37        let fmp = self.fmp;
38        let top = self.stack_get_mut(0);
39
40        *top += fmp;
41    }
42
43    /// Analogous to `Process::op_fmpupdate`.
44    pub fn op_fmpupdate(&mut self) -> Result<(), ExecutionError> {
45        let top = self.stack_get(0);
46
47        let new_fmp = self.fmp + top;
48        let new_fmp_int = new_fmp.as_int();
49        if !(FMP_MIN..=FMP_MAX).contains(&new_fmp_int) {
50            return Err(ExecutionError::InvalidFmpValue(self.fmp, new_fmp));
51        }
52
53        self.fmp = new_fmp;
54        self.decrement_stack_size();
55        Ok(())
56    }
57
58    /// Analogous to `Process::op_sdepth`.
59    pub fn op_sdepth(&mut self) {
60        let depth = self.stack_depth();
61        self.increment_stack_size();
62        self.stack_write(0, depth.into());
63    }
64
65    /// Analogous to `Process::op_caller`.
66    pub fn op_caller(&mut self) -> Result<(), ExecutionError> {
67        if !self.in_syscall {
68            return Err(ExecutionError::CallerNotInSyscall);
69        }
70
71        let caller_hash = self.caller_hash;
72        self.stack_write_word(0, &caller_hash);
73
74        Ok(())
75    }
76
77    /// Analogous to `Process::op_clk`.
78    pub fn op_clk(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
79        self.increment_stack_size();
80        self.stack_write(0, (self.clk + op_idx).into());
81        Ok(())
82    }
83
84    /// Analogous to `Process::op_emit`.
85    #[inline(always)]
86    pub async fn op_emit(
87        &mut self,
88        event_id: u32,
89        op_idx: usize,
90        host: &mut impl AsyncHost,
91        err_ctx: &impl ErrorContext,
92    ) -> Result<(), ExecutionError> {
93        let process = &mut self.state(op_idx);
94        // If it's a system event, handle it directly. Otherwise, forward it to the host.
95        if let Some(system_event) = SystemEvent::from_event_id(event_id) {
96            handle_system_event(process, system_event, err_ctx)
97        } else {
98            host.on_event(process, event_id, err_ctx).await
99        }
100    }
101}