rust_multistackvm 0.38.0

Stack-based virtual machine on top of rust_multistack crate
Documentation
use crate::multistackvm::{VM, StackOps};
use rust_dynamic::value::Value;
use rust_dynamic::types::*;
use rust_dynamic::math::Ops;
use easy_error::{Error, bail};

fn math_op(vm: &mut VM, value1: Value, value2: Value, op: StackOps, mop: Ops, err_prefix: String) -> Result<&mut VM, Error> {
    match Value::numeric_op(mop, value1, value2) {
        Ok(nvalue) => {
            match op {
                StackOps::FromStack => vm.stack.push(nvalue),
                StackOps::FromWorkBench => vm.stack.push_to_workbench(nvalue),
            };
        }
        Err(err) => {
            bail!("{} returns error: {}", &err_prefix, err);
        }
    }
    Ok(vm)
}

pub fn stdlib_math_op_multiple_inline(vm: &mut VM, depth: usize, op: StackOps, mop: Ops, err_prefix: String) -> Result<&mut VM, Error> {
    match op {
        StackOps::FromStack => {
            if vm.stack.current_stack_len() < depth {
                bail!("Stack is too shallow for inline {}()", &err_prefix);
            }
        }
        StackOps::FromWorkBench => {
            if vm.stack.current_stack_len() < depth {
                bail!("Stack is too shallow for inline {}()", &err_prefix);
            }
            if vm.stack.workbench.len() < 1 {
                bail!("Stack is too shallow for inline {}()", &err_prefix);
            }
        }
    }
    loop {
        let first_operand_value = match op {
            StackOps::FromStack => vm.stack.pull(),
            StackOps::FromWorkBench => vm.stack.pull_from_workbench(),
        };
        match first_operand_value {
            Some(value1) => {
                match vm.stack.pull() {
                    Some(value2) => {
                        if value2.type_of() == NODATA {
                            let _ = match op {
                                StackOps::FromStack => vm.stack.push(value1),
                                StackOps::FromWorkBench => vm.stack.push_to_workbench(value1),
                            };
                            break;
                        }
                        match math_op(vm, value1, value2, op.clone(), mop.clone(), err_prefix.clone()) {
                            Ok(_) => {}
                            Err(err) => {
                                bail!("{}", err);
                            }
                        }
                    }
                    None => {
                        let _ = match op {
                            StackOps::FromStack => vm.stack.push(value1),
                            StackOps::FromWorkBench => vm.stack.push_to_workbench(value1),
                        };
                        break;
                    }
                }
            }
            None => {
                bail!("{} can not get X", &err_prefix);
            }
        }
    }
    Ok(vm)
}

pub fn stdlib_math_op_inline(vm: &mut VM, depth: usize, op: StackOps, mop: Ops, err_prefix: String) -> Result<&mut VM, Error> {
    match op {
        StackOps::FromStack => {
            if vm.stack.current_stack_len() < depth {
                bail!("Stack is too shallow for inline {}()", &err_prefix);
            }
        }
        StackOps::FromWorkBench => {
            if vm.stack.current_stack_len() < depth {
                bail!("Stack is too shallow for inline {}()", &err_prefix);
            }
            if vm.stack.workbench.len() < 1 {
                bail!("Stack is too shallow for inline {}()", &err_prefix);
            }
        }
    }
    let first_operand_value = match op {
        StackOps::FromStack => vm.stack.pull(),
        StackOps::FromWorkBench => vm.stack.pull_from_workbench(),
    };
    let mmop = mop;
    match first_operand_value {
        Some(value1) => {
            match vm.stack.pull() {
                Some(value2) => {
                    match Value::numeric_op(mmop, value1, value2) {
                        Ok(nvalue) => {
                            match op {
                                StackOps::FromStack => vm.stack.push(nvalue),
                                StackOps::FromWorkBench => vm.stack.push_to_workbench(nvalue),
                            };
                        }
                        Err(err) => {
                            bail!("{} returns error: {}", &err_prefix, err);
                        }
                    }
                }
                None => {
                    bail!("{} returns: NO DATA #2", &err_prefix);
                }
            }
        }
        None => {
            bail!("{} returns: NO DATA #1", &err_prefix);
        }
    }
    Ok(vm)
}