miden_testing/
executor.rs1#[cfg(test)]
2use miden_processor::DefaultHost;
3use miden_processor::fast::{ExecutionOutput, FastProcessor};
4use miden_processor::{AdviceInputs, AsyncHost, ExecutionError, Program, StackInputs};
5
6pub(crate) struct CodeExecutor<H> {
11 host: H,
12 stack_inputs: Option<StackInputs>,
13 advice_inputs: AdviceInputs,
14}
15
16impl<H: AsyncHost> CodeExecutor<H> {
17 pub(crate) fn new(host: H) -> Self {
20 Self {
21 host,
22 stack_inputs: None,
23 advice_inputs: AdviceInputs::default(),
24 }
25 }
26
27 pub fn extend_advice_inputs(mut self, advice_inputs: AdviceInputs) -> Self {
28 self.advice_inputs.extend(advice_inputs);
29 self
30 }
31
32 pub fn stack_inputs(mut self, stack_inputs: StackInputs) -> Self {
33 self.stack_inputs = Some(stack_inputs);
34 self
35 }
36
37 #[cfg(test)]
42 pub async fn run(self, code: &str) -> Result<ExecutionOutput, ExecutionError> {
43 use alloc::borrow::ToOwned;
44 use alloc::sync::Arc;
45
46 use miden_lib::transaction::TransactionKernel;
47 use miden_objects::assembly::debuginfo::{SourceLanguage, Uri};
48 use miden_objects::assembly::{DefaultSourceManager, SourceManagerSync};
49
50 let source_manager: Arc<dyn SourceManagerSync> = Arc::new(DefaultSourceManager::default());
51 let assembler = TransactionKernel::with_kernel_library(source_manager.clone());
52
53 let virtual_source_file =
55 source_manager.load(SourceLanguage::Masm, Uri::new("_user_code"), code.to_owned());
56 let program = assembler.assemble_program(virtual_source_file).unwrap();
57
58 self.execute_program(program).await
59 }
60
61 pub async fn execute_program(
66 mut self,
67 program: Program,
68 ) -> Result<ExecutionOutput, ExecutionError> {
69 let stack_inputs =
75 StackInputs::new(self.stack_inputs.unwrap_or_default().iter().copied().collect())
76 .unwrap();
77
78 let processor = FastProcessor::new_debug(stack_inputs.as_slice(), self.advice_inputs);
79
80 let execution_output = processor.execute(&program, &mut self.host).await?;
81
82 Ok(execution_output)
83 }
84}
85
86#[cfg(test)]
87impl CodeExecutor<DefaultHost> {
88 pub fn with_default_host() -> Self {
89 use miden_lib::transaction::TransactionKernel;
90
91 let mut host = DefaultHost::default();
92
93 let test_lib = TransactionKernel::library();
94 host.load_library(test_lib.mast_forest()).unwrap();
95
96 CodeExecutor::new(host)
97 }
98}