From 37306989fee8a31b5f510cc7699c8dd0db2929b2 Mon Sep 17 00:00:00 2001 From: Ishan Jain Date: Sun, 26 May 2024 20:12:42 +0530 Subject: [PATCH] added more builtins --- src/evaluator/builtins.rs | 87 ++++++++++++++++++++++++++++++++++++++- src/evaluator/mod.rs | 20 +++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/evaluator/builtins.rs b/src/evaluator/builtins.rs index 2ebb932..e0415a7 100644 --- a/src/evaluator/builtins.rs +++ b/src/evaluator/builtins.rs @@ -1,6 +1,6 @@ use std::{cell::LazyCell, collections::HashMap}; -use super::{BuiltinFunction, Object}; +use super::{Array, BuiltinFunction, Object}; pub const BUILTINS: LazyCell> = LazyCell::new(|| { let mut map = HashMap::new(); @@ -25,5 +25,90 @@ pub const BUILTINS: LazyCell> = LazyCell::new(|| { }), ); + map.insert( + "first", + Object::Builtin(BuiltinFunction { + func: Box::new(|args: Vec| { + if args.len() != 1 { + return Object::Error(format!( + "wrong number of arguments. got={}, want=1", + args.len() + )); + } + + match &args[0] { + Object::Array(s) => s.elements[0].clone(), + v => Object::Error(format!("argument to `len` not supported, got {}", v)), + } + }), + }), + ); + + map.insert( + "last", + Object::Builtin(BuiltinFunction { + func: Box::new(|args: Vec| { + if args.len() != 1 { + return Object::Error(format!( + "wrong number of arguments. got={}, want=1", + args.len() + )); + } + + match &args[0] { + Object::Array(s) => { + let last = s.elements.len(); + s.elements[last - 1].clone() + } + v => Object::Error(format!("argument to `len` not supported, got {}", v)), + } + }), + }), + ); + + map.insert( + "rest", + Object::Builtin(BuiltinFunction { + func: Box::new(|args: Vec| { + if args.len() != 1 { + return Object::Error(format!( + "wrong number of arguments. got={}, want=1", + args.len() + )); + } + + match &args[0] { + Object::Array(s) => Object::Array(Array { + elements: s.elements.iter().skip(1).cloned().collect(), + }), + v => Object::Error(format!("argument to `len` not supported, got {}", v)), + } + }), + }), + ); + + map.insert( + "push", + Object::Builtin(BuiltinFunction { + func: Box::new(|args: Vec| { + if args.len() != 2 { + return Object::Error(format!( + "wrong number of arguments. got={}, want=2", + args.len() + )); + } + + match &args[0] { + Object::Array(s) => { + let mut elements = s.elements.clone(); + elements.push(args[1].clone()); + + Object::Array(Array { elements }) + } + v => Object::Error(format!("argument to `len` not supported, got {}", v)), + } + }), + }), + ); map }); diff --git a/src/evaluator/mod.rs b/src/evaluator/mod.rs index ee1e75c..56bad4b 100644 --- a/src/evaluator/mod.rs +++ b/src/evaluator/mod.rs @@ -467,6 +467,26 @@ mod tests { "wrong number of arguments. got=2, want=1".to_string(), )), ), + ("first([1,2,3,4])", Some(Object::Integer(1))), + ("last([1,2,3,4])", Some(Object::Integer(4))), + ( + "rest([1,2,3,4])", + Some(Object::Array(Array { + elements: vec![Object::Integer(2), Object::Integer(3), Object::Integer(4)], + })), + ), + ( + "push([1,2,3,4])", + Some(Object::Error( + "wrong number of arguments. got=1, want=2".to_string(), + )), + ), + ( + "push([1],5)", + Some(Object::Array(Array { + elements: vec![Object::Integer(1), Object::Integer(5)], + })), + ), ]; run_test_cases(&test_cases);