From 5996af1aea3f96e3bb2ec15e532dc2b864b6f5b0 Mon Sep 17 00:00:00 2001 From: teo3300 Date: Sat, 22 Jun 2024 20:23:24 +0900 Subject: [PATCH] Map/Vector applicaility - Maps and Vectors can be applied as functions, using keys and int as their arguments - Added Identity function - Test before install - added conditional mapping --- Makefile | 2 +- core/core.mal | 4 ++++ libs/lists.mal | 4 ++++ src/env.rs | 26 ++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8534243..f8a5fe2 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,6 @@ conf: mkdir -p ${HOME}/.config/mal/libs cp -f libs/* ${HOME}/.config/mal/libs/ -install: build-release conf +install: build-release test conf sudo cp target/release/rust-mal /usr/local/bin/mal sudo chown ${USER} /usr/local/bin/mal diff --git a/core/core.mal b/core/core.mal index ac47694..e8dbe17 100644 --- a/core/core.mal +++ b/core/core.mal @@ -1,5 +1,9 @@ ;; Previously in core.rs ; Logic + +; Identity function +(def! I (fn* [x] x)) + (def! not (fn* [x] (if x nil true))) diff --git a/libs/lists.mal b/libs/lists.mal index c48a3a7..1928704 100644 --- a/libs/lists.mal +++ b/libs/lists.mal @@ -1,3 +1,7 @@ +(def! map-nil (fn* [v l] + "Map nil values of l to the specified value" + (map-if v nil l))) + (def! concat (fn* [x y] (def! concat-r (fn* [x y t] "Concatenate arguments, keeping their order" (if (car x) diff --git a/src/env.rs b/src/env.rs index 01bacdd..30eb8ec 100644 --- a/src/env.rs +++ b/src/env.rs @@ -110,6 +110,32 @@ pub fn call_func(func: &MalType, args: &[MalType]) -> CallRet { _ => scream!(), } } + M::Map(m) => { + if args.is_empty() { + return Err(MalErr::unrecoverable("No key provided to Map construct")); + } + match &args[0] { + M::Str(s) | M::Key(s) => { + Ok(CallFunc::Builtin(m.get(s).unwrap_or_default().clone())) + } + _ => Err(MalErr::unrecoverable("Map argument must be string or key")), + } + } + M::Vector(v) => { + if args.is_empty() { + return Err(MalErr::unrecoverable("No key provided to Vector construct")); + } + match &args[0] { + M::Int(i) => { + if { 0..v.len() as isize }.contains(i) { + Ok(CallFunc::Builtin(v[*i as usize].clone())) + } else { + Ok(CallFunc::Builtin(M::Nil)) + } + } + _ => Err(MalErr::unrecoverable("Map argument must be string or key")), + } + } _ => Err(MalErr::unrecoverable( format!("{:?} is not a function", prt(func)).as_str(), )),