mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-08 06:28:56 +01:00
Replaced f64 with rug::Float.
This commit is contained in:
parent
0d2d6df85b
commit
93321c3dac
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -27,12 +27,29 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "az"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9bcd47d94aa4eb8c076b50fc61a75020789394ffb9bd74a180b3379130f6569"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bigdecimal"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -112,6 +129,16 @@ dependencies = [
|
|||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gmp-mpfr-sys"
|
||||||
|
version = "1.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c04ccc68f16a0be7164b9de26e65aab8507596cc1969cec2e32fb1692b53b1b"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -123,7 +150,9 @@ name = "lek"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
|
"bigdecimal",
|
||||||
"phf",
|
"phf",
|
||||||
|
"rug",
|
||||||
"rustyline",
|
"rustyline",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -161,6 +190,36 @@ dependencies = [
|
|||||||
"void",
|
"void",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -303,6 +362,17 @@ dependencies = [
|
|||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rug"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6cfccfa888f22369385e0fc5f37a37fca05782fc653df5fe7de0934cbe66632"
|
||||||
|
dependencies = [
|
||||||
|
"az",
|
||||||
|
"gmp-mpfr-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-argon2"
|
name = "rust-argon2"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -14,3 +14,5 @@ panic = "abort"
|
|||||||
rustyline = "6.1.2"
|
rustyline = "6.1.2"
|
||||||
phf = { version = "0.8", features = ["macros"] }
|
phf = { version = "0.8", features = ["macros"] }
|
||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
|
bigdecimal = "0.1.2"
|
||||||
|
rug = "1.9.0"
|
@ -2,21 +2,25 @@ use crate::ast::{compare_enums, Expr, Stmt, Unit};
|
|||||||
use crate::lexer::TokenKind;
|
use crate::lexer::TokenKind;
|
||||||
use crate::prelude;
|
use crate::prelude;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
|
use rug::ops::Pow;
|
||||||
|
use rug::Float;
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
symbol_table: &'a mut SymbolTable,
|
symbol_table: &'a mut SymbolTable,
|
||||||
angle_unit: Unit,
|
angle_unit: Unit,
|
||||||
|
precision: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
pub fn new(angle_unit: Unit, symbol_table: &'a mut SymbolTable) -> Self {
|
pub fn new(symbol_table: &'a mut SymbolTable, angle_unit: Unit, precision: u32) -> Self {
|
||||||
Context {
|
Context {
|
||||||
angle_unit: angle_unit.clone(),
|
angle_unit: angle_unit.clone(),
|
||||||
symbol_table,
|
symbol_table,
|
||||||
|
precision,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret(&mut self, statements: Vec<Stmt>) -> Result<Option<f64>, String> {
|
pub fn interpret(&mut self, statements: Vec<Stmt>) -> Result<Option<Float>, String> {
|
||||||
for (i, stmt) in statements.iter().enumerate() {
|
for (i, stmt) in statements.iter().enumerate() {
|
||||||
let value = eval_stmt(self, stmt);
|
let value = eval_stmt(self, stmt);
|
||||||
|
|
||||||
@ -31,7 +35,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<f64, String> {
|
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<Float, String> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::VarDecl(identifier, _) => eval_var_decl_stmt(context, stmt, identifier),
|
Stmt::VarDecl(identifier, _) => eval_var_decl_stmt(context, stmt, identifier),
|
||||||
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(context),
|
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(context),
|
||||||
@ -39,20 +43,24 @@ fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<f64, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt, identifier: &str) -> Result<f64, String> {
|
fn eval_var_decl_stmt(
|
||||||
|
context: &mut Context,
|
||||||
|
stmt: &Stmt,
|
||||||
|
identifier: &str,
|
||||||
|
) -> Result<Float, String> {
|
||||||
context.symbol_table.insert(&identifier, stmt.clone());
|
context.symbol_table.insert(&identifier, stmt.clone());
|
||||||
Ok(0f64)
|
Ok(Float::with_val(context.precision, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_fn_decl_stmt(_: &mut Context) -> Result<f64, String> {
|
fn eval_fn_decl_stmt(context: &mut Context) -> Result<Float, String> {
|
||||||
Ok(0f64) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
Ok(Float::with_val(context.precision, 1)) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<Float, String> {
|
||||||
eval_expr(context, &expr)
|
eval_expr(context, &expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
fn eval_expr(context: &mut Context, expr: &Expr) -> Result<Float, String> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right),
|
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right),
|
||||||
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr),
|
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr),
|
||||||
@ -71,7 +79,7 @@ fn eval_binary_expr(
|
|||||||
left: &Expr,
|
left: &Expr,
|
||||||
op: &TokenKind,
|
op: &TokenKind,
|
||||||
right: &Expr,
|
right: &Expr,
|
||||||
) -> Result<f64, String> {
|
) -> Result<Float, String> {
|
||||||
let left = eval_expr(context, &left)?;
|
let left = eval_expr(context, &left)?;
|
||||||
let right = eval_expr(context, &right)?;
|
let right = eval_expr(context, &right)?;
|
||||||
|
|
||||||
@ -80,22 +88,25 @@ fn eval_binary_expr(
|
|||||||
TokenKind::Minus => left - right,
|
TokenKind::Minus => left - right,
|
||||||
TokenKind::Star => left * right,
|
TokenKind::Star => left * right,
|
||||||
TokenKind::Slash => left / right,
|
TokenKind::Slash => left / right,
|
||||||
TokenKind::Power => left.powf(right),
|
TokenKind::Power => left.pow(right),
|
||||||
_ => 0f64,
|
_ => Float::with_val(1, 1),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_unary_expr(context: &mut Context, op: &TokenKind, expr: &Expr) -> Result<f64, String> {
|
fn eval_unary_expr(context: &mut Context, op: &TokenKind, expr: &Expr) -> Result<Float, String> {
|
||||||
let expr_value = eval_expr(context, &expr)?.clone();
|
let expr_value = eval_expr(context, &expr)?.clone();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
TokenKind::Minus => Ok(-expr_value),
|
TokenKind::Minus => Ok(-expr_value),
|
||||||
TokenKind::Exclamation => Ok(prelude::special_funcs::factorial(expr_value as i32) as f64),
|
TokenKind::Exclamation => Ok(Float::with_val(
|
||||||
|
context.precision,
|
||||||
|
prelude::special_funcs::factorial(expr_value),
|
||||||
|
)),
|
||||||
_ => Err(String::from("Invalid operator for unary expression.")),
|
_ => Err(String::from("Invalid operator for unary expression.")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<f64, String> {
|
fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<Float, String> {
|
||||||
let x = eval_expr(context, &expr);
|
let x = eval_expr(context, &expr);
|
||||||
let unit = kind.to_unit()?;
|
let unit = kind.to_unit()?;
|
||||||
|
|
||||||
@ -108,13 +119,15 @@ fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Resul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match unit {
|
/*match unit {
|
||||||
Unit::Degrees => Ok(x?.to_radians()),
|
Unit::Degrees => Ok(x?.to_radians()),
|
||||||
Unit::Radians => Ok(x?.to_degrees()),
|
Unit::Radians => Ok(x?.to_degrees()),
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<f64, String> {
|
fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<Float, String> {
|
||||||
// If there is a constant with this name, return a literal expression with its value
|
// If there is a constant with this name, return a literal expression with its value
|
||||||
if let Some(value) = prelude::CONSTANTS.get(identifier) {
|
if let Some(value) = prelude::CONSTANTS.get(identifier) {
|
||||||
return eval_expr(context, &Expr::Literal(value.to_string()));
|
return eval_expr(context, &Expr::Literal(value.to_string()));
|
||||||
@ -128,14 +141,14 @@ fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<f64, String>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_literal_expr(_: &mut Context, value: &str) -> Result<f64, String> {
|
fn eval_literal_expr(context: &mut Context, value: &str) -> Result<Float, String> {
|
||||||
match value.parse() {
|
match Float::parse(value) {
|
||||||
Ok(parsed_value) => Ok(parsed_value),
|
Ok(parsed_value) => Ok(Float::with_val(context.precision, parsed_value)),
|
||||||
Err(_) => Err(format!("Invalid number literal: '{}'.", value)),
|
Err(_) => Err(format!("Invalid number literal: '{}'.", value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_group_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
fn eval_group_expr(context: &mut Context, expr: &Expr) -> Result<Float, String> {
|
||||||
eval_expr(context, expr)
|
eval_expr(context, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +156,7 @@ fn eval_fn_call_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: &str,
|
identifier: &str,
|
||||||
expressions: &Vec<Expr>,
|
expressions: &Vec<Expr>,
|
||||||
) -> Result<f64, String> {
|
) -> Result<Float, String> {
|
||||||
// Prelude
|
// Prelude
|
||||||
let prelude_func = match expressions.len() {
|
let prelude_func = match expressions.len() {
|
||||||
1 => {
|
1 => {
|
||||||
@ -164,7 +177,7 @@ fn eval_fn_call_expr(
|
|||||||
|
|
||||||
// Special functions
|
// Special functions
|
||||||
match identifier {
|
match identifier {
|
||||||
"sum" => {
|
"sum" | "Σ" => {
|
||||||
// Make sure exactly 3 arguments were supplied.
|
// Make sure exactly 3 arguments were supplied.
|
||||||
if expressions.len() != 3 {
|
if expressions.len() != 3 {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
@ -173,9 +186,9 @@ fn eval_fn_call_expr(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = eval_expr(context, &expressions[0])? as i32;
|
let start = eval_expr(context, &expressions[0])?.to_f64() as i128;
|
||||||
let end = eval_expr(context, &expressions[1])? as i32;
|
let end = eval_expr(context, &expressions[1])?.to_f64() as i128;
|
||||||
let mut sum = 0f64;
|
let mut sum = Float::with_val(context.precision, 0);
|
||||||
|
|
||||||
for n in start..=end {
|
for n in start..=end {
|
||||||
let n_expr = Expr::Literal(String::from(n.to_string()));
|
let n_expr = Expr::Literal(String::from(n.to_string()));
|
||||||
|
54
src/lexer.rs
54
src/lexer.rs
@ -51,7 +51,7 @@ impl<'a> Lexer<'a> {
|
|||||||
// If there isn't already an EOF token, add it.
|
// If there isn't already an EOF token, add it.
|
||||||
if let TokenKind::EOF = tokens.last().unwrap().kind {
|
if let TokenKind::EOF = tokens.last().unwrap().kind {
|
||||||
} else {
|
} else {
|
||||||
tokens.push(lexer.build(TokenKind::EOF, ""));
|
tokens.push(build(TokenKind::EOF, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens
|
tokens
|
||||||
@ -64,7 +64,7 @@ impl<'a> Lexer<'a> {
|
|||||||
self.advance();
|
self.advance();
|
||||||
|
|
||||||
if self.is_at_end() {
|
if self.is_at_end() {
|
||||||
return self.build(TokenKind::EOF, "");
|
return build(TokenKind::EOF, "");
|
||||||
} else {
|
} else {
|
||||||
c = self.peek();
|
c = self.peek();
|
||||||
}
|
}
|
||||||
@ -73,47 +73,47 @@ impl<'a> Lexer<'a> {
|
|||||||
let token = match c {
|
let token = match c {
|
||||||
'+' => {
|
'+' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Plus, "")
|
build(TokenKind::Plus, "")
|
||||||
}
|
}
|
||||||
'-' => {
|
'-' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Minus, "")
|
build(TokenKind::Minus, "")
|
||||||
}
|
}
|
||||||
'*' => {
|
'*' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Star, "")
|
build(TokenKind::Star, "")
|
||||||
}
|
}
|
||||||
'/' => {
|
'/' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Slash, "")
|
build(TokenKind::Slash, "")
|
||||||
}
|
}
|
||||||
'^' => {
|
'^' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Power, "")
|
build(TokenKind::Power, "")
|
||||||
}
|
}
|
||||||
'(' => {
|
'(' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::OpenParenthesis, "")
|
build(TokenKind::OpenParenthesis, "")
|
||||||
}
|
}
|
||||||
')' => {
|
')' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::ClosedParenthesis, "")
|
build(TokenKind::ClosedParenthesis, "")
|
||||||
}
|
}
|
||||||
'|' => {
|
'|' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Pipe, "")
|
build(TokenKind::Pipe, "")
|
||||||
}
|
}
|
||||||
'=' => {
|
'=' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Equals, "")
|
build(TokenKind::Equals, "")
|
||||||
}
|
}
|
||||||
'!' => {
|
'!' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Exclamation, "")
|
build(TokenKind::Exclamation, "")
|
||||||
}
|
}
|
||||||
',' => {
|
',' => {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Comma, "")
|
build(TokenKind::Comma, "")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if c.is_digit(10) {
|
if c.is_digit(10) {
|
||||||
@ -122,7 +122,7 @@ impl<'a> Lexer<'a> {
|
|||||||
self.next_identifier()
|
self.next_identifier()
|
||||||
} else {
|
} else {
|
||||||
self.advance();
|
self.advance();
|
||||||
self.build(TokenKind::Unknown, "")
|
build(TokenKind::Unknown, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -140,9 +140,9 @@ impl<'a> Lexer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(value) = str::from_utf8(&self.source[start..end]) {
|
if let Ok(value) = str::from_utf8(&self.source[start..end]) {
|
||||||
self.build(TokenKind::Literal, value)
|
build(TokenKind::Literal, value)
|
||||||
} else {
|
} else {
|
||||||
self.build(TokenKind::Unknown, "")
|
build(TokenKind::Unknown, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,16 +162,9 @@ impl<'a> Lexer<'a> {
|
|||||||
_ => TokenKind::Identifier,
|
_ => TokenKind::Identifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.build(kind, value)
|
build(kind, value)
|
||||||
} else {
|
} else {
|
||||||
self.build(TokenKind::Unknown, "")
|
build(TokenKind::Unknown, "")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build(&self, kind: TokenKind, value: &str) -> Token {
|
|
||||||
Token {
|
|
||||||
kind,
|
|
||||||
value: value.to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +181,13 @@ impl<'a> Lexer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_identifier(c: char) -> bool {
|
fn build(kind: TokenKind, value: &str) -> Token {
|
||||||
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨'
|
Token {
|
||||||
|
kind,
|
||||||
|
value: value.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_identifier(c: char) -> bool {
|
||||||
|
c.is_alphabetic() || c == '°' || c == '√' || c == '\'' || c == '¨' || c == 'Σ'
|
||||||
}
|
}
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -48,8 +48,14 @@ fn eval_repl(parser: &mut parser::Context, input: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn eval(parser: &mut parser::Context, input: &str) {
|
fn eval(parser: &mut parser::Context, input: &str) {
|
||||||
match parser::parse(parser, input, get_angle_unit()) {
|
match parser::parse(parser, input, get_angle_unit(), 53) {
|
||||||
Ok(Some(result)) => println!("{}", result),
|
Ok(Some(result)) => {
|
||||||
|
if result.clone().fract() == 0 {
|
||||||
|
println!("{}", result.to_integer().unwrap());
|
||||||
|
} else {
|
||||||
|
println!("{}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(None) => print!(""),
|
Ok(None) => print!(""),
|
||||||
Err(err) => println!("{}", Red.paint(err)),
|
Err(err) => println!("{}", Red.paint(err)),
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use crate::{
|
|||||||
lexer::{Lexer, Token, TokenKind},
|
lexer::{Lexer, Token, TokenKind},
|
||||||
symbol_table::SymbolTable,
|
symbol_table::SymbolTable,
|
||||||
};
|
};
|
||||||
|
use rug::Float;
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
//angle_unit: Unit,
|
//angle_unit: Unit,
|
||||||
@ -22,7 +23,12 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &mut Context, input: &str, angle_unit: Unit) -> Result<Option<f64>, String> {
|
pub fn parse(
|
||||||
|
context: &mut Context,
|
||||||
|
input: &str,
|
||||||
|
angle_unit: Unit,
|
||||||
|
precision: u32,
|
||||||
|
) -> Result<Option<Float>, String> {
|
||||||
context.tokens = Lexer::lex(input);
|
context.tokens = Lexer::lex(input);
|
||||||
context.pos = 0;
|
context.pos = 0;
|
||||||
|
|
||||||
@ -30,7 +36,8 @@ pub fn parse(context: &mut Context, input: &str, angle_unit: Unit) -> Result<Opt
|
|||||||
while !is_at_end(context) {
|
while !is_at_end(context) {
|
||||||
statements.push(parse_stmt(context)?);
|
statements.push(parse_stmt(context)?);
|
||||||
}
|
}
|
||||||
let mut interpreter = interpreter::Context::new(angle_unit, &mut context.symbol_table);
|
let mut interpreter =
|
||||||
|
interpreter::Context::new(&mut context.symbol_table, angle_unit, precision);
|
||||||
interpreter.interpret(statements)
|
interpreter.interpret(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
137
src/prelude.rs
137
src/prelude.rs
@ -1,3 +1,4 @@
|
|||||||
|
use rug::Float;
|
||||||
use FuncType::*;
|
use FuncType::*;
|
||||||
|
|
||||||
pub const CONSTANTS: phf::Map<&'static str, &'static str> = phf::phf_map! {
|
pub const CONSTANTS: phf::Map<&'static str, &'static str> = phf::phf_map! {
|
||||||
@ -66,12 +67,12 @@ enum FuncType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unary functions
|
// Unary functions
|
||||||
pub struct UnaryFuncInfo(fn(f64) -> f64, FuncType);
|
pub struct UnaryFuncInfo(fn(Float) -> Float, FuncType);
|
||||||
|
|
||||||
pub struct BinaryFuncInfo(fn(f64, f64) -> f64, FuncType);
|
pub struct BinaryFuncInfo(fn(Float, Float) -> Float, FuncType);
|
||||||
|
|
||||||
impl UnaryFuncInfo {
|
impl UnaryFuncInfo {
|
||||||
fn call(&self, x: f64, angle_unit: &Unit) -> f64 {
|
fn call(&self, x: Float, angle_unit: &Unit) -> Float {
|
||||||
let func = self.0;
|
let func = self.0;
|
||||||
match self.1 {
|
match self.1 {
|
||||||
FuncType::Trig => func(from_angle_unit(x, angle_unit)),
|
FuncType::Trig => func(from_angle_unit(x, angle_unit)),
|
||||||
@ -82,7 +83,7 @@ impl UnaryFuncInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryFuncInfo {
|
impl BinaryFuncInfo {
|
||||||
fn call(&self, x: f64, y: f64, angle_unit: &Unit) -> f64 {
|
fn call(&self, x: Float, y: Float, angle_unit: &Unit) -> Float {
|
||||||
let func = self.0;
|
let func = self.0;
|
||||||
match self.1 {
|
match self.1 {
|
||||||
FuncType::Trig => func(
|
FuncType::Trig => func(
|
||||||
@ -95,7 +96,7 @@ impl BinaryFuncInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_unary_func(name: &str, x: f64, angle_unit: &Unit) -> Option<f64> {
|
pub fn call_unary_func(name: &str, x: Float, angle_unit: &Unit) -> Option<Float> {
|
||||||
if let Some(func_info) = UNARY_FUNCS.get(name) {
|
if let Some(func_info) = UNARY_FUNCS.get(name) {
|
||||||
Some(func_info.call(x, &angle_unit))
|
Some(func_info.call(x, &angle_unit))
|
||||||
} else {
|
} else {
|
||||||
@ -103,7 +104,7 @@ pub fn call_unary_func(name: &str, x: f64, angle_unit: &Unit) -> Option<f64> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_binary_func(name: &str, x: f64, y: f64, angle_unit: &Unit) -> Option<f64> {
|
pub fn call_binary_func(name: &str, x: Float, y: Float, angle_unit: &Unit) -> Option<Float> {
|
||||||
if let Some(func_info) = BINARY_FUNCS.get(name) {
|
if let Some(func_info) = BINARY_FUNCS.get(name) {
|
||||||
Some(func_info.call(x, y, angle_unit))
|
Some(func_info.call(x, y, angle_unit))
|
||||||
} else {
|
} else {
|
||||||
@ -111,188 +112,196 @@ pub fn call_binary_func(name: &str, x: f64, y: f64, angle_unit: &Unit) -> Option
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
|
fn to_angle_unit(x: Float, angle_unit: &Unit) -> Float {
|
||||||
match angle_unit {
|
match angle_unit {
|
||||||
Unit::Radians => x,
|
Unit::Radians => x,
|
||||||
Unit::Degrees => x.to_degrees(),
|
Unit::Degrees => special_funcs::to_degrees(x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
|
fn from_angle_unit(x: Float, angle_unit: &Unit) -> Float {
|
||||||
match angle_unit {
|
match angle_unit {
|
||||||
Unit::Radians => x,
|
Unit::Radians => x,
|
||||||
Unit::Degrees => x.to_radians(),
|
Unit::Degrees => special_funcs::to_radians(x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod special_funcs {
|
pub mod special_funcs {
|
||||||
pub fn factorial(x: i32) -> i32 {
|
use rug::Float;
|
||||||
let mut value = 1;
|
|
||||||
for i in 1..=x {
|
|
||||||
value *= i;
|
|
||||||
}
|
|
||||||
|
|
||||||
value
|
pub fn factorial(x: Float) -> Float {
|
||||||
|
((x + 1) as Float).gamma()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_degrees(x: Float) -> Float {
|
||||||
|
Float::with_val(10, x.to_f64().to_degrees())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_radians(x: Float) -> Float {
|
||||||
|
Float::with_val(10, x.to_f64().to_radians())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod funcs {
|
mod funcs {
|
||||||
pub fn abs(x: f64) -> f64 {
|
use rug::ops::Pow;
|
||||||
|
use rug::Float;
|
||||||
|
|
||||||
|
pub fn abs(x: Float) -> Float {
|
||||||
x.abs()
|
x.abs()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acos(x: f64) -> f64 {
|
pub fn acos(x: Float) -> Float {
|
||||||
x.acos()
|
x.acos()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acosh(x: f64) -> f64 {
|
pub fn acosh(x: Float) -> Float {
|
||||||
x.acosh()
|
x.acosh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acot(x: f64) -> f64 {
|
pub fn acot(x: Float) -> Float {
|
||||||
(1f64 / x).atan()
|
(1f64 / x).atan()
|
||||||
}
|
}
|
||||||
pub fn acoth(x: f64) -> f64 {
|
pub fn acoth(x: Float) -> Float {
|
||||||
(1f64 / x).atanh()
|
(1f64 / x).atanh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acosec(x: f64) -> f64 {
|
pub fn acosec(x: Float) -> Float {
|
||||||
(1f64 / x).asin()
|
(1f64 / x).asin()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acosech(x: f64) -> f64 {
|
pub fn acosech(x: Float) -> Float {
|
||||||
(1f64 / x).asinh()
|
(1f64 / x).asinh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asec(x: f64) -> f64 {
|
pub fn asec(x: Float) -> Float {
|
||||||
(1f64 / x).acos()
|
(1f64 / x).acos()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asech(x: f64) -> f64 {
|
pub fn asech(x: Float) -> Float {
|
||||||
(1f64 / x).acosh()
|
(1f64 / x).acosh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asin(x: f64) -> f64 {
|
pub fn asin(x: Float) -> Float {
|
||||||
x.asin()
|
x.asin()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asinh(x: f64) -> f64 {
|
pub fn asinh(x: Float) -> Float {
|
||||||
x.asinh()
|
x.asinh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn atan(x: f64) -> f64 {
|
pub fn atan(x: Float) -> Float {
|
||||||
x.atan()
|
x.atan()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn atanh(x: f64) -> f64 {
|
pub fn atanh(x: Float) -> Float {
|
||||||
x.atanh()
|
x.atanh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cbrt(x: f64) -> f64 {
|
pub fn cbrt(x: Float) -> Float {
|
||||||
x.cbrt()
|
x.cbrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ceil(x: f64) -> f64 {
|
pub fn ceil(x: Float) -> Float {
|
||||||
x.ceil()
|
x.ceil()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cos(x: f64) -> f64 {
|
pub fn cos(x: Float) -> Float {
|
||||||
x.cos()
|
x.cos()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cosh(x: f64) -> f64 {
|
pub fn cosh(x: Float) -> Float {
|
||||||
x.cos()
|
x.cos()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cosec(x: f64) -> f64 {
|
pub fn cosec(x: Float) -> Float {
|
||||||
1f64 / x.sin()
|
1f64 / x.sin()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cosech(x: f64) -> f64 {
|
pub fn cosech(x: Float) -> Float {
|
||||||
1f64 / x.sinh()
|
1f64 / x.sinh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cot(x: f64) -> f64 {
|
pub fn cot(x: Float) -> Float {
|
||||||
x.cos() / x.sin()
|
x.clone().cos() / x.sin()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn coth(x: f64) -> f64 {
|
pub fn coth(x: Float) -> Float {
|
||||||
x.cosh() / x.sinh()
|
x.clone().cosh() / x.sinh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exp(x: f64) -> f64 {
|
pub fn exp(x: Float) -> Float {
|
||||||
x.exp()
|
x.exp()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn floor(x: f64) -> f64 {
|
pub fn floor(x: Float) -> Float {
|
||||||
x.floor()
|
x.floor()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frac(x: f64) -> f64 {
|
pub fn frac(x: Float) -> Float {
|
||||||
x.fract()
|
x.fract()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hyp(x: f64, y: f64) -> f64 {
|
pub fn hyp(x: Float, y: Float) -> Float {
|
||||||
x.hypot(y)
|
x.hypot(&y)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log(x: f64) -> f64 {
|
pub fn log(x: Float) -> Float {
|
||||||
x.log(10f64)
|
x.log10()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logx(x: f64, y: f64) -> f64 {
|
pub fn logx(x: Float, y: Float) -> Float {
|
||||||
x.log(y)
|
x.log10() / y.log10()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ln(x: f64) -> f64 {
|
pub fn ln(x: Float) -> Float {
|
||||||
x.ln()
|
x.ln()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max(x: f64, y: f64) -> f64 {
|
pub fn max(x: Float, y: Float) -> Float {
|
||||||
x.max(y)
|
x.max(&y)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min(x: f64, y: f64) -> f64 {
|
pub fn min(x: Float, y: Float) -> Float {
|
||||||
x.min(y)
|
x.min(&y)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn round(x: f64) -> f64 {
|
pub fn round(x: Float) -> Float {
|
||||||
x.round()
|
x.round()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sec(x: f64) -> f64 {
|
pub fn sec(x: Float) -> Float {
|
||||||
1f64 / x.cos()
|
1f64 / x.cos()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sech(x: f64) -> f64 {
|
pub fn sech(x: Float) -> Float {
|
||||||
1f64 / x.cosh()
|
1f64 / x.cosh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sin(x: f64) -> f64 {
|
pub fn sin(x: Float) -> Float {
|
||||||
x.sin()
|
x.sin()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sinh(x: f64) -> f64 {
|
pub fn sinh(x: Float) -> Float {
|
||||||
x.sinh()
|
x.sinh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sqrt(x: f64) -> f64 {
|
pub fn sqrt(x: Float) -> Float {
|
||||||
x.sqrt()
|
x.sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nth_sqrt(x: f64, n: f64) -> f64 {
|
pub fn nth_sqrt(x: Float, n: Float) -> Float {
|
||||||
x.powf(1f64 / n)
|
x.pow(Float::with_val(1, 1) / n)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tan(x: f64) -> f64 {
|
pub fn tan(x: Float) -> Float {
|
||||||
x.tan()
|
x.tan()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tanh(x: f64) -> f64 {
|
pub fn tanh(x: Float) -> Float {
|
||||||
x.tanh()
|
x.tanh()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trunc(x: f64) -> f64 {
|
pub fn trunc(x: Float) -> Float {
|
||||||
x.trunc()
|
x.trunc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user