diff options
| author | Mica White <botahamec@outlook.com> | 2025-12-07 14:25:35 -0500 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2025-12-07 14:25:35 -0500 |
| commit | cfa44907065eb10e3b990506881b30c5891f0af2 (patch) | |
| tree | 90e2b818376a01294c8cc96184171861035c7319 /src/builtins/pairlists.rs | |
Diffstat (limited to 'src/builtins/pairlists.rs')
| -rw-r--r-- | src/builtins/pairlists.rs | 66 |
1 files changed, 66 insertions, 0 deletions
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<Value>]) -> Arc<Value> { + 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::<Box<_>>(); + + interpreter::vec_to_value(&pairs) +} + +fn assoc_inner(key: Arc<Value>, pairs: &[Arc<Value>]) -> Option<Arc<Value>> { + let get_value = |pair: &Arc<Value>| { + 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<Value>]) -> Arc<Value> { + 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<Value>]) -> Arc<Value> { + fn sublis_inner(expression: Arc<Value>, replacements: &[Arc<Value>]) -> Arc<Value> { + 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) +} |
