refactor: remove mutable reassignment

This commit is contained in:
Roman Godmaire 2024-05-14 11:50:01 -04:00
parent ed86c884ec
commit a7c6e1a07d
2 changed files with 31 additions and 46 deletions

View file

@ -26,12 +26,11 @@ macro_rules! arithmetic {
macro_rules! ordering { macro_rules! ordering {
($operator:tt) => { ($operator:tt) => {
NativeFunc(|args| { NativeFunc(|mut args| {
arg_count!(2, args.len()); arg_count!(2, args.len());
let mut args = args.into_iter(); let lhs = args.pop_front().unwrap();
let lhs = args.next().unwrap(); let rhs = args.pop_front().unwrap();
let rhs = args.next().unwrap();
let res = match (lhs, rhs) { let res = match (lhs, rhs) {
(Node::Int(lhs), Node::Int(rhs)) => lhs $operator rhs, (Node::Int(lhs), Node::Int(rhs)) => lhs $operator rhs,
@ -232,9 +231,8 @@ pub(super) fn core() -> HashMap<String, Value> {
), ),
( (
"empty?", "empty?",
NativeFunc(|args| { NativeFunc(|mut args| {
arg_count!(1, args.len()); arg_count!(1, args.len());
let mut args = args;
match args.pop_front().expect("argument length checked above") { match args.pop_front().expect("argument length checked above") {
Node::List(list) => Node::Boolean(list.is_empty()), Node::List(list) => Node::Boolean(list.is_empty()),
@ -249,9 +247,8 @@ pub(super) fn core() -> HashMap<String, Value> {
), ),
( (
"count", "count",
NativeFunc(|args| { NativeFunc(|mut args| {
arg_count!(1, args.len()); arg_count!(1, args.len());
let mut args = args;
match args.pop_front().expect("argument length checked above") { match args.pop_front().expect("argument length checked above") {
Node::List(list) => Node::Int(list.len() as i64), Node::List(list) => Node::Int(list.len() as i64),
@ -294,10 +291,10 @@ pub(super) fn core() -> HashMap<String, Value> {
), ),
( (
"last", "last",
NativeFunc(|args| { NativeFunc(|mut args| {
arg_count!(1, args.len()); arg_count!(1, args.len());
match args[0].borrow() { match args.pop_front().expect("argument length checked above") {
Node::List(list) if list.is_empty() => Node::Nil, Node::List(list) if list.is_empty() => Node::Nil,
Node::Vector(list) if list.is_empty() => Node::Nil, Node::Vector(list) if list.is_empty() => Node::Nil,
@ -312,10 +309,9 @@ pub(super) fn core() -> HashMap<String, Value> {
), ),
( (
"nth", "nth",
NativeFunc(|args| { NativeFunc(|mut args| {
arg_count!(2, args.len()); arg_count!(2, args.len());
let mut args = args;
let list = match args.pop_front().expect("argument length checked above") { let list = match args.pop_front().expect("argument length checked above") {
Node::List(list) => list, Node::List(list) => list,
Node::Vector(vec) => vec.into(), Node::Vector(vec) => vec.into(),
@ -343,9 +339,8 @@ pub(super) fn core() -> HashMap<String, Value> {
), ),
( (
"push-back", "push-back",
NativeFunc(|args| { NativeFunc(
let mut args = args; |mut args| match args.pop_front().expect("argument length checked above") {
match args.pop_front().expect("argument length checked above") {
Node::List(mut list) => { Node::List(mut list) => {
while let Some(val) = args.pop_front() { while let Some(val) = args.pop_front() {
list.push_back(val); list.push_back(val);
@ -364,14 +359,13 @@ pub(super) fn core() -> HashMap<String, Value> {
"TypeError: expected list or vector, got {}.", "TypeError: expected list or vector, got {}.",
arg.get_type() arg.get_type()
)), )),
} },
}), ),
), ),
( (
"push-front", "push-front",
NativeFunc(|args| { NativeFunc(
let mut args = args; |mut args| match args.pop_front().expect("argument length checked above") {
match args.pop_front().expect("argument length checked above") {
Node::List(mut list) => { Node::List(mut list) => {
while let Some(val) = args.pop_back() { while let Some(val) = args.pop_back() {
list.push_front(val); list.push_front(val);
@ -382,14 +376,13 @@ pub(super) fn core() -> HashMap<String, Value> {
arg => { arg => {
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
} }
} },
}), ),
), ),
( (
"pop-front", "pop-front",
NativeFunc(|args| { NativeFunc(
let mut args = args; |mut args| match args.pop_front().expect("argument length checked above") {
match args.pop_front().expect("argument length checked above") {
Node::List(mut list) => { Node::List(mut list) => {
list.pop_front(); list.pop_front();
Node::List(list) Node::List(list)
@ -397,14 +390,13 @@ pub(super) fn core() -> HashMap<String, Value> {
arg => { arg => {
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
} }
} },
}), ),
), ),
( (
"pop-back", "pop-back",
NativeFunc(|args| { NativeFunc(
let mut args = args; |mut args| match args.pop_front().expect("argument length checked above") {
match args.pop_front().expect("argument length checked above") {
Node::List(mut list) => { Node::List(mut list) => {
list.pop_back(); list.pop_back();
Node::List(list) Node::List(list)
@ -416,8 +408,8 @@ pub(super) fn core() -> HashMap<String, Value> {
arg => { arg => {
Node::Error(format!("TypeError: expected list, got {}.", arg.get_type())) Node::Error(format!("TypeError: expected list, got {}.", arg.get_type()))
} }
} },
}), ),
), ),
] ]
.into_iter() .into_iter()

View file

@ -3,10 +3,9 @@ use std::collections::VecDeque;
use crate::{Environment, Error, Result}; use crate::{Environment, Error, Result};
use mute_parser::Node; use mute_parser::Node;
pub fn eval(env: &Environment, ast: VecDeque<Node>) -> Result<VecDeque<Node>> { pub fn eval(env: &Environment, mut ast: VecDeque<Node>) -> Result<VecDeque<Node>> {
let mut results = VecDeque::new(); let mut results = VecDeque::new();
let mut ast = ast;
while let Some(node) = ast.pop_front() { while let Some(node) = ast.pop_front() {
if let Node::List(list) = &node { if let Node::List(list) = &node {
let first = match list.front() { let first = match list.front() {
@ -17,8 +16,7 @@ pub fn eval(env: &Environment, ast: VecDeque<Node>) -> Result<VecDeque<Node>> {
node => node.cloned(), node => node.cloned(),
}; };
if let Some(Node::Macro(body)) = first { if let Some(Node::Macro(mut body)) = first {
let mut body = body;
let parameters = body.pop_front().ok_or_else(|| todo!())?; let parameters = body.pop_front().ok_or_else(|| todo!())?;
let parameters = read_parameters(parameters.clone())?; let parameters = read_parameters(parameters.clone())?;
let args = list.clone().into_iter().skip(1).collect::<VecDeque<Node>>(); let args = list.clone().into_iter().skip(1).collect::<VecDeque<Node>>();
@ -56,8 +54,7 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
let operator = eval_node(env, list.pop_front().ok_or(Error::InvalidOperator)?)?; let operator = eval_node(env, list.pop_front().ok_or(Error::InvalidOperator)?)?;
match operator { match operator {
Node::Function(body) => { Node::Function(mut body) => {
let mut body = body;
let parameters = body.pop_front().ok_or_else(|| todo!())?; let parameters = body.pop_front().ok_or_else(|| todo!())?;
let parameters = read_parameters(parameters.clone())?; let parameters = read_parameters(parameters.clone())?;
@ -81,8 +78,7 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
} }
} }
Node::Macro(body) => { Node::Macro(mut body) => {
let mut body = body;
let parameters = body.pop_front().ok_or_else(|| todo!())?; let parameters = body.pop_front().ok_or_else(|| todo!())?;
let parameters = read_parameters(parameters.clone())?; let parameters = read_parameters(parameters.clone())?;
@ -135,8 +131,7 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
Node::Void Node::Void
} }
Node::Let(body) => { Node::Let(mut body) => {
let mut body = body;
let args = match body.pop_front().ok_or_else(|| todo!())? { let args = match body.pop_front().ok_or_else(|| todo!())? {
Node::List(list) => list Node::List(list) => list
.into_iter() .into_iter()
@ -161,12 +156,11 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
eval(&env, body)?.pop_back().unwrap() eval(&env, body)?.pop_back().unwrap()
} }
Node::If(body) => { Node::If(mut body) => {
if body.len() != 2 && body.len() != 3 { if body.len() != 2 && body.len() != 3 {
Err(Error::MismatchedArgCount(3, body.len()))? Err(Error::MismatchedArgCount(3, body.len()))?
} }
let mut body = body;
let cond = body.pop_front().expect("arg count verified above").clone(); let cond = body.pop_front().expect("arg count verified above").clone();
let consequence = 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() { let alternative = match body.pop_front() {
@ -222,8 +216,7 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
env, env,
eval_node(env, body.pop_front().ok_or_else(|| todo!())?)?, eval_node(env, body.pop_front().ok_or_else(|| todo!())?)?,
)?, )?,
Node::Apply(body) => { Node::Apply(mut body) => {
let mut body = body;
let operator = eval_node(env, body.pop_front().ok_or(Error::InvalidOperator)?)?; let operator = eval_node(env, body.pop_front().ok_or(Error::InvalidOperator)?)?;
let mut args = match body.pop_front() { let mut args = match body.pop_front() {