mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-07 05:59:03 +01:00
Made parenthesis optional for unary functions
This only applies when the argument is a literal. To do this efficiently, I changed the `prelude` module. The module now has compile-time generated hashmaps of functions.
This commit is contained in:
parent
2cdade5d05
commit
34364dd40e
149
Cargo.lock
generated
149
Cargo.lock
generated
@ -113,6 +113,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
name = "lek"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"rustyline",
|
||||
]
|
||||
|
||||
@ -150,6 +151,131 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||
dependencies = [
|
||||
"phf_macros",
|
||||
"phf_shared",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
@ -204,6 +330,23 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7e33a62f20d3dc02a1bc9c1d385f92b459bbf35e4dc325eed20c53db5b90c03"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.6.0"
|
||||
@ -216,6 +359,12 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.0"
|
||||
|
@ -12,3 +12,4 @@ panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
rustyline = "6.1.2"
|
||||
phf = { version = "0.8", features = ["macros"] }
|
||||
|
@ -1,22 +1,21 @@
|
||||
use std::{collections::HashMap, mem};
|
||||
use std::mem;
|
||||
|
||||
use crate::lexer::TokenKind;
|
||||
use crate::parser::{Expr, Stmt, Unit};
|
||||
use crate::prelude::{self, Prelude};
|
||||
use crate::visitor::Visitor;
|
||||
use crate::prelude::{self};
|
||||
use crate::{symbol_table::SymbolTable, visitor::Visitor};
|
||||
|
||||
pub struct Interpreter<'a> {
|
||||
symbol_table: &'a mut HashMap<String, Stmt>,
|
||||
symbol_table: &'a mut SymbolTable,
|
||||
angle_unit: Unit,
|
||||
prelude: Prelude,
|
||||
}
|
||||
|
||||
impl<'a> Interpreter<'a> {
|
||||
pub fn new(angle_unit: Unit, symbol_table: &'a mut HashMap<String, Stmt>) -> Self {
|
||||
pub fn new(angle_unit: Unit, symbol_table: &'a mut SymbolTable) -> Self {
|
||||
//let mut hashmap: HashMap<String, Stmt> = HashMap::new();
|
||||
for constant in prelude::CONSTANTS {
|
||||
symbol_table.insert(
|
||||
constant.0.to_string(),
|
||||
constant.0,
|
||||
Stmt::VarDecl(
|
||||
constant.0.to_string(),
|
||||
Box::new(Expr::Literal(constant.1.to_string())),
|
||||
@ -27,7 +26,6 @@ impl<'a> Interpreter<'a> {
|
||||
Interpreter {
|
||||
angle_unit: angle_unit.clone(),
|
||||
symbol_table,
|
||||
prelude: Prelude::new(angle_unit),
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,23 +65,10 @@ impl<'a> Visitor<f64, f64> for Interpreter<'a> {
|
||||
fn visit_stmt(&mut self, stmt: &Stmt) -> f64 {
|
||||
match stmt {
|
||||
Stmt::VarDecl(identifier, _) => {
|
||||
self.symbol_table.insert(identifier.clone(), stmt.clone());
|
||||
0f64
|
||||
}
|
||||
Stmt::FnDecl(identifier, arguments, _) => {
|
||||
// Initialise each of the arguments as their own variable.
|
||||
for argument in arguments {
|
||||
self.visit_stmt(&Stmt::VarDecl(
|
||||
argument.clone(),
|
||||
Box::new(Expr::Literal(String::from("0"))),
|
||||
));
|
||||
}
|
||||
|
||||
// Add the function to the symbol table.
|
||||
self.symbol_table
|
||||
.insert(format!("{}()", identifier.clone()), stmt.clone());
|
||||
self.symbol_table.insert(&identifier, stmt.clone());
|
||||
0f64
|
||||
}
|
||||
Stmt::FnDecl(_, _, _) => 0f64, // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||
Stmt::Expr(expr) => self.visit_expr(&expr),
|
||||
}
|
||||
}
|
||||
@ -138,12 +123,12 @@ impl<'a> Visitor<f64, f64> for Interpreter<'a> {
|
||||
let prelude_func = match expressions.len() {
|
||||
1 => {
|
||||
let x = self.visit_expr(&expressions[0]);
|
||||
self.prelude.call_unary_func(identifier, x)
|
||||
prelude::call_unary_func(identifier, x, &self.angle_unit)
|
||||
}
|
||||
2 => {
|
||||
let x = self.visit_expr(&expressions[0]);
|
||||
let y = self.visit_expr(&expressions[1]);
|
||||
self.prelude.call_binary_func(identifier, x, y)
|
||||
prelude::call_binary_func(identifier, x, y, &self.angle_unit)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
@ -184,5 +184,5 @@ impl<'a> Lexer<'a> {
|
||||
}
|
||||
|
||||
fn is_valid_identifier(c: char) -> bool {
|
||||
c.is_alphabetic() || c == '°' || c == '√' || c == '\''
|
||||
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨'
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ mod interpreter;
|
||||
mod lexer;
|
||||
mod parser;
|
||||
mod prelude;
|
||||
mod symbol_table;
|
||||
mod visitor;
|
||||
use parser::{Parser, Unit};
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
use std::{collections::HashMap, mem};
|
||||
use std::mem;
|
||||
|
||||
use crate::{
|
||||
interpreter::Interpreter,
|
||||
lexer::{Lexer, Token, TokenKind},
|
||||
prelude,
|
||||
symbol_table::SymbolTable,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -34,7 +35,7 @@ pub struct Parser {
|
||||
pub angle_unit: Unit,
|
||||
tokens: Vec<Token>,
|
||||
pos: usize,
|
||||
symbol_table: HashMap<String, Stmt>,
|
||||
symbol_table: SymbolTable,
|
||||
}
|
||||
|
||||
impl TokenKind {
|
||||
@ -55,7 +56,7 @@ impl Parser {
|
||||
Parser {
|
||||
tokens: Vec::new(),
|
||||
pos: 0,
|
||||
symbol_table: HashMap::new(),
|
||||
symbol_table: SymbolTable::new(),
|
||||
angle_unit: prelude::DEFAULT_ANGLE_UNIT,
|
||||
}
|
||||
}
|
||||
@ -106,7 +107,15 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
return Stmt::FnDecl(identifier, parameter_identifiers, Box::new(expr));
|
||||
let fn_decl =
|
||||
Stmt::FnDecl(identifier.clone(), parameter_identifiers, Box::new(expr));
|
||||
|
||||
// Insert the function declaration into the symbol table during parsing
|
||||
// so that the parser can find out if particular functions exist.
|
||||
self.symbol_table
|
||||
.insert(&format!("{}()", identifier), fn_decl.clone());
|
||||
|
||||
return fn_decl;
|
||||
}
|
||||
|
||||
panic!("Unexpected error.");
|
||||
@ -221,6 +230,16 @@ impl Parser {
|
||||
fn parse_identifier(&mut self) -> Expr {
|
||||
let identifier = self.advance().clone();
|
||||
|
||||
// Eg. sqrt64
|
||||
if self.match_token(TokenKind::Literal) {
|
||||
// If there is a function with this name, parse it as a function, with the next token as the argument.
|
||||
if self.symbol_table.contains_func(&identifier.value) {
|
||||
let parameter = Expr::Literal(self.advance().value.clone());
|
||||
return Expr::FnCall(identifier.value, vec![parameter]);
|
||||
}
|
||||
}
|
||||
|
||||
// Eg. sqrt(64)
|
||||
if self.match_token(TokenKind::OpenParenthesis) {
|
||||
self.advance();
|
||||
|
||||
@ -234,10 +253,11 @@ impl Parser {
|
||||
|
||||
self.consume(TokenKind::ClosedParenthesis);
|
||||
|
||||
Expr::FnCall(identifier.value, parameters)
|
||||
} else {
|
||||
Expr::Var(identifier.value)
|
||||
return Expr::FnCall(identifier.value, parameters);
|
||||
}
|
||||
|
||||
// Eg. x
|
||||
Expr::Var(identifier.value)
|
||||
}
|
||||
|
||||
fn peek(&self) -> &Token {
|
||||
|
213
src/prelude.rs
213
src/prelude.rs
@ -1,5 +1,5 @@
|
||||
use crate::parser::Unit;
|
||||
use std::collections::HashMap;
|
||||
use FuncType::*;
|
||||
|
||||
pub const DEFAULT_ANGLE_UNIT: Unit = Unit::Radians;
|
||||
pub const CONSTANTS: &[(&str, &str)] = &[
|
||||
@ -12,36 +12,77 @@ pub const CONSTANTS: &[(&str, &str)] = &[
|
||||
("ϕ", "1.61803398"),
|
||||
];
|
||||
|
||||
use funcs::*;
|
||||
pub const UNARY_FUNCS: phf::Map<&'static str, UnaryFuncInfo> = phf::phf_map! {
|
||||
"cos" => UnaryFuncInfo(cos, Trig),
|
||||
"cosec" => UnaryFuncInfo(cosec, Trig),
|
||||
"cosech" => UnaryFuncInfo(cosech, Trig),
|
||||
"cosh" => UnaryFuncInfo(cosh, Trig),
|
||||
"cot" => UnaryFuncInfo(cot, Trig),
|
||||
"coth" => UnaryFuncInfo(coth, Trig),
|
||||
"sec" => UnaryFuncInfo(sec, Trig),
|
||||
"sech" => UnaryFuncInfo(sech, Trig),
|
||||
"sin" => UnaryFuncInfo(sin, Trig),
|
||||
"sinh" => UnaryFuncInfo(sinh, Trig),
|
||||
"tan" => UnaryFuncInfo(tan, Trig),
|
||||
"tanh" => UnaryFuncInfo(tanh, Trig),
|
||||
|
||||
"acos" => UnaryFuncInfo(acos, InverseTrig),
|
||||
"acosec" => UnaryFuncInfo(acosec, InverseTrig),
|
||||
"acosech" => UnaryFuncInfo(acosech, InverseTrig),
|
||||
"acosh" => UnaryFuncInfo(acosh, InverseTrig),
|
||||
"acot" => UnaryFuncInfo(acot, InverseTrig),
|
||||
"acoth" => UnaryFuncInfo(acoth, InverseTrig),
|
||||
"asec" => UnaryFuncInfo(asec, InverseTrig),
|
||||
"asech" => UnaryFuncInfo(asech, InverseTrig),
|
||||
"asin" => UnaryFuncInfo(asin, InverseTrig),
|
||||
"asinh" => UnaryFuncInfo(asinh, InverseTrig),
|
||||
"atan" => UnaryFuncInfo(atan, InverseTrig),
|
||||
"atanh" => UnaryFuncInfo(atanh, InverseTrig),
|
||||
|
||||
"abs" => UnaryFuncInfo(abs, Other),
|
||||
"cbrt" => UnaryFuncInfo(cbrt, Other),
|
||||
"ceil" => UnaryFuncInfo(ceil, Other),
|
||||
"exp" => UnaryFuncInfo(exp, Other),
|
||||
"floor" => UnaryFuncInfo(floor, Other),
|
||||
"frac" => UnaryFuncInfo(frac, Other),
|
||||
"log" => UnaryFuncInfo(log, Other),
|
||||
"ln" => UnaryFuncInfo(ln, Other),
|
||||
"round" => UnaryFuncInfo(round, Other),
|
||||
"sqrt" => UnaryFuncInfo(sqrt, Other),
|
||||
"trunc" => UnaryFuncInfo(trunc, Other),
|
||||
};
|
||||
pub const BINARY_FUNCS: phf::Map<&'static str, BinaryFuncInfo> = phf::phf_map! {
|
||||
"max" => BinaryFuncInfo(max, Other),
|
||||
"min" => BinaryFuncInfo(min, Other),
|
||||
};
|
||||
|
||||
enum FuncType {
|
||||
Trig,
|
||||
InverseTrig,
|
||||
Other,
|
||||
}
|
||||
|
||||
struct UnaryFuncInfo {
|
||||
func: Box<fn(f64) -> f64>,
|
||||
func_type: FuncType,
|
||||
}
|
||||
// Unary functions
|
||||
pub struct UnaryFuncInfo(fn(f64) -> f64, FuncType);
|
||||
|
||||
pub struct BinaryFuncInfo(fn(f64, f64) -> f64, FuncType);
|
||||
|
||||
impl UnaryFuncInfo {
|
||||
fn call(&self, x: f64, angle_unit: &Unit) -> f64 {
|
||||
let func = *self.func;
|
||||
match self.func_type {
|
||||
let func = self.0;
|
||||
match self.1 {
|
||||
FuncType::Trig => func(from_angle_unit(x, angle_unit)),
|
||||
FuncType::InverseTrig => to_angle_unit(func(x), angle_unit),
|
||||
FuncType::Other => func(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
struct BinaryFuncInfo {
|
||||
func: Box<fn(f64, f64) -> f64>,
|
||||
func_type: FuncType,
|
||||
}
|
||||
|
||||
impl BinaryFuncInfo {
|
||||
fn call(&self, x: f64, y: f64, angle_unit: &Unit) -> f64 {
|
||||
let func = *self.func;
|
||||
match self.func_type {
|
||||
let func = self.0;
|
||||
match self.1 {
|
||||
FuncType::Trig => func(
|
||||
from_angle_unit(x, angle_unit),
|
||||
from_angle_unit(y, angle_unit),
|
||||
@ -52,6 +93,22 @@ impl BinaryFuncInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_unary_func(name: &str, x: f64, angle_unit: &Unit) -> Option<f64> {
|
||||
if let Some(func_info) = UNARY_FUNCS.get(name) {
|
||||
Some(func_info.call(x, &angle_unit))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_binary_func(name: &str, x: f64, y: f64, angle_unit: &Unit) -> Option<f64> {
|
||||
if let Some(func_info) = BINARY_FUNCS.get(name) {
|
||||
Some(func_info.call(x, y, angle_unit))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn to_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
|
||||
match angle_unit {
|
||||
Unit::Radians => x,
|
||||
@ -66,130 +123,6 @@ fn from_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Prelude {
|
||||
angle_unit: Unit,
|
||||
unary: HashMap<String, UnaryFuncInfo>,
|
||||
binary: HashMap<String, BinaryFuncInfo>,
|
||||
}
|
||||
|
||||
impl Prelude {
|
||||
pub fn new(angle_unit: Unit) -> Self {
|
||||
Prelude {
|
||||
angle_unit,
|
||||
unary: HashMap::new(),
|
||||
binary: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_unary_func(&mut self, name: &str, x: f64) -> Option<f64> {
|
||||
if let Some(func_info) = self.unary.get(name) {
|
||||
Some(func_info.call(x, &self.angle_unit))
|
||||
} else {
|
||||
let trig_func: Option<fn(f64) -> f64> = match name {
|
||||
"cos" => Some(funcs::cos),
|
||||
"cosec" => Some(funcs::cosec),
|
||||
"cosech" => Some(funcs::cosech),
|
||||
"cosh" => Some(funcs::cosh),
|
||||
"cot" => Some(funcs::cot),
|
||||
"coth" => Some(funcs::coth),
|
||||
"sec" => Some(funcs::sec),
|
||||
"sech" => Some(funcs::sech),
|
||||
"sin" => Some(funcs::sin),
|
||||
"sinh" => Some(funcs::sinh),
|
||||
"tan" => Some(funcs::tan),
|
||||
"tanh" => Some(funcs::tanh),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(func) = trig_func {
|
||||
let func_info = UnaryFuncInfo {
|
||||
func: Box::new(func),
|
||||
func_type: FuncType::Trig,
|
||||
};
|
||||
let value = func_info.call(x, &self.angle_unit);
|
||||
self.unary.insert(name.to_string(), func_info);
|
||||
|
||||
return Some(value);
|
||||
}
|
||||
|
||||
let inv_trig_func: Option<fn(f64) -> f64> = match name {
|
||||
"acos" => Some(funcs::acos),
|
||||
"acosh" => Some(funcs::acosh),
|
||||
"acot" => Some(funcs::acot),
|
||||
"acoth" => Some(funcs::acoth),
|
||||
"acosec" => Some(funcs::acosec),
|
||||
"asec" => Some(funcs::asec),
|
||||
"asech" => Some(funcs::asech),
|
||||
"asin" => Some(funcs::asin),
|
||||
"asinh" => Some(funcs::asinh),
|
||||
"atan" => Some(funcs::atan),
|
||||
"atanh" => Some(funcs::atanh),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(func) = inv_trig_func {
|
||||
let func_info = UnaryFuncInfo {
|
||||
func: Box::new(func),
|
||||
func_type: FuncType::InverseTrig,
|
||||
};
|
||||
let value = func_info.call(x, &self.angle_unit);
|
||||
self.unary.insert(name.to_string(), func_info);
|
||||
|
||||
return Some(value);
|
||||
}
|
||||
|
||||
let misc_func: Option<fn(f64) -> f64> = match name {
|
||||
"abs" => Some(funcs::abs),
|
||||
"cbrt" => Some(funcs::cbrt),
|
||||
"ceil" => Some(funcs::ceil),
|
||||
"exp" => Some(funcs::exp),
|
||||
"floor" => Some(funcs::floor),
|
||||
"frac" => Some(funcs::frac),
|
||||
"log" => Some(funcs::log),
|
||||
"ln" => Some(funcs::ln),
|
||||
"round" => Some(funcs::round),
|
||||
"sqrt" => Some(funcs::sqrt),
|
||||
"trunc" => Some(funcs::trunc),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(func) = misc_func {
|
||||
let func_info = UnaryFuncInfo {
|
||||
func: Box::new(func),
|
||||
func_type: FuncType::Other,
|
||||
};
|
||||
let value = func_info.call(x, &self.angle_unit);
|
||||
self.unary.insert(name.to_string(), func_info);
|
||||
|
||||
return Some(value);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_binary_func(&mut self, name: &str, x: f64, y: f64) -> Option<f64> {
|
||||
let misc_func: Option<fn(f64, f64) -> f64> = match name {
|
||||
"max" => Some(funcs::max),
|
||||
"min" => Some(funcs::min),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(func) = misc_func {
|
||||
let func_info = BinaryFuncInfo {
|
||||
func: Box::new(func),
|
||||
func_type: FuncType::Other,
|
||||
};
|
||||
let value = func_info.call(x, y, &self.angle_unit);
|
||||
self.binary.insert(name.to_string(), func_info);
|
||||
|
||||
return Some(value);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod funcs {
|
||||
pub fn abs(x: f64) -> f64 {
|
||||
x.abs()
|
||||
@ -211,7 +144,11 @@ mod funcs {
|
||||
}
|
||||
|
||||
pub fn acosec(x: f64) -> f64 {
|
||||
(1f64 / x).sinh()
|
||||
(1f64 / x).asin()
|
||||
}
|
||||
|
||||
pub fn acosech(x: f64) -> f64 {
|
||||
(1f64 / x).asinh()
|
||||
}
|
||||
|
||||
pub fn asec(x: f64) -> f64 {
|
||||
|
28
src/symbol_table.rs
Normal file
28
src/symbol_table.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use crate::{parser::Stmt, prelude};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct SymbolTable {
|
||||
hashmap: HashMap<String, Stmt>,
|
||||
}
|
||||
|
||||
impl SymbolTable {
|
||||
pub fn new() -> Self {
|
||||
SymbolTable {
|
||||
hashmap: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: &str, value: Stmt) {
|
||||
self.hashmap.insert(key.into(), value);
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &str) -> Option<&Stmt> {
|
||||
self.hashmap.get(key)
|
||||
}
|
||||
|
||||
pub fn contains_func(&self, key: &str) -> bool {
|
||||
prelude::UNARY_FUNCS.contains_key(key)
|
||||
|| prelude::UNARY_FUNCS.contains_key(key)
|
||||
|| self.hashmap.contains_key(&format!("{}()", key))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user