Skip to content

Commit

Permalink
Added more functions.
Browse files Browse the repository at this point in the history
Added theming
  • Loading branch information
shartrec committed Jun 14, 2024
1 parent 39fff11 commit 473e990
Show file tree
Hide file tree
Showing 11 changed files with 496 additions and 83 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Project exclude paths
Cargo.lock
/target/
/.idea/.gitignore
/.idea/modules.xml
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
palette = "0.7.6"

[dependencies.iced]
git = "https://github.com/iced-rs/iced.git"
rev = "cdb18e610a72b4a025d7e1890140393adee5b087"
features = ["multi-window"]
features = ["canvas", "multi-window"]
109 changes: 109 additions & 0 deletions src/evaluator/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2024.
*
* Copyright 2024 Trevor Campbell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the “Software”), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/

use std::fmt::Debug;

use crate::evaluator::Token;

#[derive(Clone, Debug)]
pub(crate) struct Constant {
name: &'static str,
value: f64,
}

impl Constant {

pub(crate) fn name(&self) -> &'static str {
&self.name
}

pub(crate) fn is_token(
&self,
chars: &Vec<char>,
exp_len: &usize,
i: &usize,
) -> Option<(Token, usize)> {
// All these lengths need to be done in characters not Strings because of unicode
let name = self.name();
let cons_as_chars = name.chars().collect::<Vec<char>>();
let name_len = cons_as_chars.len();
let expr_chars_to_compare = &chars[*i..*i + name_len];
if i + name_len - 1 < *exp_len && expr_chars_to_compare == cons_as_chars
{
//Need to check the next character is not alphanumeric, otherwise it is the name of a different function
if (i + name_len < *exp_len) && chars[*i + name_len].is_alphanumeric() {
None
} else {
Some((Token::Number(self.value), name_len))
}
} else {
None
}
}

}


pub(crate) fn get_all() -> Vec<Constant> {
vec![
Constant {
name: "π",
value: std::f64::consts::PI,
},
Constant {
name: "e",
value: std::f64::consts::E,
},
Constant {
name: "Φ",
value: 1.61803,
},
Constant {
name: "C",
value: 299792458.0
},
Constant {
name: "ℎ",
value: 6.626e-34
},
Constant {
name: "G",
value: 6.674e-11
},

]
}

#[cfg(test)]
mod tests {
use crate::assert_near;
use crate::evaluator::constants::Constant;

#[test]
fn test_const() {
let f = Constant {
name: "Pi",
value: 50.2,
};
assert_near!(f.value(), 50.2);
}
}
48 changes: 48 additions & 0 deletions src/evaluator/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,54 @@ pub(crate) fn get_all() -> Vec<Function> {
name: "atan",
function: |v, mode| do_atrig(v, mode, f64::atan),
},
Function {
name: "cosec",
function: |v, mode| 1.0 / do_trig(v, mode, f64::sin)
},
Function {
name: "sec",
function: |v, mode| 1.0 / do_trig(v, mode, f64::cos),
},
Function {
name: "cot",
function: |v, mode| 1.0 / do_trig(v, mode, f64::tan),
},
Function {
name: "acosec",
function: |v, mode| do_atrig(1.0 / v, mode, f64::asin)
},
Function {
name: "asec",
function: |v, mode| do_atrig(1.0 / v, mode, f64::acos),
},
Function {
name: "acot",
function: |v, mode| do_atrig(1.0 / v, mode, f64::atan),
},
Function {
name: "sinh",
function: |v, _| v.sinh(),
},
Function {
name: "cosh",
function: |v, _| v.cosh(),
},
Function {
name: "tanh",
function: |v, _| v.tanh(),
},
Function {
name: "asinh",
function: |v, _| v.asinh(),
},
Function {
name: "acosh",
function: |v, _| v.acosh(),
},
Function {
name: "atanh",
function: |v, _| v.atanh(),
},
Function {
name: "exp",
function: |v, _| v.exp(),
Expand Down
7 changes: 7 additions & 0 deletions src/evaluator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
use std::fmt::{Debug, Display, Formatter};
use std::rc::Rc;

use crate::evaluator::constants::Constant;
use crate::evaluator::functions::Function;
use crate::evaluator::parser::Parser;
use crate::evaluator::tokeniser::tokenize;

mod functions;
pub(crate) mod parser;
pub(crate) mod tokeniser;
mod constants;

#[derive(Clone, Debug)]
pub(crate) enum Token {
Expand Down Expand Up @@ -126,13 +128,15 @@ impl Display for AngleMode {
pub(crate) struct Evaluator<'a> {
angle_mode: &'a AngleMode,
function_register: Vec<Function>,
constant_register: Vec<Constant>,
}

impl<'a> Evaluator<'a> {
pub(crate) fn create(angle_mode: &'a AngleMode) -> Self {
Self {
angle_mode,
function_register: functions::get_all(),
constant_register: constants::get_all(),
}
}

Expand All @@ -156,4 +160,7 @@ impl<'a> Evaluator<'a> {
pub fn function_register(&self) -> &Vec<Function> {
&self.function_register
}
pub fn constant_register(&self) -> &Vec<Constant> {
&self.constant_register
}
}
34 changes: 29 additions & 5 deletions src/evaluator/tokeniser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,23 @@ pub(crate) fn tokenize(expression: &str, evaluator: &Evaluator) -> Result<Vec<To
_ => {
// We now look for a function.
match parse_functions(&chars, chars.len(), i, &evaluator) {
Ok((token, consumed)) => {
Some((token, consumed)) => {
tokens.push(token);
i += consumed;
continue;
}
Err(e) => return Err(e),
None => {
match parse_constants(&chars, chars.len(), i, &evaluator) {
Some((token, consumed)) => {
tokens.push(token);
i += consumed;
continue;
}
None => {
return Err(format!("Invalid token '{}' at position: {}", chars[i], i))
}
}
}
}
}
}
Expand All @@ -70,11 +81,24 @@ fn parse_functions(
exp_len: usize,
i: usize,
evaluator: &Evaluator,
) -> Result<(Token, usize), String> {
) -> Option<(Token, usize)> {
for function in evaluator.function_register() {
if let Some((token, consumed)) = function.is_token(chars, &exp_len, &i) {
return Ok((token, consumed));
return Some((token, consumed));
}
}
None
}
fn parse_constants(
chars: &Vec<char>,
exp_len: usize,
i: usize,
evaluator: &Evaluator,
) -> Option<(Token, usize)> {
for constant in evaluator.constant_register() {
if let Some((token, consumed)) = constant.is_token(chars, &exp_len, &i) {
return Some((token, consumed));
}
}
Err(format!("Invalid token '{}' at position: {}", &chars[i], i))
None
}
Loading

0 comments on commit 473e990

Please sign in to comment.