refactor: remove mutable reassignment
This commit is contained in:
parent
ed86c884ec
commit
a7c6e1a07d
2 changed files with 31 additions and 46 deletions
56
mute-interpreter/src/env/core.rs
vendored
56
mute-interpreter/src/env/core.rs
vendored
|
@ -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()
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in a new issue