diff --git a/mute-interpreter/src/env/core.rs b/mute-interpreter/src/env/core.rs index fb751b0..12ef3fd 100644 --- a/mute-interpreter/src/env/core.rs +++ b/mute-interpreter/src/env/core.rs @@ -1,5 +1,5 @@ -use std::borrow::Borrow; use std::collections::HashMap; +use std::{borrow::Borrow, collections::VecDeque}; use super::{macros::arg_count, NativeFunc, Value}; use crate::Node; @@ -139,6 +139,38 @@ pub(super) fn core() -> HashMap { ), // Collections ("list", NativeFunc(Node::List)), + ( + "range", + NativeFunc(|mut args| { + let (min, max) = match args.len() { + 0 => return Node::Error("expected at least 1 argument".to_string()), + 1 => match args.pop_front().expect("argument length checked above") { + Node::Int(max) => (1, (max as usize)), + node => { + return Node::Error(format!("expected int, got {}", node.get_type())) + } + }, + 2 => match (args.pop_front().unwrap(), args.pop_front().unwrap()) { + (Node::Int(min), Node::Int(max)) => (min as usize, max as usize), + (min, max) => { + return Node::Error(format!( + "expected int and int, got {} and {}", + min.get_type(), + max.get_type() + )) + } + }, + count => { + return Node::Error(format!("expected 1 or 2 arguments, got {}", count)) + } + }; + + let list = + VecDeque::from_iter((min..(max + 1)).into_iter().map(|i| Node::Int(i as i64))); + + Node::List(list) + }), + ), ( "list?", NativeFunc(|args| { diff --git a/mute-interpreter/src/evaluator.rs b/mute-interpreter/src/evaluator.rs index 6fd664e..a8685cf 100644 --- a/mute-interpreter/src/evaluator.rs +++ b/mute-interpreter/src/evaluator.rs @@ -359,6 +359,8 @@ mod test { #[case("(empty? (list))", "true")] #[case("(count (list))", "0")] #[case("(count (list 1 2 3))", "3")] + #[case("(range 5)", "(1 2 3 4 5)")] + #[case("(range 6 10)", "(6 7 8 9 10)")] // Vectors #[case("(vector 1 2 3)", "[1 2 3]")] #[case("(vector? [])", "true")]