summaryrefslogtreecommitdiff
path: root/src/builtins.rs
blob: 201cd895f4272b6756c744a2d49e9ed0014fe4fc (plain)
use std::sync::{Arc, LazyLock};

use crate::interpreter::{self, Interpreter, Value, wrap_in_quote};

mod lists;
mod numbers;
mod pairlists;

pub use lists::*;
pub use numbers::*;
pub use pairlists::*;

pub static T: LazyLock<Arc<Value>> = LazyLock::new(|| Arc::new(Value::Identifier("T".into())));
pub static F: LazyLock<Arc<Value>> = LazyLock::new(|| Arc::new(Value::Identifier("F".into())));
pub static NIL: LazyLock<Arc<Value>> = LazyLock::new(|| Arc::new(Value::Identifier("NIL".into())));

fn delsh_bool(value: bool) -> Arc<Value> {
	match value {
		true => T.clone(),
		false => NIL.clone(),
	}
}

pub fn quote(_interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	args[0].clone()
}

pub fn eval(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let form = interpreter.eval(args[0].clone());
	let variables = args
		.get(1)
		.map(|value| interpreter.eval(value.clone()).list().expect("a pair list"));

	interpreter.push_frame();

	if let Some(variables) = variables {
		for variable in variables {
			let Some((name, value)) = variable.pair() else {
				continue;
			};
			let Some(name) = name.string() else {
				continue;
			};
			interpreter.set_atom(name.clone(), value.clone());
		}
	}

	let result = interpreter.eval(form);

	interpreter.pop_frame();
	result
}

pub fn apply(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let function = interpreter.eval(args[0].clone());
	let arguments = interpreter
		.eval(args[1].clone())
		.list()
		.expect("a list of arguments")
		.into_iter()
		.map(wrap_in_quote)
		.collect::<Box<_>>();
	let variables = args.get(2).map(|value| {
		interpreter
			.eval(value.clone())
			.list()
			.expect("a list of variables")
	});

	interpreter.push_frame();

	if let Some(variables) = variables {
		for variable in variables {
			let Some((name, value)) = variable.pair() else {
				continue;
			};
			let Some(name) = name.string() else {
				continue;
			};
			interpreter.set_atom(name.clone(), value.clone());
		}
	}

	let result = interpreter.run_function(&function, &arguments);

	interpreter.pop_frame();
	result
}

pub fn define(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let definitions = args[0].list().expect("a list of definitions");
	for definition in definitions {
		let pair = definition.list().expect("a name-value pair");
		let Some(name) = pair[0].string() else {
			continue;
		};

		let value = interpreter.eval(pair[1].clone());
		interpreter.set_atom(name.clone(), value);
	}

	NIL.clone()
}

pub fn set(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let lhs = args[0]
		.identifier()
		.expect("an identifier on the left side");
	let rhs = interpreter.eval(args[1].clone());
	interpreter.set_atom(lhs.clone(), rhs.clone());

	rhs
}

pub fn lambda(_interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	Arc::new(Value::DelshFn {
		args: args[0]
			.list()
			.expect("a list of argument names")
			.into_iter()
			.filter_map(|value| value.identifier().cloned())
			.collect(),
		command: args[1].clone(),
	})
}

pub fn defun(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let Value::Identifier(function_name) = &*args[0] else {
		return NIL.clone();
	};

	let function = Value::DelshFn {
		args: args[1]
			.list()
			.expect("a list of parameter names")
			.into_iter()
			.filter_map(|value| value.identifier().cloned())
			.collect(),
		command: args[2].clone(),
	};

	let function = Arc::new(function);
	interpreter.set_atom(function_name.clone(), function.clone());
	function
}

pub fn do_function(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let Some(last_arg) = args.last() else {
		return NIL.clone();
	};

	for arg in &args[..args.len() - 1] {
		interpreter.eval(arg.clone());
	}

	interpreter.eval(last_arg.clone())
}

pub fn if_function(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let condition = interpreter.eval(args[0].clone());
	let if_block = args[1].clone();
	let else_block = args[2].clone();

	if condition != *NIL {
		interpreter.eval(if_block)
	} else {
		interpreter.eval(else_block)
	}
}

pub fn cond_function(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	for case in args {
		let case = case.list().expect("a list of cases");
		let condition = interpreter.eval(case[0].clone());
		if condition != *NIL {
			let mut result = NIL.clone();
			for command in &case[1..] {
				result = interpreter.eval(command.clone());
			}
			return result;
		}
	}

	NIL.clone()
}

pub fn while_function(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let condition = args[0].clone();
	let while_block = args[1].clone();

	while interpreter.eval(condition.clone()) != NIL.clone() {
		interpreter.eval(while_block.clone());
	}

	NIL.clone()
}

pub fn loop_function(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let expression = args[0].clone();

	loop {
		interpreter.eval(expression.clone());
	}
}

pub fn cons(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	Arc::new(Value::Pair(
		interpreter.eval(args[0].clone()),
		interpreter.eval(args[1].clone()),
	))
}

pub fn ff(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	fn ff_inner(arg: Arc<Value>) -> Arc<Value> {
		if let Value::Pair(a, _b) = &*arg {
			ff_inner(a.clone())
		} else {
			arg
		}
	}

	ff_inner(interpreter.eval(args[0].clone()))
}

pub fn subst(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	fn subst_inner(replacement: Arc<Value>, pattern: Arc<Value>, full: Arc<Value>) -> Arc<Value> {
		if full == pattern {
			return replacement;
		}

		if let Value::Pair(a, b) = &*full {
			return Arc::new(Value::Pair(
				subst_inner(replacement.clone(), pattern.clone(), a.clone()),
				subst_inner(replacement, pattern, b.clone()),
			));
		}

		full
	}

	let arg1 = interpreter.eval(args[0].clone());
	let arg2 = interpreter.eval(args[1].clone());
	let arg3 = interpreter.eval(args[2].clone());

	subst_inner(arg1, arg2, arg3)
}

pub fn is_atom(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	match &*interpreter.eval(args[0].clone()) {
		Value::Identifier(_) => T.clone(),
		Value::Number(_) => T.clone(),
		Value::String(_) => T.clone(),
		Value::RustFn(_) => T.clone(),
		Value::DelshFn { .. } => T.clone(),
		Value::Pair(..) => NIL.clone(),
	}
}

pub fn is_nil(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let x = interpreter.eval(args[0].clone());

	delsh_bool(x == *NIL)
}

pub fn maplist(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	let list = interpreter.eval(args[0].clone()).list().expect("a list");
	let mapper = interpreter.eval(args[1].clone());

	let mapped = list
		.into_iter()
		.map(|i| interpreter.run_function(&mapper, &[i]))
		.collect::<Box<_>>();
	interpreter::vec_to_value(&mapped)
}

pub fn and(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	for arg in args {
		let arg = interpreter.eval(arg.clone());
		if arg != *NIL {
			return arg;
		}
	}

	NIL.clone()
}

pub fn or(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	for arg in args {
		let arg = interpreter.eval(arg.clone());
		if arg == *NIL {
			return arg;
		}
	}

	NIL.clone()
}

pub fn not(interpreter: &mut Interpreter, args: &[Arc<Value>]) -> Arc<Value> {
	is_nil(interpreter, args)
}