#[cfg(test)]
use miden_processor::DefaultHost;
use miden_processor::advice::AdviceInputs;
use miden_processor::{ExecutionOutput, FastProcessor, Host, Program, StackInputs};
#[cfg(test)]
use miden_protocol::assembly::Assembler;
use crate::ExecError;
pub(crate) struct CodeExecutor<H> {
host: H,
stack_inputs: Option<StackInputs>,
advice_inputs: AdviceInputs,
}
impl<H: Host> CodeExecutor<H> {
pub(crate) fn new(host: H) -> Self {
Self {
host,
stack_inputs: None,
advice_inputs: AdviceInputs::default(),
}
}
pub fn extend_advice_inputs(mut self, advice_inputs: AdviceInputs) -> Self {
self.advice_inputs.extend(advice_inputs);
self
}
pub fn stack_inputs(mut self, stack_inputs: StackInputs) -> Self {
self.stack_inputs = Some(stack_inputs);
self
}
#[cfg(test)]
pub async fn run(self, code: &str) -> Result<ExecutionOutput, ExecError> {
use alloc::borrow::ToOwned;
use alloc::sync::Arc;
use miden_protocol::assembly::debuginfo::{SourceLanguage, Uri};
use miden_protocol::assembly::{DefaultSourceManager, SourceManagerSync};
use miden_standards::code_builder::CodeBuilder;
let source_manager: Arc<dyn SourceManagerSync> = Arc::new(DefaultSourceManager::default());
let assembler: Assembler = CodeBuilder::with_kernel_library(source_manager.clone()).into();
let virtual_source_file =
source_manager.load(SourceLanguage::Masm, Uri::new("_user_code"), code.to_owned());
let program = assembler.assemble_program(virtual_source_file).unwrap();
self.execute_program(program).await
}
pub async fn execute_program(mut self, program: Program) -> Result<ExecutionOutput, ExecError> {
let stack_inputs = self.stack_inputs.unwrap_or_default();
let processor = FastProcessor::new(stack_inputs)
.with_advice(self.advice_inputs)
.with_debugging(true);
let execution_output =
processor.execute(&program, &mut self.host).await.map_err(ExecError::new)?;
Ok(execution_output)
}
}
#[cfg(test)]
impl CodeExecutor<DefaultHost> {
pub fn with_default_host() -> Self {
use miden_core_lib::CoreLibrary;
use miden_protocol::ProtocolLib;
use miden_protocol::transaction::TransactionKernel;
use miden_standards::StandardsLib;
let mut host = DefaultHost::default();
let core_lib = CoreLibrary::default();
host.load_library(core_lib.mast_forest()).unwrap();
let standards_lib = StandardsLib::default();
host.load_library(standards_lib.mast_forest()).unwrap();
let protocol_lib = ProtocolLib::default();
host.load_library(protocol_lib.mast_forest()).unwrap();
let kernel_lib = TransactionKernel::library();
host.load_library(kernel_lib.mast_forest()).unwrap();
CodeExecutor::new(host)
}
}