From 4a02f7cb957232be82b05038607c874332e4e3a5 Mon Sep 17 00:00:00 2001 From: Roman Godmaire Date: Sat, 17 Feb 2024 22:16:51 -0500 Subject: [PATCH] refactor: use macro for arg counting --- src/evaluator/env.rs | 45 +++++++++++------------------------------ src/evaluator/macros.rs | 10 +++++++++ src/evaluator/mod.rs | 2 ++ 3 files changed, 24 insertions(+), 33 deletions(-) create mode 100644 src/evaluator/macros.rs diff --git a/src/evaluator/env.rs b/src/evaluator/env.rs index ac27f25..5c18da4 100644 --- a/src/evaluator/env.rs +++ b/src/evaluator/env.rs @@ -1,5 +1,6 @@ use std::{borrow::Borrow, cell::RefCell, collections::HashMap, rc::Rc}; +use super::macros::arg_count; use super::{eval_ast_node, Error, Expression}; use crate::parser::Node; @@ -130,9 +131,7 @@ pub fn core_environment() -> Rc { ( "eq?", Expression::NativeFunc(|args| { - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); if args[0] == args[1] { return Ok(Expression::Boolean(true).into()); @@ -144,9 +143,7 @@ pub fn core_environment() -> Rc { ( "not", Expression::NativeFunc(|args| { - if args.len() != 1 { - Err(Error::MismatchedArgCount(1, args.len()))? - } + arg_count!(1, args.len()); if *args[0] == Expression::Boolean(false) { return Ok(Expression::Boolean(true).into()); @@ -158,9 +155,7 @@ pub fn core_environment() -> Rc { ( "<", Expression::NativeFunc(|args| { - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let less_than = match (args[0].borrow(), args[1].borrow()) { (Expression::Int(lhs), Expression::Int(rhs)) => lhs < rhs, @@ -173,9 +168,7 @@ pub fn core_environment() -> Rc { ( ">", Expression::NativeFunc(|args| { - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let greater_than = match (args[0].borrow(), args[1].borrow()) { (Expression::Int(lhs), Expression::Int(rhs)) => lhs > rhs, @@ -188,9 +181,7 @@ pub fn core_environment() -> Rc { ( "<=", Expression::NativeFunc(|args| { - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let less_than_equal = match (args[0].borrow(), args[1].borrow()) { (Expression::Int(lhs), Expression::Int(rhs)) => lhs <= rhs, @@ -203,9 +194,7 @@ pub fn core_environment() -> Rc { ( ">=", Expression::NativeFunc(|args| { - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let greater_than_equal = match (args[0].borrow(), args[1].borrow()) { (Expression::Int(lhs), Expression::Int(rhs)) => lhs >= rhs, @@ -219,9 +208,7 @@ pub fn core_environment() -> Rc { ( "if", Expression::NativeFunc(|args| { - if args.len() != 3 { - Err(Error::MismatchedArgCount(3, args.len()))? - } + arg_count!(3, args.len()); let (cond, consequence, alternative) = (args[0].clone(), args[1].clone(), args[2].clone()); @@ -239,9 +226,7 @@ pub fn core_environment() -> Rc { "define!", Expression::Special(|env, args| { let mut args = args.into_iter(); - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let key = match args.next().unwrap() { Node::Symbol(name) => name, @@ -258,9 +243,7 @@ pub fn core_environment() -> Rc { ( "let*", Expression::Special(|env, args| { - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let mut args = args.into_iter(); let new_env = match args.next().unwrap() { @@ -288,9 +271,7 @@ pub fn core_environment() -> Rc { "fn*", Expression::Special(|env, args| { let mut args = args; - if args.len() != 2 { - Err(Error::MismatchedArgCount(2, args.len()))? - } + arg_count!(2, args.len()); let arg_list = args.remove(0); let body = args.remove(0); @@ -317,9 +298,7 @@ pub fn core_environment() -> Rc { ( "display", Expression::NativeFunc(|args| { - if args.len() != 1 { - Err(Error::MismatchedArgCount(1, args.len()))? - } + arg_count!(1, args.len()); print!("{}", args[0]); diff --git a/src/evaluator/macros.rs b/src/evaluator/macros.rs new file mode 100644 index 0000000..6a0c343 --- /dev/null +++ b/src/evaluator/macros.rs @@ -0,0 +1,10 @@ +#[macro_export] +macro_rules! arg_count { + ($expected:expr, $given:expr) => { + if $expected != $given { + Err(Error::MismatchedArgCount($expected, $given))? + } + }; +} + +pub(crate) use arg_count; diff --git a/src/evaluator/mod.rs b/src/evaluator/mod.rs index 3c8a72f..3d05777 100644 --- a/src/evaluator/mod.rs +++ b/src/evaluator/mod.rs @@ -6,6 +6,8 @@ use thiserror::Error; use crate::parser::Node; mod env; +mod macros; + pub use env::{core_environment, Environment}; #[derive(Debug, PartialEq)]