miden_processor/
executor.rs1use miden_mast_package::debug_info::{DebugSourceNodeId, PackageDebugInfo};
2
3use crate::{
4 ExecutionError, ExecutionOptions, ExecutionOutput, FastProcessor, FutureMaybeSend, Host,
5 Program, StackInputs,
6 advice::{AdviceError, AdviceInputs},
7};
8
9pub trait ProgramExecutor {
18 fn new(
26 stack_inputs: StackInputs,
27 advice_inputs: AdviceInputs,
28 options: ExecutionOptions,
29 ) -> Result<Self, AdviceError>
30 where
31 Self: Sized;
32
33 fn with_debug_info(self, package_debug_info: PackageDebugInfo) -> Self;
35
36 fn with_entrypoint_source_node(self, entrypoint_source_node: Option<DebugSourceNodeId>)
38 -> Self;
39
40 fn execute<H: Host + Send>(
42 self,
43 program: &Program,
44 host: &mut H,
45 ) -> impl FutureMaybeSend<Result<ExecutionOutput, ExecutionError>>;
46}
47
48impl ProgramExecutor for FastProcessor {
49 fn new(
50 stack_inputs: StackInputs,
51 advice_inputs: AdviceInputs,
52 options: ExecutionOptions,
53 ) -> Result<Self, AdviceError> {
54 FastProcessor::new_with_options(stack_inputs, advice_inputs, options)
55 }
56
57 fn with_debug_info(mut self, package_debug_info: PackageDebugInfo) -> Self {
58 self.package_debug_info = Some(package_debug_info);
59 self
60 }
61
62 fn with_entrypoint_source_node(
63 mut self,
64 entrypoint_source_node: Option<DebugSourceNodeId>,
65 ) -> Self {
66 self.entrypoint_source_node = entrypoint_source_node;
67 self
68 }
69
70 fn execute<H: Host + Send>(
71 self,
72 program: &Program,
73 host: &mut H,
74 ) -> impl FutureMaybeSend<Result<ExecutionOutput, ExecutionError>> {
75 async move {
76 match (self.package_debug_info.clone(), self.entrypoint_source_node) {
77 (Some(package_debug_info), Some(entrypoint_source_node)) => {
78 FastProcessor::execute_with_package_debug_info_at_source_node(
79 self,
80 program,
81 &package_debug_info,
82 entrypoint_source_node,
83 host,
84 )
85 .await
86 },
87 (Some(package_debug_info), None) => {
88 FastProcessor::execute_with_package_debug_info(
89 self,
90 program,
91 &package_debug_info,
92 host,
93 )
94 .await
95 },
96 (None, _) => FastProcessor::execute(self, program, host).await,
97 }
98 }
99 }
100}
101
102#[cfg(test)]
106mod tests {
107 use miden_assembly::Assembler;
108
109 use super::*;
110 use crate::{DefaultHost, StackInputs};
111
112 #[tokio::test(flavor = "current_thread")]
113 async fn program_executor_default_impl_runs_via_trait() {
114 let program = Assembler::default()
115 .assemble_program("program", "begin push.3 swap drop end")
116 .unwrap()
117 .unwrap_program();
118
119 let processor = <FastProcessor as ProgramExecutor>::new(
121 StackInputs::default(),
122 AdviceInputs::default(),
123 ExecutionOptions::default(),
124 )
125 .unwrap();
126 let output = <FastProcessor as ProgramExecutor>::execute(
127 processor,
128 &program,
129 &mut DefaultHost::default(),
130 )
131 .await
132 .unwrap();
133
134 assert_eq!(output.stack.get_element(0), Some(crate::Felt::from_u32(3)));
137 }
138
139 #[test]
140 fn program_executor_reports_invalid_advice_inputs() {
141 let advice_inputs =
142 AdviceInputs::default().with_map([(crate::Word::default(), vec![crate::Felt::ONE])]);
143 let options = ExecutionOptions::default().with_max_advice_size_bytes(0);
144
145 let result =
146 <FastProcessor as ProgramExecutor>::new(StackInputs::default(), advice_inputs, options);
147
148 assert!(result.is_err());
149 }
150
151 #[tokio::test(flavor = "current_thread")]
152 async fn program_executor_default_falls_back_when_no_source_node() {
153 let program = Assembler::default()
154 .assemble_program("program", "begin push.3 swap drop end")
155 .unwrap()
156 .unwrap_program();
157
158 let processor = <FastProcessor as ProgramExecutor>::new(
161 StackInputs::default(),
162 AdviceInputs::default(),
163 ExecutionOptions::default(),
164 )
165 .unwrap();
166 let processor = <FastProcessor as ProgramExecutor>::with_debug_info(
167 processor,
168 PackageDebugInfo::default(),
169 );
170 let output = <FastProcessor as ProgramExecutor>::execute(
171 processor,
172 &program,
173 &mut DefaultHost::default(),
174 )
175 .await
176 .unwrap();
177
178 assert_eq!(output.stack.get_element(0), Some(crate::Felt::from_u32(3)));
179 }
180}