From cfa44907065eb10e3b990506881b30c5891f0af2 Mon Sep 17 00:00:00 2001 From: Mica White Date: Sun, 7 Dec 2025 14:25:35 -0500 Subject: First commit --- src/builtins/pairlists.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/builtins/pairlists.rs (limited to 'src/builtins/pairlists.rs') diff --git a/src/builtins/pairlists.rs b/src/builtins/pairlists.rs new file mode 100644 index 0000000..1c18810 --- /dev/null +++ b/src/builtins/pairlists.rs @@ -0,0 +1,66 @@ +use std::sync::Arc; + +use crate::interpreter::{self, Interpreter, Value}; + +pub fn pair(interpreter: &mut Interpreter, args: &[Arc]) -> Arc { + let keys = interpreter + .eval(args[0].clone()) + .list() + .expect("a list of keys"); + let vals = interpreter + .eval(args[1].clone()) + .list() + .expect("a list of values"); + + let pairs = keys + .into_iter() + .zip(vals) + .map(|(key, value)| Arc::new(Value::Pair(key, value))) + .collect::>(); + + interpreter::vec_to_value(&pairs) +} + +fn assoc_inner(key: Arc, pairs: &[Arc]) -> Option> { + let get_value = |pair: &Arc| { + if let Value::Pair(k, v) = &**pair { + (k == &key).then(|| v.clone()) + } else { + None + } + }; + + pairs.iter().filter_map(get_value).next() +} + +pub fn assoc(interpreter: &mut Interpreter, args: &[Arc]) -> Arc { + let key = interpreter.eval(args[0].clone()); + let pairs = interpreter.eval(args[1].clone()).list().expect("a list"); + + assoc_inner(key, &pairs).unwrap() +} + +pub fn sublis(interpreter: &mut Interpreter, args: &[Arc]) -> Arc { + fn sublis_inner(expression: Arc, replacements: &[Arc]) -> Arc { + if let Some(value) = assoc_inner(expression.clone(), replacements) { + return value.clone(); + } + + if let Value::Pair(a, b) = &*expression { + return Arc::new(Value::Pair( + sublis_inner(a.clone(), replacements), + sublis_inner(b.clone(), replacements), + )); + } + + expression + } + + let expression = interpreter.eval(args[1].clone()); + let replacements = interpreter + .eval(args[0].clone()) + .list() + .expect("a list of replacements"); + + sublis_inner(expression, &replacements) +} -- cgit v1.2.3