vyder 0.3.4

Create custom libraries for vyder.
Documentation
use std::process::ExitCode;

use vyder_core::{values, Error, Span, ValueEnum, ValueResult};

pub type Function = fn(&[ValueResult], Span) -> Result<(ValueResult, Option<ExitCode>), Error>;

/// A collection of `Function` and child `Module`'s.
pub struct Module {
    pub(crate) functions: Vec<(String, Function, bool)>,
    pub(crate) modules: Vec<(String, Module)>,
}

impl Module {
    /// Create a `ModuleBuilder` to help make a module.
    pub fn builder() -> ModuleBuilder {
        ModuleBuilder {
            functions: vec![],
            modules: vec![],
        }
    }

    pub fn to_value_enum(&self) -> ValueEnum {
        let mut values = vec![];

        for (identifier, module) in &self.modules {
            values.push((
                values::Str {
                    value: identifier.to_string(),
                }
                .into(),
                module.to_value_enum(),
            ))
        }

        for (identifier, function, can_be_error) in &self.functions {
            values.push((
                values::Str {
                    value: identifier.to_string(),
                }
                .into(),
                values::Callable::Lib {
                    function: *function,
                    can_be_error: *can_be_error,
                }
                .into(),
            ))
        }

        values::Map { values }.into()
    }
}

pub struct ModuleBuilder {
    functions: Vec<(String, Function, bool)>,
    modules: Vec<(String, Module)>,
}

impl ModuleBuilder {
    pub fn build(self) -> Module {
        Module {
            functions: self.functions,
            modules: self.modules,
        }
    }

    pub fn function(mut self, identifier: &str, function: Function, can_be_error: bool) -> Self {
        self.functions
            .push((identifier.to_string(), function, can_be_error));
        self
    }

    pub fn module(mut self, identifier: &str, module: Module) -> Self {
        self.modules.push((identifier.to_string(), module));
        self
    }
}