regulus 0.0.14

A simple, interpreted language with very simple syntax and zero dependencies
Documentation
/// Declares a group of builtin functions and exports them.
///
/// # Example
/// ```rust
/// use regulus::prelude::*;
/// functions! {
///     /// Length of a list.
///     "len"(1) => |state, args| {
///         let len = args[0].eval_list(state)?.len();
///         Ok(Atom::Int(len as i64))
///     }
///     /// Logical AND.
///     "&&"(2) => |state, args| Ok(Atom::Bool(
///         args[0].eval_bool(state)? &&
///         args[1].eval_bool(state)?
///     ))
///  }
/// ```
///
/// Here, the name before the parens is the function ident,
/// the parens contain the argc (`_` if any number of args is allowed)
/// and the right side is the closure body of the builtin function.
///
/// The macro invocation generates a `pub` function called `functions` that returns
/// `Vec<(&'static str, Function)>`.
#[macro_export]
macro_rules! functions {
    ($(
        $(#[doc = $doc: literal])* $name: literal ($argc: tt) => $callback: expr)
    *) => {
        pub fn functions() -> std::vec::Vec<(&'static str, $crate::prelude::Function)> {
            $(
                $crate::check_nonempty_doc! {
                    $(#[doc = $doc])* $name
                }
            )*
            std::vec![
                $((
                    $name,
                    $crate::prelude::Function::new(
                        [$($doc),*].map(str::trim_start).join("\n"),
                        $crate::make_argc!($argc),
                        $callback,
                    ),
                )),*
            ]
        }
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! check_nonempty_doc {
    ($name: literal) => {
        compile_error!(concat!(
            "builtin function ",
            stringify!($name),
            " has no documentation"
        ));
    };
    ($(#[doc = $doc: literal])* $name: literal) => {};
}

#[macro_export]
#[doc(hidden)]
macro_rules! make_argc {
    (_) => {
        None
    };
    ($num: literal) => {
        Some($num)
    };
}