rust_multistackvm 0.38.0

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

#[derive(Debug, Clone)]
pub enum MoveOps {
    ToStack,
    ToWorkbench,
}

fn stdlib_stack_conditional_move_base(vm: &mut VM, op: MoveOps, err_prefix: String) -> Result<&mut VM, Error> {

    if vm.stack.current_stack_len() < 2 {
        bail!("Stack is too shallow for inline {}()", &err_prefix);
    }
    match vm.stack.pull() {
        Some(lambda_val) => {
            match lambda_val.type_of() {
                LAMBDA => {
                    match vm.lambda_eval(lambda_val) {
                        Ok(_) => {}
                        Err(err) => {
                            bail!("{} lambda returns: {}", &err_prefix, err);
                        }
                    }
                    let outcome = match vm.stack.pull() {
                        Some(outcome) => outcome,
                        None => {
                            bail!("{} returns: NO OUTCOME", &err_prefix);
                        }
                    };
                    let outcome_bool = match outcome.cast_bool() {
                        Ok(outcome_bool) => outcome_bool,
                        Err(err) => {
                            bail!("{} returns: OUTCOME IS NOT BOOLEAN: {}", &err_prefix, err);
                        }
                    };
                    let value = match vm.stack.pull() {
                        Some(value) => value,
                        None => {
                            bail!("{} returns: NO VALUE TO MOVE", &err_prefix);
                        }
                    };
                    if outcome_bool {
                        match op {
                            MoveOps::ToStack => {
                                match vm.stack.pull() {
                                    Some(name_val) => {
                                        match name_val.cast_string() {
                                            Ok(stack_name) => {
                                                vm.stack.push_to_stack(stack_name, value);
                                            }
                                            Err(err) => {
                                                bail!("{} returns: {}", &err_prefix, err);
                                            }
                                        }
                                    }
                                    None => {
                                        bail!("{} returns: NO DATA for stack name", &err_prefix);
                                    }
                                }
                            }
                            MoveOps::ToWorkbench => {
                                vm.stack.push_to_workbench(value);
                            }
                        }
                    }
                }
                _ => {
                    bail!("{} expected to have a LAMBDA at #1", &err_prefix);
                }
            }
        }
        None => {
            bail!("{} returns: NO DATA #1", &err_prefix);
        }
    }
    Ok(vm)
}

pub fn stdlib_stack_conditional_move_to_stack(vm: &mut VM) -> Result<&mut VM, Error> {
    stdlib_stack_conditional_move_base(vm, MoveOps::ToStack, "?MOVE".to_string())
}

pub fn stdlib_stack_conditional_move_to_workbench(vm: &mut VM) -> Result<&mut VM, Error> {
    stdlib_stack_conditional_move_base(vm, MoveOps::ToWorkbench, "?.".to_string())
}

pub fn init_stdlib(vm: &mut VM) {
    let _ = vm.register_inline("?move".to_string(), stdlib_stack_conditional_move_to_stack);
    let _ = vm.register_inline("?.".to_string(), stdlib_stack_conditional_move_to_workbench);
}