Skip to content

Commit

Permalink
code restructuring moved literalvalue to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
cezaris13 committed Dec 8, 2024
1 parent e20a145 commit 24d575f
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 146 deletions.
2 changes: 1 addition & 1 deletion src/environment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::expression::LiteralValue;
use crate::expression_literal_value::LiteralValue;

use std::cell::RefCell;
use std::collections::HashMap;
Expand Down
130 changes: 13 additions & 117 deletions src/expression.rs
Original file line number Diff line number Diff line change
@@ -1,102 +1,14 @@
use crate::environment::Environment;
use crate::expression::LiteralValue::*;
use crate::token::TokenType::*;
use crate::token::{Token, TokenType};
use std::fmt::Display;
use crate::expression_literal_value::LiteralValue::{self, *};
use crate::token::{Token, TokenType::*};

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

#[cfg(test)]
#[path = "./tests/expression_tests.rs"]
mod tests;

#[derive(Clone, Debug, PartialEq)]
pub enum LiteralValue {
IntValue(i64),
FValue(f64),
StringValue(String),
True,
False,
Nil,
}

impl From<Token> for LiteralValue {
fn from(token: Token) -> Self {
match token.token_type {
TokenType::Number => match token.literal {
Some(crate::token::LiteralValue::IntValue(int_value)) => IntValue(int_value),
Some(crate::token::LiteralValue::FValue(float_value)) => FValue(float_value),
_ => panic!("Could not unwrap as number"),
},
TokenType::String => match token.literal {
Some(crate::token::LiteralValue::StringValue(string_value)) => {
StringValue(string_value)
}
_ => panic!("Could not unwrap as String"),
},
TokenType::False => Self::False,
TokenType::True => Self::True,
TokenType::Nil => Self::Nil,
_ => panic!("Could not create literal value from {:?}", token),
}
}
}

impl From<bool> for LiteralValue {
fn from(boolean: bool) -> Self {
if boolean {
Self::True
} else {
Self::False
}
}
}

impl From<&LiteralValue> for bool {
fn from(literal_value: &LiteralValue) -> Self {
match literal_value {
IntValue(x) => *x != 0,
FValue(x) => *x != 0.0,
StringValue(string) => string.len() != 0,
LiteralValue::True => true,
LiteralValue::False => false,
LiteralValue::Nil => false,
}
}
}

impl From<LiteralValue> for bool {
fn from(literal_value: LiteralValue) -> Self {
Self::from(&literal_value)
}
}

impl Display for LiteralValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
IntValue(integer) => integer.to_string(),
FValue(float) => float.to_string(),
StringValue(string) => string.clone(),
Self::True => String::from("true"),
Self::False => String::from("false"),
Self::Nil => String::from("nil"),
};
write!(f, "{}", str)
}
}

impl LiteralValue {
pub fn to_type(&self) -> &str {
match self {
IntValue(_) => "Int",
FValue(_) => "Float",
Self::True | Self::False => "Bool",
StringValue(_) => "String",
Self::Nil => "Nil",
}
}
}

macro_rules! compare_values {
($self:ident, $op_symbol:tt, $left:expr, $right:expr) => {
match (&$left, &$right) {
Expand All @@ -105,7 +17,7 @@ macro_rules! compare_values {
(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)),
_ => $self.not_implemented_error(&stringify!($op_symbol), &$left, &$right),
_ => LiteralValue::not_implemented_error(&stringify!($op_symbol), &$left, &$right),
}
};
}
Expand All @@ -128,7 +40,7 @@ macro_rules! arithmetic_operation {
(any, StringValue(string)) if stringify!($op_symbol) == "+" => {
Ok(StringValue(format!("{0}{1}", any, string)))
}
_ => $self.not_implemented_error(&stringify!($op_symbol), &$left, &$right),
_ => LiteralValue::not_implemented_error(&stringify!($op_symbol), &$left, &$right),
}
}
};
Expand Down Expand Up @@ -166,7 +78,7 @@ pub enum Expression {
}

