From ab20f6e85e7302e8a2df4ed1f5571e5df49547f7 Mon Sep 17 00:00:00 2001 From: Roman Godmaire Date: Tue, 14 May 2024 20:04:35 -0400 Subject: [PATCH] refactor: namespaces(?) And move list functions over there --- mute-interpreter/src/env/core.rs | 193 +--------------------------- mute-interpreter/src/env/list.rs | 200 ++++++++++++++++++++++++++++++ mute-interpreter/src/env/mod.rs | 3 + mute-interpreter/src/evaluator.rs | 46 +++---- mute-parser/src/lexer.rs | 2 +- 5 files changed, 231 insertions(+), 213 deletions(-) create mode 100644 mute-interpreter/src/env/list.rs diff --git a/mute-interpreter/src/env/core.rs b/mute-interpreter/src/env/core.rs index 40333d8..33f173f 100644 --- a/mute-interpreter/src/env/core.rs +++ b/mute-interpreter/src/env/core.rs @@ -1,5 +1,7 @@ -use std::collections::HashMap; -use std::{borrow::Borrow, collections::VecDeque}; +use std::{ + borrow::Borrow, + collections::{HashMap, VecDeque}, +}; use super::{macros::arg_count, NativeFunc, Value}; use crate::Node; @@ -170,18 +172,6 @@ pub(super) fn core() -> HashMap { Node::List(list) }), ), - ( - "list?", - NativeFunc(|args| { - arg_count!(1, args.len()); - - if let Node::List(_list) = args[0].borrow() { - return Node::Boolean(true); - } - - Node::Boolean(false) - }), - ), ("vector", NativeFunc(|args| Node::Vector(args.into()))), ( "vector?", @@ -229,38 +219,6 @@ pub(super) fn core() -> HashMap { Node::Boolean(false) }), ), - ( - "empty?", - NativeFunc(|mut args| { - arg_count!(1, args.len()); - - match args.pop_front().expect("argument length checked above") { - Node::List(list) => Node::Boolean(list.is_empty()), - Node::Vector(vec) => Node::Boolean(vec.is_empty()), - Node::Hashmap(map) => Node::Boolean(map.is_empty()), - arg => Node::Error(format!( - "TypeError: expected list, vector, or hashmap, got {}.", - arg.get_type() - )), - } - }), - ), - ( - "count", - NativeFunc(|mut args| { - arg_count!(1, args.len()); - - match args.pop_front().expect("argument length checked above") { - Node::List(list) => Node::Int(list.len() as i64), - Node::Vector(vec) => Node::Int(vec.len() as i64), - Node::Hashmap(map) => Node::Int(map.len() as i64), - arg => Node::Error(format!( - "TypeError: expected list, vector, or hashmap, got {}.", - arg.get_type() - )), - } - }), - ), // Strings ( "str", @@ -272,149 +230,6 @@ pub(super) fn core() -> HashMap { }), ), // List stuff - ( - "first", - NativeFunc(|args| { - arg_count!(1, args.len()); - - match args[0].borrow() { - Node::List(list) if list.is_empty() => Node::Nil, - Node::Vector(vec) if vec.is_empty() => Node::Nil, - Node::List(list) => list.front().unwrap().clone(), - Node::Vector(vec) => vec.first().unwrap().clone(), - arg => Node::Error(format!( - "TypeError: expected list or vector, got {}.", - arg.get_type() - )), - } - }), - ), - ( - "last", - NativeFunc(|mut args| { - arg_count!(1, args.len()); - - match args.pop_front().expect("argument length checked above") { - Node::List(list) if list.is_empty() => Node::Nil, - Node::Vector(list) if list.is_empty() => Node::Nil, - - Node::List(list) => list.back().unwrap().clone(), - Node::Vector(vec) => vec.last().unwrap().clone(), - arg => Node::Error(format!( - "TypeError: expected list or vector, got {}.", - arg.get_type() - )), - } - }), - ), - ( - "nth", - NativeFunc(|mut args| { - arg_count!(2, args.len()); - - let list = match args.pop_front().expect("argument length checked above") { - Node::List(list) => list, - Node::Vector(vec) => vec.into(), - arg => { - return Node::Error(format!( - "TypeError: expected list or vector, got {}.", - arg.get_type() - )) - } - }; - - let nth = match args.pop_front().expect("argument length checked above") { - Node::Int(val) => val as usize, - Node::Float(val) => val as usize, - arg => { - return Node::Error(format!( - "TypeError: expected int or float, got {}.", - arg.get_type() - )) - } - }; - - if nth < 1 { - return Node::Error(format!("TypeError: expected positive int, got {}", nth)); - } - - list.get(nth - 1).unwrap().clone() - }), - ), - ( - "push-back", - NativeFunc( - |mut args| match args.pop_front().expect("argument length checked above") { - Node::List(mut list) => { - while let Some(val) = args.pop_front() { - list.push_back(val); - } - - Node::List(list) - } - Node::Vector(mut vec) => { - while let Some(val) = args.pop_front() { - vec.push(val); - } - - Node::Vector(vec) - } - arg => Node::Error(format!( - "TypeError: expected list or vector, got {}.", - arg.get_type() - )), - }, - ), - ), - ( - "push-front", - NativeFunc( - |mut args| match args.pop_front().expect("argument length checked above") { - Node::List(mut list) => { - while let Some(val) = args.pop_back() { - list.push_front(val); - } - - Node::List(list) - } - arg => { - Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) - } - }, - ), - ), - ( - "pop-front", - NativeFunc( - |mut args| match args.pop_front().expect("argument length checked above") { - Node::List(mut list) => { - list.pop_front(); - Node::List(list) - } - arg => { - Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) - } - }, - ), - ), - ( - "pop-back", - NativeFunc( - |mut args| match args.pop_front().expect("argument length checked above") { - Node::List(mut list) => { - list.pop_back(); - Node::List(list) - } - Node::Vector(mut vec) => { - vec.pop(); - Node::Vector(vec) - } - arg => { - Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) - } - }, - ), - ), ] .into_iter() .map(|(k, v)| (k.to_string(), Value::NativeFunc(v))) diff --git a/mute-interpreter/src/env/list.rs b/mute-interpreter/src/env/list.rs new file mode 100644 index 0000000..e0b158a --- /dev/null +++ b/mute-interpreter/src/env/list.rs @@ -0,0 +1,200 @@ +use std::borrow::Borrow; +use std::collections::HashMap; + +use super::{macros::arg_count, NativeFunc, Value}; +use crate::Node; + +pub(super) fn lib() -> HashMap { + [ + ( + "list?", + NativeFunc(|args| { + arg_count!(1, args.len()); + + if let Node::List(_list) = args[0].borrow() { + return Node::Boolean(true); + } + + Node::Boolean(false) + }), + ), + ( + "empty?", + NativeFunc(|mut args| { + arg_count!(1, args.len()); + + match args.pop_front().expect("argument length checked above") { + Node::List(list) => Node::Boolean(list.is_empty()), + Node::Vector(vec) => Node::Boolean(vec.is_empty()), + Node::Hashmap(map) => Node::Boolean(map.is_empty()), + arg => Node::Error(format!( + "TypeError: expected list, vector, or hashmap, got {}.", + arg.get_type() + )), + } + }), + ), + ( + "count", + NativeFunc(|mut args| { + arg_count!(1, args.len()); + + match args.pop_front().expect("argument length checked above") { + Node::List(list) => Node::Int(list.len() as i64), + Node::Vector(vec) => Node::Int(vec.len() as i64), + Node::Hashmap(map) => Node::Int(map.len() as i64), + arg => Node::Error(format!( + "TypeError: expected list, vector, or hashmap, got {}.", + arg.get_type() + )), + } + }), + ), + ( + "first", + NativeFunc(|args| { + arg_count!(1, args.len()); + + match args[0].borrow() { + Node::List(list) if list.is_empty() => Node::Nil, + Node::Vector(vec) if vec.is_empty() => Node::Nil, + Node::List(list) => list.front().unwrap().clone(), + Node::Vector(vec) => vec.first().unwrap().clone(), + arg => Node::Error(format!( + "TypeError: expected list or vector, got {}.", + arg.get_type() + )), + } + }), + ), + ( + "last", + NativeFunc(|mut args| { + arg_count!(1, args.len()); + + match args.pop_front().expect("argument length checked above") { + Node::List(list) if list.is_empty() => Node::Nil, + Node::Vector(list) if list.is_empty() => Node::Nil, + + Node::List(list) => list.back().unwrap().clone(), + Node::Vector(vec) => vec.last().unwrap().clone(), + arg => Node::Error(format!( + "TypeError: expected list or vector, got {}.", + arg.get_type() + )), + } + }), + ), + ( + "nth", + NativeFunc(|mut args| { + arg_count!(2, args.len()); + + let list = match args.pop_front().expect("argument length checked above") { + Node::List(list) => list, + Node::Vector(vec) => vec.into(), + arg => { + return Node::Error(format!( + "TypeError: expected list or vector, got {}.", + arg.get_type() + )) + } + }; + + let nth = match args.pop_front().expect("argument length checked above") { + Node::Int(val) => val as usize, + Node::Float(val) => val as usize, + arg => { + return Node::Error(format!( + "TypeError: expected int or float, got {}.", + arg.get_type() + )) + } + }; + + if nth < 1 { + return Node::Error(format!("TypeError: expected positive int, got {}", nth)); + } + + list.get(nth - 1).unwrap().clone() + }), + ), + ( + "push-back", + NativeFunc( + |mut args| match args.pop_front().expect("argument length checked above") { + Node::List(mut list) => { + while let Some(val) = args.pop_front() { + list.push_back(val); + } + + Node::List(list) + } + Node::Vector(mut vec) => { + while let Some(val) = args.pop_front() { + vec.push(val); + } + + Node::Vector(vec) + } + arg => Node::Error(format!( + "TypeError: expected list or vector, got {}.", + arg.get_type() + )), + }, + ), + ), + ( + "push-front", + NativeFunc( + |mut args| match args.pop_front().expect("argument length checked above") { + Node::List(mut list) => { + while let Some(val) = args.pop_back() { + list.push_front(val); + } + + Node::List(list) + } + arg => { + Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) + } + }, + ), + ), + ( + "pop-front", + NativeFunc( + |mut args| match args.pop_front().expect("argument length checked above") { + Node::List(mut list) => { + list.pop_front(); + Node::List(list) + } + arg => { + Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) + } + }, + ), + ), + ( + "pop-back", + NativeFunc( + |mut args| match args.pop_front().expect("argument length checked above") { + Node::List(mut list) => { + list.pop_back(); + Node::List(list) + } + Node::Vector(mut vec) => { + vec.pop(); + Node::Vector(vec) + } + arg => { + Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) + } + }, + ), + ), + ] + .into_iter() + .map(|(k, v)| (format!("List.{k}"), Value::NativeFunc(v))) + .collect() +} diff --git a/mute-interpreter/src/env/mod.rs b/mute-interpreter/src/env/mod.rs index 2da579e..02d7675 100644 --- a/mute-interpreter/src/env/mod.rs +++ b/mute-interpreter/src/env/mod.rs @@ -6,6 +6,7 @@ use crate::Node; mod core; mod io; +mod list; mod macros; mod standard; @@ -74,10 +75,12 @@ impl std::default::Default for Environment { let mut env = HashMap::new(); let core = core::core(); let io = io::io(); + let list = list::lib(); let stdlib = standard::standard(); env.extend(core); env.extend(io); + env.extend(list); env.extend(stdlib); let env = RawEnvironment { diff --git a/mute-interpreter/src/evaluator.rs b/mute-interpreter/src/evaluator.rs index de6794a..1830716 100644 --- a/mute-interpreter/src/evaluator.rs +++ b/mute-interpreter/src/evaluator.rs @@ -456,30 +456,30 @@ mod test { #[case("{:a \"uwu\"}", "{:a: uwu}")] // Lists #[case("(list 1 2 3)", "(1 2 3)")] - #[case("(list? (list))", "true")] - #[case("(list? 23)", "false")] - #[case("(empty? (list 1 2 3))", "false")] - #[case("(empty? (list))", "true")] - #[case("(count (list))", "0")] - #[case("(count (list 1 2 3))", "3")] + #[case("(List.list? (list))", "true")] + #[case("(List.list? 23)", "false")] #[case("(range 5)", "(1 2 3 4 5)")] #[case("(range 6 10)", "(6 7 8 9 10)")] + #[case("(List.empty? (list 1 2 3))", "false")] + #[case("(List.empty? (list))", "true")] + #[case("(List.count (list))", "0")] + #[case("(List.count (list 1 2 3))", "3")] // Vectors #[case("(vector 1 2 3)", "[1 2 3]")] #[case("(vector? [])", "true")] #[case("(vector? 23)", "false")] - #[case("(empty? [1 2 3])", "false")] - #[case("(empty? [])", "true")] - #[case("(count [])", "0")] - #[case("(count [1 2 3])", "3")] + #[case("(List.empty? [1 2 3])", "false")] + #[case("(List.empty? [])", "true")] + #[case("(List.count [])", "0")] + #[case("(List.count [1 2 3])", "3")] // Hashmaps #[case("(hashmap :a 1)", "{:a: 1}")] #[case("(hashmap? {})", "true")] #[case("(hashmap? 23)", "false")] - #[case("(empty? {:a 1})", "false")] - #[case("(empty? {})", "true")] - #[case("(count {})", "0")] - #[case("(count {:a 1})", "1")] + #[case("(List.empty? {:a 1})", "false")] + #[case("(List.empty? {})", "true")] + #[case("(List.count {})", "0")] + #[case("(List.count {:a 1})", "1")] // Environment manipulation #[case("(define (asdf (+ 2 2))) (+ asdf 2)", "6")] #[case("(define (add (fn* (a b) (+ a b)))) (add 1 2)", "3")] @@ -526,15 +526,15 @@ mod test { #[case("(str (+ 1 2))", "3")] #[case("(str (list 1 2 3))", "(1 2 3)")] // List Manipulation - #[case("(first (list 1 2 3))", "1")] - #[case("(last (list 1 2 3))", "3")] - #[case("(nth (list 1 2 3) 2)", "2")] - #[case("(push-front (list 1 2 3) 0)", "(0 1 2 3)")] - #[case("(push-back (list 1 2 3) 4)", "(1 2 3 4)")] - #[case("(pop-front (list 1 2 3))", "(2 3)")] - #[case("(pop-back (list 1 2 3))", "(1 2)")] - #[case("(push-back [1 2 3] 4)", "[1 2 3 4]")] - #[case("(pop-back [1 2 3 4])", "[1 2 3]")] + #[case("(List.first (list 1 2 3))", "1")] + #[case("(List.last (list 1 2 3))", "3")] + #[case("(List.nth (list 1 2 3) 2)", "2")] + #[case("(List.push-front (list 1 2 3) 0)", "(0 1 2 3)")] + #[case("(List.push-back (list 1 2 3) 4)", "(1 2 3 4)")] + #[case("(List.pop-front (list 1 2 3))", "(2 3)")] + #[case("(List.pop-back (list 1 2 3))", "(1 2)")] + #[case("(List.push-back [1 2 3] 4)", "[1 2 3 4]")] + #[case("(List.pop-back [1 2 3 4])", "[1 2 3]")] // Iteration #[case("(map '(1 2 3) (fn* (x) (* x x)))", "(1 4 9)")] #[case("(filter '(1 2 3) (fn* (x) (> x 1)))", "(2 3)")] diff --git a/mute-parser/src/lexer.rs b/mute-parser/src/lexer.rs index 662cd5f..2739f57 100644 --- a/mute-parser/src/lexer.rs +++ b/mute-parser/src/lexer.rs @@ -199,7 +199,7 @@ fn read_int(input: &mut Peekable, first: char) -> Token { } fn read_ident(input: &mut Peekable, first: char) -> Token { - let special_characters = ['!', '?', '*', '-', '_']; + let special_characters = ['!', '?', '*', '-', '_', '.']; let mut raw_ident = vec![first]; while let Some(c) = input.peek() {