tlisp 0.0.2

Lisp interpreter in Rust
Documentation
use std::{cell::RefCell, collections::HashMap, rc::Rc, vec};

use crate::{environment::Environment, object::Object};

use super::RuntimeFn;

fn unquote(args: &Vec<Object>) -> Object {
  match args.get(0) {
    Some(Object::Quote(o)) => {
      let o = o.clone();

      (*o).clone()
    }
    Some(o) => o.clone(),
    None => Object::Void,
  }
}

fn cdr(args: &Vec<Object>, _env: &mut Rc<RefCell<Environment>>) -> Result<Object, String> {
  let list = unquote(args);

  match list {
    Object::List(list) => {
      let cdr = list.get(1..);

      match cdr {
        Some(cdr) => Ok(Object::List(cdr.to_vec())),
        None => Ok(Object::Void),
      }
    }
    _ => Ok(Object::Void),
  }
}

fn car(args: &Vec<Object>, _env: &mut Rc<RefCell<Environment>>) -> Result<Object, String> {
  let list = unquote(args);

  match list {
    Object::List(list) => {
      let car = list.get(0);

      match car {
        Some(car) => Ok(car.clone()),
        None => Ok(Object::Void),
      }
    }
    _ => Ok(Object::Void),
  }
}

fn cons(args: &Vec<Object>, _env: &mut Rc<RefCell<Environment>>) -> Result<Object, String> {
  let car = args.get(0);
  let cdr = args.get(1);

  let list = match cdr.clone().unwrap_or(&Object::Void) {
    Object::Quote(o) => {
      let o = o.clone();

      (*o).clone()
    }
    o => o.clone(),
  };

  match car {
    Some(car) => match list {
      Object::List(list) => {
        let mut list = list.clone();

        list.insert(0, car.clone());

        Ok(Object::List(list))
      }
      _ => Ok(Object::List(vec![car.clone()])),
    },
    None => Ok(Object::List(vec![])),
  }
}

pub fn load_list_fns(methods: &mut HashMap<String, Rc<RuntimeFn>>) {
  methods.insert("cdr".to_string(), Rc::new(cdr));
  methods.insert("car".to_string(), Rc::new(car));
  methods.insert("cons".to_string(), Rc::new(cons));
}