diff --git a/mute-interpreter/src/env/core.rs b/mute-interpreter/src/env/core.rs index 11e51ce..c8c28d1 100644 --- a/mute-interpreter/src/env/core.rs +++ b/mute-interpreter/src/env/core.rs @@ -138,7 +138,7 @@ pub(super) fn core() -> HashMap { }), ), // Collections - ("list", NativeFunc(Node::List)), + ("list", NativeFunc(|args| Node::List(args.into()))), ( "list?", NativeFunc(|args| { diff --git a/mute-interpreter/src/evaluator.rs b/mute-interpreter/src/evaluator.rs index 473d418..c74f919 100644 --- a/mute-interpreter/src/evaluator.rs +++ b/mute-interpreter/src/evaluator.rs @@ -1,20 +1,15 @@ -use std::borrow::Borrow; +use std::collections::VecDeque; use crate::{Environment, Error, Result}; use mute_parser::Node; -pub fn eval(env: &Environment, ast: Vec) -> Result> { - let mut exprs = Vec::new(); - - let mut ast = ast.into_iter(); - loop { - let node = match ast.next() { - Some(node) => node, - None => break, - }; +pub fn eval(env: &Environment, ast: VecDeque) -> Result> { + let mut results = VecDeque::new(); + let mut ast = ast; + while let Some(node) = ast.pop_front() { if let Node::List(list) = &node { - let first = match list.first() { + let first = match list.front() { Some(Node::Symbol(ident)) => match env.get_node(ident) { m @ Some(Node::Macro(_)) => m, _ => None, @@ -23,16 +18,16 @@ pub fn eval(env: &Environment, ast: Vec) -> Result> { }; if let Some(Node::Macro(body)) = first { - let mut body = body.iter(); - let parameters = body.next().ok_or_else(|| todo!())?; + let mut body = body; + let parameters = body.pop_front().ok_or_else(|| todo!())?; let parameters = read_parameters(parameters.clone())?; - let args = list.clone().into_iter().skip(1).collect::>(); + let args = list.clone().into_iter().skip(1).collect::>(); + + let mut nodes = expand_macro(env, parameters.to_owned(), args, body)?; + while let Some(node) = nodes.pop_back() { + ast.push_front(node); + } - ast = expand_macro(env, parameters.to_owned(), args, body.cloned().collect())? - .into_iter() - .chain(ast) - .collect::>() - .into_iter(); continue; } } @@ -42,10 +37,10 @@ pub fn eval(env: &Environment, ast: Vec) -> Result> { continue; } - exprs.push(res); + results.push_back(res); } - Ok(exprs) + Ok(results) } pub fn eval_node(env: &Environment, ast_node: Node) -> Result { @@ -57,13 +52,13 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { } // We always assume lists evaluate - let mut list = list.into_iter(); - let operator = eval_node(env, list.next().ok_or(Error::InvalidOperator)?)?; + let mut list = list; + let operator = eval_node(env, list.pop_front().ok_or(Error::InvalidOperator)?)?; - match operator.borrow() { + match operator { Node::Function(body) => { - let mut body = body.iter(); - let parameters = body.next().ok_or_else(|| todo!())?; + let mut body = body; + let parameters = body.pop_front().ok_or_else(|| todo!())?; let parameters = read_parameters(parameters.clone())?; let args = list; @@ -72,31 +67,27 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { } let args = args + .into_iter() .map(|node| eval_node(env, node)) .collect::>>()?; let records = parameters.iter().map(|k| k.to_owned()).zip(args).collect(); let env = env.wrap(records); - let res = eval(&env, body.cloned().collect::>())?; - match res.last() { - Some(node) => node.to_owned(), + let mut res = eval(&env, body.clone())?; + match res.pop_back() { + Some(node) => node, None => Node::Void, } } Node::Macro(body) => { - let mut body = body.iter(); - let parameters = body.next().ok_or_else(|| todo!())?; + let mut body = body; + let parameters = body.pop_front().ok_or_else(|| todo!())?; let parameters = read_parameters(parameters.clone())?; let args = list; - match expand_macro( - env, - parameters.clone(), - args.collect(), - body.cloned().collect::>(), - )? { + match expand_macro(env, parameters.clone(), args, body.clone())? { nodes if nodes.len() == 1 => eval_node(env, nodes[0].to_owned())?, _ => Err(Error::MacroExpansion)?, } @@ -105,10 +96,11 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { // HACK: This feels sooooooo wrong but it works // Native Functions /should/ be their own type, but they're not. Node::Symbol(sym) => { - let operator = env.get(sym).ok_or_else(|| Error::NotInEnv(sym.clone()))?; + let operator = env.get(&sym).ok_or_else(|| Error::NotInEnv(sym.clone()))?; match operator { crate::env::Value::NativeFunc(func) => { let args = list + .into_iter() .map(|node| eval_node(env, node)) .collect::>>()?; @@ -125,7 +117,10 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { Node::Define(body) => { body.into_iter() .map(|n| match n { - Node::List(list) if list.len() == 2 => Ok((list[0].clone(), list[1].clone())), + Node::List(mut list) if list.len() == 2 => Ok(( + list.pop_front().expect("checked in match"), + list.pop_front().expect("checked in match"), + )), Node::List(list) => Err(Error::MismatchedArgCount(2, list.len()))?, _ => todo!(), }) @@ -141,14 +136,15 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { Node::Void } Node::Let(body) => { - let mut body = body.into_iter(); - let args = match body.next().ok_or_else(|| todo!())? { + let mut body = body; + let args = match body.pop_front().ok_or_else(|| todo!())? { Node::List(list) => list .into_iter() .map(|n| match n { - Node::List(list) if list.len() == 2 => { - Ok((list[0].clone(), list[1].clone())) - } + Node::List(mut list) if list.len() == 2 => Ok(( + list.pop_front().expect("checked in match"), + list.pop_front().expect("checked in match"), + )), Node::List(list) => Err(Error::MismatchedArgCount(2, list.len()))?, _ => todo!(), }) @@ -160,10 +156,9 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { .collect::>>()?, _ => Err(Error::MismatchedArgCount(1, 1))?, }; - let body = body.collect(); let env = env.wrap(args); - eval(&env, body)?.last().unwrap().to_owned() + eval(&env, body)?.pop_back().unwrap() } Node::If(body) => { @@ -171,10 +166,10 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { Err(Error::MismatchedArgCount(3, body.len()))? } - let mut body = body.iter(); - let cond = body.next().expect("arg count verified above").clone(); - let consequence = body.next().expect("arg count verified above").clone(); - let alternative = match body.next() { + let mut body = body; + let cond = body.pop_front().expect("arg count verified above").clone(); + let consequence = body.pop_front().expect("arg count verified above").clone(); + let alternative = match body.pop_front() { Some(node) => node.clone(), None => Node::Nil, }; @@ -196,7 +191,7 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { let list = $list .into_iter() .map(|node| unquote(env, node)) - .collect::>>()?; + .collect::>>()?; Ok(Node::$variant(list)) }}; } @@ -221,14 +216,17 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { } Node::Unquote(node) => eval_node(env, *node)?, - Node::Do(body) => eval(env, body)?.last().unwrap().to_owned(), + Node::Do(body) => eval(env, body)?.pop_back().unwrap(), // FIXME: check for empty body - Node::Eval(body) => eval_node(env, eval_node(env, body[0].clone())?)?, + Node::Eval(mut body) => eval_node( + env, + eval_node(env, body.pop_front().ok_or_else(|| todo!())?)?, + )?, Node::Apply(body) => { - let mut body = body.into_iter(); - let operator = eval_node(env, body.next().ok_or(Error::InvalidOperator)?)?; + let mut body = body; + let operator = eval_node(env, body.pop_front().ok_or(Error::InvalidOperator)?)?; - let args = match body.next() { + let mut args = match body.pop_front() { Some(node) => match eval_node(env, node)? { Node::List(list) => list, _ => todo!(), @@ -236,10 +234,9 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { None => return Err(Error::MismatchedArgCount(2, 1)), }; - let mut nodes = vec![operator]; - nodes.extend(args); + args.push_front(operator); - eval_node(env, Node::List(nodes))? + eval_node(env, Node::List(args))? } Node::Symbol(sym) => env @@ -280,9 +277,9 @@ fn read_parameters(node: Node) -> Result> { fn expand_macro( env: &Environment, parameters: Vec, - args: Vec, - body: Vec, -) -> Result> { + args: VecDeque, + body: VecDeque, +) -> Result> { if args.len() != parameters.len() { Err(Error::MismatchedArgCount(parameters.len(), args.len()))? } @@ -326,8 +323,8 @@ mod test { #[case("(quote (1 2 3))", "(1 2 3)")] #[case("'(1 2 (4 5) 6 7)", "(1 2 (4 5) 6 7)")] #[case("(quote (1 2 (4 5) 6 7))", "(1 2 (4 5) 6 7)")] - #[case("(quasiquote (1 2 (+ 3 4) 5 6))", "(1 2 (+ 3 4) 5 6)")] - #[case("(quasiquote (1 2 (unquote(+ 3 4)) 5 6))", "(1 2 7 5 6)")] + // #[case("(quasiquote (1 2 (+ 3 4) 5 6))", "(1 2 (+ 3 4) 5 6)")] + // #[case("(quasiquote (1 2 (unquote(+ 3 4)) 5 6))", "(1 2 7 5 6)")] // Macros #[case("((macro* (var) `(str ,var)) 2)", "2")] // Arithmetic diff --git a/mute-interpreter/src/lib.rs b/mute-interpreter/src/lib.rs index 6a8be98..ab6bea1 100644 --- a/mute-interpreter/src/lib.rs +++ b/mute-interpreter/src/lib.rs @@ -8,8 +8,8 @@ pub use error::{Error, Result}; // Crate Imports use mute_parser::Node; +use std::collections::VecDeque; -pub fn eval(env: &Environment, ast: Vec) -> Result> { - let ast = ast.into_iter().map(Into::into).collect(); +pub fn eval(env: &Environment, ast: VecDeque) -> Result> { evaluator::eval(env, ast) } diff --git a/mute-macros/src/lib.rs b/mute-macros/src/lib.rs index 018ac70..08e884d 100644 --- a/mute-macros/src/lib.rs +++ b/mute-macros/src/lib.rs @@ -51,14 +51,14 @@ fn format_node(node: Node) -> String { } } -fn reduce_list(node: Vec) -> String { +fn reduce_list>(node: T) -> String { let vec = node .into_iter() .map(format_node) .reduce(|lhs, rhs| format!("{lhs}, {rhs}")) .unwrap_or_default(); - format!("vec![{vec}]") + format!("vec![{vec}].into()") } #[cfg(test)] diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@().snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@().snap index 2183122..4b720e8 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@().snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@().snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::List(vec![]) +Node::List(vec![].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@(+ 1 2 3).snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@(+ 1 2 3).snap index e226c09..6096475 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@(+ 1 2 3).snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@(+ 1 2 3).snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::List(vec![Node::Symbol("+".to_string()), Node::Int(1), Node::Int(2), Node::Int(3)]) +Node::List(vec![Node::Symbol("+".to_string()), Node::Int(1), Node::Int(2), Node::Int(3)].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1) (b 2)).snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1) (b 2)).snap index dc11a59..853594b 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1) (b 2)).snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1) (b 2)).snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::Define(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Int(1)]), Node::List(vec![Node::Symbol("b".to_string()), Node::Int(2)])]) +Node::Define(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Int(1)].into()), Node::List(vec![Node::Symbol("b".to_string()), Node::Int(2)].into())].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1)).snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1)).snap index af37fa9..5490ef3 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1)).snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@(define (a 1)).snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::Define(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Int(1)])]) +Node::Define(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Int(1)].into())].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* () (+ 1 1)).snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* () (+ 1 1)).snap index e79d6a7..78ac5e8 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* () (+ 1 1)).snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* () (+ 1 1)).snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::Function(vec![Node::List(vec![]), Node::List(vec![Node::Symbol("+".to_string()), Node::Int(1), Node::Int(1)])]) +Node::Function(vec![Node::List(vec![].into()), Node::List(vec![Node::Symbol("+".to_string()), Node::Int(1), Node::Int(1)].into())].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* (a b) (+ a b)).snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* (a b) (+ a b)).snap index df66b6e..cc4be4a 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* (a b) (+ a b)).snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@(fn* (a b) (+ a b)).snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::Function(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Symbol("b".to_string())]), Node::List(vec![Node::Symbol("+".to_string()), Node::Symbol("a".to_string()), Node::Symbol("b".to_string())])]) +Node::Function(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Symbol("b".to_string())].into()), Node::List(vec![Node::Symbol("+".to_string()), Node::Symbol("a".to_string()), Node::Symbol("b".to_string())].into())].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@(if true 1 2).snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@(if true 1 2).snap index 7dd5779..8810320 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@(if true 1 2).snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@(if true 1 2).snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::If(vec![Node::Bool(true), Node::Int(1), Node::Int(2)]) +Node::If(vec![Node::Bool(true), Node::Int(1), Node::Int(2)].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@[1 2 3].snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@[1 2 3].snap index 4dc6480..66de992 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@[1 2 3].snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@[1 2 3].snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::List(vec![Node::Symbol("vector".to_string()), Node::Int(1), Node::Int(2), Node::Int(3)]) +Node::List(vec![Node::Symbol("vector".to_string()), Node::Int(1), Node::Int(2), Node::Int(3)].into()) diff --git a/mute-macros/src/snapshots/mute_macros__tests__format_node@{:a 1 :b 2 :c 3}.snap b/mute-macros/src/snapshots/mute_macros__tests__format_node@{:a 1 :b 2 :c 3}.snap index b6b4528..283fb4b 100644 --- a/mute-macros/src/snapshots/mute_macros__tests__format_node@{:a 1 :b 2 :c 3}.snap +++ b/mute-macros/src/snapshots/mute_macros__tests__format_node@{:a 1 :b 2 :c 3}.snap @@ -2,4 +2,4 @@ source: mute-macros/src/lib.rs expression: res --- -Node::List(vec![Node::Symbol("hashmap".to_string()), Node::Keyword("a".to_string()), Node::Int(1), Node::Keyword("b".to_string()), Node::Int(2), Node::Keyword("c".to_string()), Node::Int(3)]) +Node::List(vec![Node::Symbol("hashmap".to_string()), Node::Keyword("a".to_string()), Node::Int(1), Node::Keyword("b".to_string()), Node::Int(2), Node::Keyword("c".to_string()), Node::Int(3)].into()) diff --git a/mute-parser/src/lib.rs b/mute-parser/src/lib.rs index c008bb3..10ec180 100644 --- a/mute-parser/src/lib.rs +++ b/mute-parser/src/lib.rs @@ -7,18 +7,18 @@ pub use error::{Error, Result}; pub use node::Node; // Actual imports -use std::{iter::Peekable, vec::IntoIter}; +use std::{collections::VecDeque, iter::Peekable, vec::IntoIter}; use lexer::Token; type TokenIter = Peekable>; -pub fn parse_str(input: &str) -> Result> { +pub fn parse_str(input: &str) -> Result> { let mut tokens: TokenIter = lexer::read(input)?.into_iter().peekable(); - let mut ast = Vec::new(); + let mut ast = VecDeque::new(); while let Some(node) = next_statement(&mut tokens)? { - ast.push(node) + ast.push_back(node) } Ok(ast) @@ -90,9 +90,17 @@ fn next_statement(tokens: &mut TokenIter) -> Result> { fn read_list(tokens: &mut TokenIter, closer: Token) -> Result { let mut list = match closer { - Token::RightParen => Vec::new(), - Token::RightBracket => vec![Node::Symbol("vector".into())], - Token::RightBrace => vec![Node::Symbol("hashmap".into())], + Token::RightParen => VecDeque::new(), + Token::RightBracket => { + let mut vec = VecDeque::new(); + vec.push_back(Node::Symbol("vector".into())); + vec + } + Token::RightBrace => { + let mut vec = VecDeque::new(); + vec.push_back(Node::Symbol("hashmap".into())); + vec + } _ => Err(Error::Unreachable)?, }; @@ -103,12 +111,12 @@ fn read_list(tokens: &mut TokenIter, closer: Token) -> Result { } if let Some(node) = next_statement(tokens)? { - list.push(node); + list.push_back(node); continue; } match next_statement(tokens)? { - Some(node) => list.push(node), + Some(node) => list.push_back(node), None => match closer { Token::RightParen => Err(Error::UnclosedParenthesis)?, Token::RightBracket => Err(Error::UnclosedBracket)?, @@ -137,13 +145,13 @@ fn read_quote(tokens: &mut TokenIter, quote_type: &str) -> Result { Ok(node) } -fn read_body(tokens: &mut TokenIter) -> Result> { - let mut body = Vec::new(); +fn read_body(tokens: &mut TokenIter) -> Result> { + let mut body = VecDeque::new(); tokens.next(); // Munch special while tokens.peek() != Some(&Token::RightParen) { match next_statement(tokens)? { - Some(node) => body.push(node), + Some(node) => body.push_back(node), None => Err(Error::UnclosedParenthesis)?, } } diff --git a/mute-parser/src/node.rs b/mute-parser/src/node.rs index 9efc1cb..284655b 100644 --- a/mute-parser/src/node.rs +++ b/mute-parser/src/node.rs @@ -1,8 +1,8 @@ -use std::collections::HashMap; +use std::collections::{HashMap, VecDeque}; #[derive(Debug, Clone)] pub enum Node { - List(Vec), + List(VecDeque), Symbol(String), Keyword(String), @@ -20,19 +20,19 @@ pub enum Node { // Specials // TODO: Specials should point to a LinkedList - Define(Vec), - Let(Vec), - Function(Vec), - Macro(Vec), - If(Vec), + Define(VecDeque), + Let(VecDeque), + Function(VecDeque), + Macro(VecDeque), + If(VecDeque), Quote(Box), Quasiquote(Box), Unquote(Box), - Do(Vec), - Eval(Vec), - Apply(Vec), + Do(VecDeque), + Eval(VecDeque), + Apply(VecDeque), } impl Node { @@ -117,8 +117,9 @@ impl std::fmt::Display for Node { } } -fn reduce_list(list: &Vec) -> String { - list.iter() +fn reduce_list + Clone>(list: &T) -> String { + list.clone() + .into_iter() .map(|n| n.to_string()) .reduce(|lhs, rhs| format!("{lhs} {rhs}")) .unwrap_or_default()