nyavascript 0.1.0

Lisp implementation. Called NyavaScript because I'm a monster
Documentation
#[cfg(test)]
mod test;

use crate::parse::{ parse, ParseError };
use crate::s_expression::{ SExpressionRef as SXRef, util };
use crate::evaluate::{
    Environment as Env,
    Scope,
    evaluate as eval,
    Result as EvalResult,
};

#[derive(Clone, Debug, PartialEq)]
pub struct LispMacro {
    definition: SXRef,
    args: Vec<String>,
}

impl LispMacro {
    pub fn new(args: Vec<String>, definition: SXRef) -> LispMacro {
        LispMacro {
            definition,
            args,
        }
    }

    pub fn args(&self) -> &Vec<String> {
        &self.args
    }

    pub fn definition(&self) -> SXRef {
        SXRef::clone(&self.definition)
    }

    pub fn execute(&self, args: SXRef, env: &mut Env) -> EvalResult {
        env.push(Scope::new());

        if let Some(key) = self.args().first() {
            env.set(key.to_owned(), args);
        }

        let ret = eval(self.definition(), env);

        env.pop();

        ret
    }
}

impl TryFrom<&str> for LispMacro {
    type Error = ParseError;

    fn try_from(text: &str) -> Result<Self, Self::Error> {
        let ast = parse(text)?;

        Ok(ast.into())
    }
}

impl From<SXRef> for LispMacro {
    fn from(sx: SXRef) -> Self {
        let args = util::car(&util::cdr(&sx)).iter()
            .filter_map(|sx| sx.as_symbol().map(|s| s.into()))
            .collect();

        let definition = util::car(&util::cdr(&util::cdr(&sx)));

        LispMacro::new(args, definition)
    }
}

impl std::fmt::Display for LispMacro {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "[LispMacro]")
    }
}