runmat-vm 0.4.5

RunMat virtual machine and bytecode interpreter
Documentation
#![allow(clippy::result_large_err)]

use futures::executor::block_on;
use runmat_builtins::Value;
use runmat_hir::{HirProgram, LoweringContext, SemanticError};
use runmat_runtime::RuntimeError;

const EXEC_STACK_BYTES: usize = 32 * 1024 * 1024;

fn run_with_stack<T>(f: impl FnOnce() -> T + Send + 'static) -> Result<T, RuntimeError>
where
    T: Send + 'static,
{
    let handle = std::thread::Builder::new()
        .name("runmat-vm-test".to_string())
        .stack_size(EXEC_STACK_BYTES)
        .spawn(f)
        .map_err(|err| RuntimeError::new(format!("failed to spawn test thread: {err}")))?;
    match handle.join() {
        Ok(result) => Ok(result),
        Err(_) => Err(RuntimeError::new("test thread panicked")),
    }
}

pub fn execute(program: &HirProgram) -> Result<Vec<Value>, RuntimeError> {
    let program = program.clone();
    run_with_stack(move || {
        let bc = runmat_vm::compile(&program, &std::collections::HashMap::new())
            .map_err(RuntimeError::from)?;
        block_on(runmat_vm::interpret(&bc))
    })?
}

pub fn lower(program: &runmat_parser::Program) -> Result<HirProgram, SemanticError> {
    runmat_hir::lower(program, &LoweringContext::empty()).map(|result| result.hir)
}

#[allow(dead_code)]
pub fn interpret(bytecode: &runmat_vm::Bytecode) -> Result<Vec<Value>, RuntimeError> {
    let bytecode = bytecode.clone();
    run_with_stack(move || block_on(runmat_vm::interpret(&bytecode)))?
}