impl Display for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str = match self {
Expression::Binary {
left,
Expand Down Expand Up @@ -202,9 +114,9 @@ impl Display for Expression {
Expression::Variable { token } => {
if let Some(_) = &token.literal {
format!(
"(defvar {} {:?})",
"(defvar {} {})",
token.lexeme,
LiteralValue::from(token.clone()).to_string()
LiteralValue::from(token.clone())
)
} else {
format!("(defvar {})", token.lexeme)
Expand All @@ -217,8 +129,6 @@ impl Display for Expression {
}

impl Expression {
// region evaluation

pub fn evaluate(&self, environment: &mut Environment) -> Result<LiteralValue, String> {
match self {
Expression::Literal { value } => Ok(value.clone()),
Expand Down Expand Up @@ -257,9 +167,11 @@ impl Expression {
LessEqual => compare_values!(self, <=, left, right),
BangEqual => Ok(LiteralValue::from(left != right)),
EqualEqual => Ok(LiteralValue::from(left == right)),
_ => {
self.not_implemented_error(&stringify!(operator.token_type), &left, &right)
}
_ => LiteralValue::not_implemented_error(
&stringify!(operator.token_type),
&left,
&right,
),
}
}
Expression::Variable { token } => environment.get(&token.lexeme),
Expand Down Expand Up @@ -289,20 +201,4 @@ impl Expression {
}
}
}

fn not_implemented_error(
&self,
token_type: &str,
left: &LiteralValue,
right: &LiteralValue,
) -> Result<LiteralValue, String> {
Err(format!(
"{:?} operation is not implemented for: {:?} and {:?}",
token_type.parse::<TokenType>()?,
left.to_string(),
right.to_string()
))
}

// endregion
}
105 changes: 105 additions & 0 deletions src/expression_literal_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use crate::expression_literal_value::LiteralValue::*;
use crate::token::{Token, TokenType, LiteralValue as TokenLiteralValue};

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

#[derive(Clone, Debug, PartialEq)]
pub enum LiteralValue {
IntValue(i64),
FValue(f64),
StringValue(String),
True,
False,
Nil,
}

impl From<Token> for LiteralValue {
fn from(token: Token) -> Self {
match token.token_type {
TokenType::Number => match token.literal {
Some(TokenLiteralValue::IntValue(int_value)) => IntValue(int_value),
Some(TokenLiteralValue::FValue(float_value)) => FValue(float_value),
_ => panic!("Could not unwrap as number"),
},
TokenType::String => match token.literal {
Some(TokenLiteralValue::StringValue(string_value)) => {
StringValue(string_value)
}
_ => panic!("Could not unwrap as String"),
},
TokenType::False => Self::False,
TokenType::True => Self::True,
TokenType::Nil => Self::Nil,
_ => panic!("Could not create literal value from {}", token),
}
}
}

impl From<bool> for LiteralValue {
fn from(boolean: bool) -> Self {
if boolean {
Self::True
} else {
Self::False
}
}
}

impl From<&LiteralValue> for bool {
fn from(literal_value: &LiteralValue) -> Self {
match literal_value {
IntValue(x) => *x != 0,
FValue(x) => *x != 0.0,
StringValue(string) => string.len() != 0,
LiteralValue::True => true,
LiteralValue::False => false,
LiteralValue::Nil => false,
}
}
}

impl From<LiteralValue> for bool {
fn from(literal_value: LiteralValue) -> Self {
Self::from(&literal_value)
}
}

impl Display for LiteralValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str = match self {
IntValue(integer) => integer.to_string(),
FValue(float) => float.to_string(),
StringValue(string) => string.clone(),
Self::True => String::from("true"),
Self::False => String::from("false"),
Self::Nil => String::from("nil"),
};
write!(f, "{}", str)
}
}

impl LiteralValue {
pub fn to_type(&self) -> &str {
match self {
IntValue(_) => "Int",
FValue(_) => "Float",
Self::True | Self::False => "Bool",
StringValue(_) => "String",
Self::Nil => "Nil",
}
}

pub fn not_implemented_error(
token_type: &str,
left: &LiteralValue,
right: &LiteralValue,
) -> Result<LiteralValue, String> {
Err(format!(
"{:?} operation is not implemented for: {} and {}",
token_type.parse::<TokenType>()?,
left,
right
))
}
}
5 changes: 3 additions & 2 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::environment::Environment;
use crate::expression::{Expression, LiteralValue};
use crate::expression::Expression;
use crate::expression_literal_value::LiteralValue;
use crate::statement::Statement;

use std::cell::RefCell;
Expand Down Expand Up @@ -28,7 +29,7 @@ impl Interpreter {
}
Statement::Print { expression } => {
let result = expression.evaluate(&mut self.environment.borrow_mut())?;
println!("{}", result.to_string());
println!("{}", result);
}
Statement::Variable { token, initializer } => {
let nil = Expression::Literal {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod environment;
mod expression;
mod expression_literal_value;
mod interpreter;
mod parser;
mod scanner;
Expand Down
3 changes: 2 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::expression::Expression;
use crate::expression::Expression::*;
use crate::expression::{Expression, LiteralValue};
use crate::expression_literal_value::LiteralValue;
use crate::statement::Statement;
use crate::token::TokenType::*;
use crate::token::{Token, TokenType};
Expand Down
2 changes: 1 addition & 1 deletion src/tests/environment_tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[cfg(test)]
mod tests {
use crate::environment::Environment;
use crate::expression::LiteralValue::*;
use crate::expression_literal_value::LiteralValue::*;

use std::cell::RefCell;
use std::rc::Rc;
Expand Down
Loading

0 comments on commit 24d575f

Please sign in to comment.