Skip to content

Commit

Permalink
expressionliteral traits for addition
Browse files Browse the repository at this point in the history
  • Loading branch information
cezaris13 committed Dec 8, 2024
1 parent fa8fabc commit 4724dad
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 49 deletions.
54 changes: 9 additions & 45 deletions src/expression.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::compare_values;
use crate::environment::Environment;
use crate::expression_literal_value::LiteralValue::{self, *};
use crate::token::{Token, TokenType::*};
Expand All @@ -9,43 +10,6 @@ use std::string::String;
#[path = "./tests/expression_tests.rs"]
mod tests;

macro_rules! compare_values {
($self:ident, $op_symbol:tt, $left:expr, $right:expr) => {
match (&$left, &$right) {
(IntValue(x), IntValue(y)) => Ok(LiteralValue::from(x $op_symbol y)),
(FValue(x), FValue(y)) => Ok(LiteralValue::from(x $op_symbol y)),
(IntValue(x), FValue(y)) => Ok(LiteralValue::from((*x as f64) $op_symbol *y)),
(FValue(x), IntValue(y)) => Ok(LiteralValue::from(*x $op_symbol (*y as f64))),
(StringValue(x), StringValue(y)) => Ok(LiteralValue::from(x $op_symbol y)),
_ => LiteralValue::not_implemented_error(&stringify!($op_symbol), &$left, &$right),
}
};
}

macro_rules! arithmetic_operation {
($self:ident, $op_symbol:tt, $left: expr, $right: expr) => {
{
if stringify!($op_symbol) == "/" && matches!($right, IntValue(0) | FValue(0.0)) {
return Err(String::from("Division by 0"));
}

match (&$left, &$right) {
(IntValue(x), IntValue(y)) => Ok(IntValue(x $op_symbol y)),
(FValue(x), FValue(y)) => Ok(FValue(x $op_symbol y)),
(IntValue(x), FValue(y)) => Ok(FValue((*x as f64) $op_symbol y)),
(FValue(x), IntValue(y)) => Ok(FValue(x $op_symbol (*y as f64))),
(StringValue(string), any) if stringify!($op_symbol) == "+" => {
Ok(StringValue(format!("{0}{1}", string, any)))
}
(any, StringValue(string)) if stringify!($op_symbol) == "+" => {
Ok(StringValue(format!("{0}{1}", any, string)))
}
_ => LiteralValue::not_implemented_error(&stringify!($op_symbol), &$left, &$right),
}
}
};
}

#[derive(Clone, Debug, PartialEq)]
pub enum Expression {
Binary {
Expand Down Expand Up @@ -157,14 +121,14 @@ impl Expression {
let right = (*right).evaluate(environment)?;

match &operator.token_type {
Plus => arithmetic_operation!(self, +, left, right),
Minus => arithmetic_operation!(self, -, left, right),
Star => arithmetic_operation!(self, *, left, right),
Slash => arithmetic_operation!(self, /, left, right),
Greater => compare_values!(self, >, left, right),
GreaterEqual => compare_values!(self, >=, left, right),
Less => compare_values!(self, <, left, right),
LessEqual => compare_values!(self, <=, left, right),
Plus => left + right,
Minus => left - right,
Star => left * right,
Slash => left / right,
Greater => compare_values!(>, left, right),
GreaterEqual => compare_values!(>=, left, right),
Less => compare_values!(<, left, right),
LessEqual => compare_values!(<=, left, right),
BangEqual => Ok(LiteralValue::from(left != right)),
EqualEqual => Ok(LiteralValue::from(left == right)),
_ => LiteralValue::not_implemented_error(
Expand Down
77 changes: 73 additions & 4 deletions src/expression_literal_value.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::expression_literal_value::LiteralValue::*;
use crate::token::{Token, TokenType, LiteralValue as TokenLiteralValue};
use crate::token::{LiteralValue as TokenLiteralValue, Token, TokenType};

use std::fmt::{Display, Formatter};
use std::ops;
use std::string::String;

#[cfg(test)]
Expand All @@ -27,9 +28,7 @@ impl From<Token> for LiteralValue {
_ => panic!("Could not unwrap as number"),
},
TokenType::String => match token.literal {
Some(TokenLiteralValue::StringValue(string_value)) => {
StringValue(string_value)
}
Some(TokenLiteralValue::StringValue(string_value)) => StringValue(string_value),
_ => panic!("Could not unwrap as String"),
},
TokenType::False => Self::False,
Expand Down Expand Up @@ -107,3 +106,73 @@ impl LiteralValue {
))
}
}

#[macro_export]
macro_rules! compare_values {
($op_symbol:tt, $left:expr, $right:expr) => {
match (&$left, &$right) {
(IntValue(x), IntValue(y)) => Ok(LiteralValue::from(x $op_symbol y)),
(FValue(x), FValue(y)) => Ok(LiteralValue::from(x $op_symbol y)),
(IntValue(x), FValue(y)) => Ok(LiteralValue::from((*x as f64) $op_symbol *y)),
(FValue(x), IntValue(y)) => Ok(LiteralValue::from(*x $op_symbol (*y as f64))),
(StringValue(x), StringValue(y)) => Ok(LiteralValue::from(x $op_symbol y)),
_ => LiteralValue::not_implemented_error(&stringify!($op_symbol), &$left, &$right),
}
};
}

macro_rules! arithmetic_operation {
($left: expr, $op_symbol:tt, $right: expr) => {
{
if stringify!($op_symbol) == "/" && matches!($right, IntValue(0) | FValue(0.0)) {
return Err(String::from("Division by 0"));
}

match (&$left, &$right) {
(IntValue(x), IntValue(y)) => Ok(IntValue(x $op_symbol y)),
(FValue(x), FValue(y)) => Ok(FValue(x $op_symbol y)),
(IntValue(x), FValue(y)) => Ok(FValue((*x as f64) $op_symbol y)),
(FValue(x), IntValue(y)) => Ok(FValue(x $op_symbol (*y as f64))),
(StringValue(string), any) if stringify!($op_symbol) == "+" => {
Ok(StringValue(format!("{0}{1}", string, any)))
}
(any, StringValue(string)) if stringify!($op_symbol) == "+" => {
Ok(StringValue(format!("{0}{1}", any, string)))
}
_ => LiteralValue::not_implemented_error(&stringify!($op_symbol), &$left, &$right),
}
}
};
}

impl ops::Add<LiteralValue> for LiteralValue {
type Output = Result<Self, String>;

fn add(self, _rhs: Self) -> Self::Output {
arithmetic_operation!(&self, +, &_rhs)
}
}

impl ops::Sub<LiteralValue> for LiteralValue {
type Output = Result<Self, String>;

fn sub(self, _rhs: Self) -> Self::Output {
arithmetic_operation!(&self, -, &_rhs)
}
}

impl ops::Mul<LiteralValue> for LiteralValue {
type Output = Result<Self, String>;

fn mul(self, _rhs: Self) -> Self::Output {
arithmetic_operation!(&self, *, &_rhs)
}
}

impl ops::Div<LiteralValue> for LiteralValue {
type Output = Result<Self, String>;

fn div(self, _rhs: Self) -> Self::Output {
arithmetic_operation!(&self, /, &_rhs)
}
}

0 comments on commit 4724dad

Please sign in to comment.