Skip to content

Commit

Permalink
commented everything for better readability
Browse files Browse the repository at this point in the history
  • Loading branch information
orzklv committed Aug 7, 2023
1 parent 6744faf commit e85fd80
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ use crate::error::SchierkeError;
use crate::expression::Expression;
use std::collections::HashMap;

/// Environment
/// Place where we store variables
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Environment {
/// Variables HashMap
variables: HashMap<String, Expression>,
}

impl Environment {
/// Create a new environment instance, if one is not provided
pub fn new(env: Option<Environment>) -> Environment {
match env {
Some(e) => e,
None => Default::default(),
}
}

/// Setter | store a variable in the environment
pub fn define(
&mut self,
name: Expression,
Expand All @@ -27,14 +32,15 @@ impl Environment {
value
}

/// Getter | lookup a variable in the environment
pub fn lookup(&self, name: String) -> Result<Expression, SchierkeError> {
match self.variables.get(name.as_str()) {
Some(e) => Ok(e.clone()),
None => Err(SchierkeError::UndefinedVariable),
}
}

// load changes from another environment
/// Load changes from another environment
pub fn load(&mut self, env: Environment) {
self.variables = env.variables;
}
Expand Down
1 change: 1 addition & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt::Debug;

/// Error type for Schierke
#[derive(PartialEq)]
pub enum SchierkeError {
ParseError,
Expand Down
4 changes: 4 additions & 0 deletions src/expression.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::convert::TryFrom;
use std::fmt::Debug;

/// The expression enum is used to represent the
/// different types of expressions
#[derive(PartialEq, Clone, Debug)]
pub enum Expression {
Number(i64),
Expand All @@ -12,6 +14,7 @@ pub enum Expression {
Divide(Vec<Expression>),
}

/// The TryFrom trait is used to convert an Expression to a i64
impl TryFrom<Expression> for i64 {
type Error = &'static str;

Expand All @@ -23,6 +26,7 @@ impl TryFrom<Expression> for i64 {
}
}

/// Implement the Display trait for Expression to be able to print it
impl std::fmt::Display for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Expand Down
52 changes: 52 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,99 @@ use environment::Environment;
use error::SchierkeError;
use expression::Expression;

/// Schierke is a simple functional lab language
#[derive(Default, PartialEq, Clone)]
pub struct Schierke {
/// The global environment where global variables are stored
global: Environment,
}

impl Schierke {
/// Create a new Schierke instance
pub fn new() -> Schierke {
Schierke {
global: Default::default(),
}
}

/// Evaluate an expression
///
/// # Arguments
/// * `exp` - The expression to evaluate
/// * `env` - The variable environment
///
/// # Returns
/// * `Result<Expression, SchierkeError>` - The result of the expression
pub fn eval(
&mut self,
exp: Expression,
env: Option<Environment>,
) -> Result<Expression, SchierkeError> {
// Create a new environment where we can store variables
// If we're given an environment, use that instead
// This environment is global, so it will be used for all expressions
let mut _e: Environment = match env {
Some(e) => e,
None => self.global.clone(),
};

// Evaluate of the expression
let rev: Result<Expression, SchierkeError> = match exp.clone() {
// Number expression
Expression::Number(e) => Ok(Expression::Number(e)),

// String expression
Expression::String(e) => Ok(Expression::String(e)),

// Variable expression
Expression::Variable(e) => match e.len() {
// If the length is 1, we're looking up a variable
1 => {
let result = _e.lookup(e[0].clone().to_string());
Ok(result.unwrap())
}

// If the length is 2, we're defining a variable
2 => {
let result = _e.define(e[0].clone(), self.eval(e[1].clone(), None).unwrap());
Ok(result)
}

// If the length is anything else, we're doing something wrong
_ => Err(SchierkeError::TooMuchArguments),
},

// Add expression
Expression::Add(e)

// Subtract expression
| Expression::Subtract(e)

// Multiply expression
| Expression::Multiply(e)

// Divide expression
| Expression::Divide(e) => {
// If the length is not 2, we're doing something wrong
if e.len() != 2 {
return Err(SchierkeError::UnknownExpression);
}

// Create initial result variable to save the result of the expression
let mut result = 0;

// Evaluate the first expression and add it to the result
result += match self.eval(e[0].clone(), None)? {
n => match i64::try_from(n) {
Ok(n) => n,
Err(_) => return Err(SchierkeError::UnknownExpression),
},
};

// Evaluate the second expression and depending on the expression,
// add, subtract, multiply, or divide it to the result
match exp.clone() {
// If the second expression is addition, add the result by the second expression
Expression::Add(_) => {
result += match self.eval(e[1].clone(), None)? {
n => match i64::try_from(n) {
Expand All @@ -70,6 +109,8 @@ impl Schierke {
},
};
}

// If the second expression is subtraction, subtract the result by the second expression
Expression::Subtract(_) => {
result -= match self.eval(e[1].clone(), None)? {
n => match i64::try_from(n) {
Expand All @@ -78,6 +119,8 @@ impl Schierke {
}
}
}

// If the second expression is multiplication, multiply the result by the second expression
Expression::Multiply(_) => {
result *= match self.eval(e[1].clone(), None)? {
n => match i64::try_from(n) {
Expand All @@ -86,6 +129,8 @@ impl Schierke {
},
};
}

// If the second expression is division, divide the result by the second expression
Expression::Divide(_) => {
result /= match self.eval(e[1].clone(), None)? {
n => match i64::try_from(n) {
Expand All @@ -94,17 +139,24 @@ impl Schierke {
},
};
}

// If the expression is anything else, we're doing something wrong
_ => {
return Err(SchierkeError::UnknownExpression);
}
};

// Return the result
Ok(Expression::Number(result))
}
};

// Save the environment to the global environment
// This is so we can use the variables in the global environment
// after the expression has been evaluated
self.global.load(_e);

// Return the result
rev
}
}
Expand Down

0 comments on commit e85fd80

Please sign in to comment.