mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-12 17:40:52 +01:00
Fix floating point literal conversion
Signed-off-by: dvishal485 <dvishal485@gmail.com>
This commit is contained in:
parent
bdb7502e9d
commit
0281e921d5
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::{ConditionalPiece, Expr, Identifier, RangedVar, Stmt},
|
ast::{ConditionalPiece, Expr, Identifier, RangedVar, Stmt},
|
||||||
errors::KalkError,
|
errors::KalkError,
|
||||||
inverter,
|
float, inverter,
|
||||||
lexer::TokenKind,
|
lexer::TokenKind,
|
||||||
parser, prelude,
|
parser, prelude,
|
||||||
symbol_table::SymbolTable,
|
symbol_table::SymbolTable,
|
||||||
@ -102,7 +102,7 @@ fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, KalkErr
|
|||||||
context,
|
context,
|
||||||
Expr::Binary(
|
Expr::Binary(
|
||||||
Box::new(Expr::Binary(
|
Box::new(Expr::Binary(
|
||||||
Box::new(Expr::Literal(0f64)),
|
Box::new(Expr::Literal(float!(0f64))),
|
||||||
TokenKind::Plus,
|
TokenKind::Plus,
|
||||||
Box::new(Expr::FnCall(identifier, arguments)),
|
Box::new(Expr::FnCall(identifier, arguments)),
|
||||||
)),
|
)),
|
||||||
@ -432,7 +432,7 @@ fn analyse_comparison_with_var(
|
|||||||
ranged_var.min = Expr::Binary(
|
ranged_var.min = Expr::Binary(
|
||||||
Box::new(right),
|
Box::new(right),
|
||||||
TokenKind::Plus,
|
TokenKind::Plus,
|
||||||
Box::new(Expr::Literal(1f64)),
|
Box::new(Expr::Literal(float!(1f64))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TokenKind::LessThan => {
|
TokenKind::LessThan => {
|
||||||
@ -445,7 +445,7 @@ fn analyse_comparison_with_var(
|
|||||||
ranged_var.max = Expr::Binary(
|
ranged_var.max = Expr::Binary(
|
||||||
Box::new(right),
|
Box::new(right),
|
||||||
TokenKind::Plus,
|
TokenKind::Plus,
|
||||||
Box::new(Expr::Literal(1f64)),
|
Box::new(Expr::Literal(float!(1f64))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -456,9 +456,9 @@ fn analyse_comparison_with_var(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(Expr::Binary(
|
Ok(Expr::Binary(
|
||||||
Box::new(Expr::Literal(0f64)),
|
Box::new(Expr::Literal(float!(0f64))),
|
||||||
TokenKind::Equals,
|
TokenKind::Equals,
|
||||||
Box::new(Expr::Literal(0f64)),
|
Box::new(Expr::Literal(float!(0f64))),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,13 +578,23 @@ fn with_adjacent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rug")]
|
||||||
|
fn parse_float_from_str(s: &str) -> rug::Float {
|
||||||
|
rug::Float::parse(s).map_or(float!(f64::NAN), |valid| float!(valid))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rug"))]
|
||||||
|
fn parse_float_from_str(s: &str) -> f64 {
|
||||||
|
s.parse::<f64>().unwrap_or(f64::NAN)
|
||||||
|
}
|
||||||
|
|
||||||
fn build_indexed_var(context: &mut Context, identifier: Identifier) -> Result<Expr, KalkError> {
|
fn build_indexed_var(context: &mut Context, identifier: Identifier) -> Result<Expr, KalkError> {
|
||||||
let underscore_pos = identifier.pure_name.find('_').unwrap();
|
let underscore_pos = identifier.pure_name.find('_').unwrap();
|
||||||
let var_name = &identifier.pure_name[0..underscore_pos];
|
let var_name = &identifier.pure_name[0..underscore_pos];
|
||||||
let lowered = &identifier.pure_name[underscore_pos + 1..];
|
let lowered = &identifier.pure_name[underscore_pos + 1..];
|
||||||
let lowered_expr =
|
let lowered_expr =
|
||||||
if !lowered.is_empty() && lowered.chars().next().unwrap_or('\0').is_ascii_digit() {
|
if !lowered.is_empty() && lowered.chars().next().unwrap_or('\0').is_ascii_digit() {
|
||||||
Expr::Literal(lowered.parse::<f64>().unwrap_or(f64::NAN))
|
Expr::Literal(parse_float_from_str(lowered))
|
||||||
} else {
|
} else {
|
||||||
build_var(context, lowered)
|
build_var(context, lowered)
|
||||||
};
|
};
|
||||||
@ -702,8 +712,8 @@ fn build_var(context: &mut Context, name: &str) -> Expr {
|
|||||||
if let Some(vars) = context.comprehension_vars.as_mut() {
|
if let Some(vars) = context.comprehension_vars.as_mut() {
|
||||||
vars.push(RangedVar {
|
vars.push(RangedVar {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
max: Expr::Literal(0f64),
|
max: Expr::Literal(float!(0f64)),
|
||||||
min: Expr::Literal(0f64),
|
min: Expr::Literal(float!(0f64)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -766,3 +776,15 @@ fn analyse_fn(
|
|||||||
|
|
||||||
Ok(Expr::FnCall(identifier, analysed_arguments))
|
Ok(Expr::FnCall(identifier, analysed_arguments))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[cfg(test)]
|
||||||
|
// mod test {
|
||||||
|
// use test_case::test_case;
|
||||||
|
// #[test_case("1")]
|
||||||
|
// #[test_case("500000000000000002")]
|
||||||
|
// #[test_case("-5000000000000000002")]
|
||||||
|
// fn test_float_from_str(s: &str) {
|
||||||
|
// // failing assertion to test this
|
||||||
|
// assert_eq!(crate::analysis::parse_float_from_str(s), crate::float!(1f64));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -19,6 +19,9 @@ pub enum Expr {
|
|||||||
Var(Identifier),
|
Var(Identifier),
|
||||||
Group(Box<Expr>),
|
Group(Box<Expr>),
|
||||||
FnCall(Identifier, Vec<Expr>),
|
FnCall(Identifier, Vec<Expr>),
|
||||||
|
#[cfg(feature="rug")]
|
||||||
|
Literal(rug::Float),
|
||||||
|
#[cfg(not(feature="rug"))]
|
||||||
Literal(f64),
|
Literal(f64),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Piecewise(Vec<ConditionalPiece>),
|
Piecewise(Vec<ConditionalPiece>),
|
||||||
@ -100,16 +103,16 @@ impl Identifier {
|
|||||||
pub fn build_literal_ast(kalk_value: &crate::kalk_value::KalkValue) -> Expr {
|
pub fn build_literal_ast(kalk_value: &crate::kalk_value::KalkValue) -> Expr {
|
||||||
if kalk_value.has_imaginary() {
|
if kalk_value.has_imaginary() {
|
||||||
Expr::Binary(
|
Expr::Binary(
|
||||||
Box::new(Expr::Literal(kalk_value.to_f64())),
|
Box::new(Expr::Literal(kalk_value.to_float())),
|
||||||
TokenKind::Plus,
|
TokenKind::Plus,
|
||||||
Box::new(Expr::Binary(
|
Box::new(Expr::Binary(
|
||||||
Box::new(Expr::Literal(kalk_value.imaginary_to_f64())),
|
Box::new(Expr::Literal(kalk_value.imaginary_to_float())),
|
||||||
TokenKind::Star,
|
TokenKind::Star,
|
||||||
Box::new(Expr::Var(Identifier::from_full_name("i"))),
|
Box::new(Expr::Var(Identifier::from_full_name("i"))),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Expr::Literal(kalk_value.to_f64())
|
Expr::Literal(kalk_value.to_float())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,8 @@ pub(crate) fn eval_expr(
|
|||||||
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr, unit),
|
Expr::Unary(op, expr) => eval_unary_expr(context, op, expr, unit),
|
||||||
Expr::Unit(identifier, expr) => eval_unit_expr(context, identifier, expr),
|
Expr::Unit(identifier, expr) => eval_unit_expr(context, identifier, expr),
|
||||||
Expr::Var(identifier) => eval_var_expr(context, identifier, unit),
|
Expr::Var(identifier) => eval_var_expr(context, identifier, unit),
|
||||||
Expr::Literal(value) => eval_literal_expr(context, *value, unit),
|
// copy trait for Float?
|
||||||
|
Expr::Literal(value) => eval_literal_expr(context, value.clone(), unit),
|
||||||
Expr::Boolean(value) => Ok(KalkValue::Boolean(*value)),
|
Expr::Boolean(value) => Ok(KalkValue::Boolean(*value)),
|
||||||
Expr::Group(expr) => eval_group_expr(context, expr, unit),
|
Expr::Group(expr) => eval_group_expr(context, expr, unit),
|
||||||
Expr::FnCall(identifier, expressions) => {
|
Expr::FnCall(identifier, expressions) => {
|
||||||
@ -287,7 +288,7 @@ fn eval_var_expr(
|
|||||||
) -> Result<KalkValue, KalkError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
// 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.full_name.as_ref() as &str) {
|
if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
|
||||||
return eval_expr(context, &Expr::Literal(*value), unit);
|
return eval_expr(context, &Expr::Literal(float!(*value)), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sum_variables) = &context.sum_variables {
|
if let Some(sum_variables) = &context.sum_variables {
|
||||||
@ -315,7 +316,7 @@ fn eval_var_expr(
|
|||||||
#[cfg(feature = "rug")]
|
#[cfg(feature = "rug")]
|
||||||
fn eval_literal_expr(
|
fn eval_literal_expr(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
value: f64,
|
value: rug::Float,
|
||||||
unit: Option<&String>,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, KalkError> {
|
) -> Result<KalkValue, KalkError> {
|
||||||
let mut float = float!(value);
|
let mut float = float!(value);
|
||||||
@ -771,7 +772,7 @@ fn eval_comprehension(
|
|||||||
let var = vars.first().unwrap();
|
let var = vars.first().unwrap();
|
||||||
context.symbol_table.insert(Stmt::VarDecl(
|
context.symbol_table.insert(Stmt::VarDecl(
|
||||||
Identifier::from_full_name(&var.name),
|
Identifier::from_full_name(&var.name),
|
||||||
Box::new(Expr::Literal(0f64)),
|
Box::new(Expr::Literal(float!(0f64))),
|
||||||
));
|
));
|
||||||
|
|
||||||
let min = eval_expr(context, &var.min, None)?.to_f64() as i32;
|
let min = eval_expr(context, &var.min, None)?.to_f64() as i32;
|
||||||
@ -781,7 +782,7 @@ fn eval_comprehension(
|
|||||||
for i in min..max {
|
for i in min..max {
|
||||||
context.symbol_table.set(Stmt::VarDecl(
|
context.symbol_table.set(Stmt::VarDecl(
|
||||||
Identifier::from_full_name(&var.name),
|
Identifier::from_full_name(&var.name),
|
||||||
Box::new(Expr::Literal(i as f64)),
|
Box::new(Expr::Literal(float!(i))),
|
||||||
));
|
));
|
||||||
|
|
||||||
if conditions.len() > 1 {
|
if conditions.len() > 1 {
|
||||||
@ -852,7 +853,7 @@ mod tests {
|
|||||||
binary(
|
binary(
|
||||||
var(crate::parser::DECL_UNIT),
|
var(crate::parser::DECL_UNIT),
|
||||||
TokenKind::Star,
|
TokenKind::Star,
|
||||||
literal(180f64),
|
f64_to_float_literal(180f64),
|
||||||
),
|
),
|
||||||
TokenKind::Slash,
|
TokenKind::Slash,
|
||||||
var("pi"),
|
var("pi"),
|
||||||
@ -864,7 +865,7 @@ mod tests {
|
|||||||
binary(
|
binary(
|
||||||
binary(var(crate::parser::DECL_UNIT), TokenKind::Star, var("pi")),
|
binary(var(crate::parser::DECL_UNIT), TokenKind::Star, var("pi")),
|
||||||
TokenKind::Slash,
|
TokenKind::Slash,
|
||||||
literal(180f64),
|
f64_to_float_literal(180f64),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -910,24 +911,25 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_literal() {
|
fn test_literal() {
|
||||||
let stmt = Stmt::Expr(literal(1f64));
|
let stmt = Stmt::Expr(f64_to_float_literal(1f64));
|
||||||
|
|
||||||
assert_eq!(interpret(stmt).unwrap().unwrap().to_f64(), 1f64);
|
assert_eq!(interpret(stmt).unwrap().unwrap().to_f64(), 1f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_binary() {
|
fn test_binary() {
|
||||||
let add = Stmt::Expr(binary(literal(2f64), Plus, literal(3f64)));
|
let add = Stmt::Expr(binary(f64_to_float_literal(2f64), Plus, f64_to_float_literal(3f64)));
|
||||||
let sub = Stmt::Expr(binary(literal(2f64), Minus, literal(3f64)));
|
let sub = Stmt::Expr(binary(f64_to_float_literal(2f64), Minus, f64_to_float_literal(3f64)));
|
||||||
let mul = Stmt::Expr(binary(literal(2f64), Star, literal(3f64)));
|
let mul = Stmt::Expr(binary(f64_to_float_literal(2f64), Star, f64_to_float_literal(3f64)));
|
||||||
let div = Stmt::Expr(binary(literal(2f64), Slash, literal(4f64)));
|
let div = Stmt::Expr(binary(f64_to_float_literal(2f64), Slash, f64_to_float_literal(4f64)));
|
||||||
let pow = Stmt::Expr(binary(literal(2f64), Power, literal(3f64)));
|
let pow = Stmt::Expr(binary(f64_to_float_literal(2f64), Power, f64_to_float_literal(3f64)));
|
||||||
let equals = Stmt::Expr(binary(literal(2f64), Equals, literal(3f64)));
|
let equals = Stmt::Expr(binary(f64_to_float_literal(2f64), Equals, f64_to_float_literal(3f64)));
|
||||||
let not_equals = Stmt::Expr(binary(literal(2f64), NotEquals, literal(3f64)));
|
let not_equals = Stmt::Expr(binary(f64_to_float_literal(2f64), NotEquals, f64_to_float_literal(3f64)));
|
||||||
let greater_than = Stmt::Expr(binary(literal(2f64), GreaterThan, literal(3f64)));
|
let greater_than = Stmt::Expr(binary(f64_to_float_literal(2f64), GreaterThan, f64_to_float_literal(3f64)));
|
||||||
let less_than = Stmt::Expr(binary(literal(2f64), LessThan, literal(3f64)));
|
let less_than = Stmt::Expr(binary(f64_to_float_literal(2f64), LessThan, f64_to_float_literal(3f64)));
|
||||||
let greater_or_equals = Stmt::Expr(binary(literal(2f64), GreaterOrEquals, literal(3f64)));
|
let greater_or_equals =
|
||||||
let less_or_equals = Stmt::Expr(binary(literal(2f64), LessOrEquals, literal(3f64)));
|
Stmt::Expr(binary(f64_to_float_literal(2f64), GreaterOrEquals, f64_to_float_literal(3f64)));
|
||||||
|
let less_or_equals = Stmt::Expr(binary(f64_to_float_literal(2f64), LessOrEquals, f64_to_float_literal(3f64)));
|
||||||
|
|
||||||
assert_eq!(interpret(add).unwrap().unwrap().to_f64(), 5f64);
|
assert_eq!(interpret(add).unwrap().unwrap().to_f64(), 5f64);
|
||||||
assert_eq!(interpret(sub).unwrap().unwrap().to_f64(), -1f64);
|
assert_eq!(interpret(sub).unwrap().unwrap().to_f64(), -1f64);
|
||||||
@ -963,9 +965,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_percent() {
|
fn test_percent() {
|
||||||
let stmt = Stmt::Expr(binary(
|
let stmt = Stmt::Expr(binary(
|
||||||
literal(5f64),
|
f64_to_float_literal(5f64),
|
||||||
Percent,
|
Percent,
|
||||||
group(binary(literal(3f64), Plus, unary(Percent, literal(2f64)))),
|
group(binary(f64_to_float_literal(3f64), Plus, unary(Percent, f64_to_float_literal(2f64)))),
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(cmp(interpret(stmt).unwrap().unwrap(), 1.94f64));
|
assert!(cmp(interpret(stmt).unwrap().unwrap(), 1.94f64));
|
||||||
@ -973,8 +975,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unary() {
|
fn test_unary() {
|
||||||
let neg = Stmt::Expr(unary(Minus, literal(1f64)));
|
let neg = Stmt::Expr(unary(Minus, f64_to_float_literal(1f64)));
|
||||||
let fact = Stmt::Expr(unary(Exclamation, literal(5f64)));
|
let fact = Stmt::Expr(unary(Exclamation, f64_to_float_literal(5f64)));
|
||||||
|
|
||||||
assert_eq!(interpret(neg).unwrap().unwrap().to_f64(), -1f64);
|
assert_eq!(interpret(neg).unwrap().unwrap().to_f64(), -1f64);
|
||||||
assert_eq!(interpret(fact).unwrap().unwrap().to_f64(), 120f64);
|
assert_eq!(interpret(fact).unwrap().unwrap().to_f64(), 120f64);
|
||||||
@ -982,9 +984,9 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_angle_units() {
|
fn test_angle_units() {
|
||||||
let rad_explicit = Stmt::Expr(fn_call("sin", vec![*unit("rad", literal(1f64))]));
|
let rad_explicit = Stmt::Expr(fn_call("sin", vec![*unit("rad", f64_to_float_literal(1f64))]));
|
||||||
let deg_explicit = Stmt::Expr(fn_call("sin", vec![*unit("deg", literal(1f64))]));
|
let deg_explicit = Stmt::Expr(fn_call("sin", vec![*unit("deg", f64_to_float_literal(1f64))]));
|
||||||
let implicit = Stmt::Expr(fn_call("sin", vec![*literal(1f64)]));
|
let implicit = Stmt::Expr(fn_call("sin", vec![*f64_to_float_literal(1f64)]));
|
||||||
|
|
||||||
assert!(cmp(interpret(rad_explicit).unwrap().unwrap(), 0.84147098));
|
assert!(cmp(interpret(rad_explicit).unwrap().unwrap(), 0.84147098));
|
||||||
assert!(cmp(interpret(deg_explicit).unwrap().unwrap(), 0.01745240));
|
assert!(cmp(interpret(deg_explicit).unwrap().unwrap(), 0.01745240));
|
||||||
@ -1024,7 +1026,7 @@ mod tests {
|
|||||||
|
|
||||||
// Prepare by inserting a variable declaration in the symbol table.
|
// Prepare by inserting a variable declaration in the symbol table.
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
symbol_table.insert(var_decl("x", literal(1f64)));
|
symbol_table.insert(var_decl("x", f64_to_float_literal(1f64)));
|
||||||
|
|
||||||
let mut context = context(&mut symbol_table, "rad");
|
let mut context = context(&mut symbol_table, "rad");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1045,7 +1047,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_var_decl() {
|
fn test_var_decl() {
|
||||||
let stmt = var_decl("x", literal(1f64));
|
let stmt = var_decl("x", f64_to_float_literal(1f64));
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
context(&mut symbol_table, "rad")
|
context(&mut symbol_table, "rad")
|
||||||
.interpret(vec![stmt])
|
.interpret(vec![stmt])
|
||||||
@ -1056,14 +1058,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fn() {
|
fn test_fn() {
|
||||||
let stmt = Stmt::Expr(fn_call("f", vec![*literal(1f64)]));
|
let stmt = Stmt::Expr(fn_call("f", vec![*f64_to_float_literal(1f64)]));
|
||||||
|
|
||||||
// Prepare by inserting a variable declaration in the symbol table.
|
// Prepare by inserting a variable declaration in the symbol table.
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
symbol_table.insert(fn_decl(
|
symbol_table.insert(fn_decl(
|
||||||
"f",
|
"f",
|
||||||
vec![String::from("x")],
|
vec![String::from("x")],
|
||||||
binary(var("x"), TokenKind::Plus, literal(2f64)),
|
binary(var("x"), TokenKind::Plus, f64_to_float_literal(2f64)),
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut context = context(&mut symbol_table, "rad");
|
let mut context = context(&mut symbol_table, "rad");
|
||||||
@ -1075,7 +1077,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_undefined_fn() {
|
fn test_undefined_fn() {
|
||||||
let stmt = Stmt::Expr(fn_call("f", vec![*literal(1f64)]));
|
let stmt = Stmt::Expr(fn_call("f", vec![*f64_to_float_literal(1f64)]));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret(stmt),
|
interpret(stmt),
|
||||||
@ -1089,9 +1091,9 @@ mod tests {
|
|||||||
let stmt = Stmt::Expr(fn_call(
|
let stmt = Stmt::Expr(fn_call(
|
||||||
"sum",
|
"sum",
|
||||||
vec![
|
vec![
|
||||||
*binary(var("n"), TokenKind::Equals, literal(start)),
|
*binary(var("n"), TokenKind::Equals, f64_to_float_literal(start)),
|
||||||
*literal(to),
|
*f64_to_float_literal(to),
|
||||||
*binary(var("n"), TokenKind::Plus, literal(3f64)),
|
*binary(var("n"), TokenKind::Plus,f64_to_float_literal(3f64)),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -1103,10 +1105,10 @@ mod tests {
|
|||||||
let stmt = Stmt::Expr(fn_call(
|
let stmt = Stmt::Expr(fn_call(
|
||||||
"integrate",
|
"integrate",
|
||||||
vec![
|
vec![
|
||||||
*literal(2f64),
|
*f64_to_float_literal(2f64),
|
||||||
*literal(4f64),
|
*f64_to_float_literal(4f64),
|
||||||
*binary(
|
*binary(
|
||||||
binary(var("x"), TokenKind::Power, literal(3f64)),
|
binary(var("x"), TokenKind::Power, f64_to_float_literal(3f64)),
|
||||||
TokenKind::Star,
|
TokenKind::Star,
|
||||||
var("dx"),
|
var("dx"),
|
||||||
),
|
),
|
||||||
|
@ -116,7 +116,7 @@ fn invert_binary(
|
|||||||
symbol_table,
|
symbol_table,
|
||||||
left,
|
left,
|
||||||
&TokenKind::Plus,
|
&TokenKind::Plus,
|
||||||
&multiply_into(&Expr::Literal(-1f64), inside_group)?,
|
&multiply_into(&Expr::Literal(crate::float!(-1f64)), inside_group)?,
|
||||||
unknown_var,
|
unknown_var,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -303,7 +303,7 @@ fn invert_fn_call(
|
|||||||
Expr::Binary(
|
Expr::Binary(
|
||||||
Box::new(target_expr),
|
Box::new(target_expr),
|
||||||
TokenKind::Power,
|
TokenKind::Power,
|
||||||
Box::new(Expr::Literal(2f64)),
|
Box::new(Expr::Literal(crate::float!(2f64))),
|
||||||
),
|
),
|
||||||
symbol_table,
|
symbol_table,
|
||||||
&arguments[0],
|
&arguments[0],
|
||||||
@ -456,49 +456,49 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_binary() {
|
fn test_binary() {
|
||||||
let ladd = binary(decl_unit(), Plus, literal(1f64));
|
let ladd = binary(decl_unit(), Plus, f64_to_float_literal(1f64));
|
||||||
let lsub = binary(decl_unit(), Minus, literal(1f64));
|
let lsub = binary(decl_unit(), Minus, f64_to_float_literal(1f64));
|
||||||
let lmul = binary(decl_unit(), Star, literal(1f64));
|
let lmul = binary(decl_unit(), Star, f64_to_float_literal(1f64));
|
||||||
let ldiv = binary(decl_unit(), Slash, literal(1f64));
|
let ldiv = binary(decl_unit(), Slash, f64_to_float_literal(1f64));
|
||||||
|
|
||||||
let radd = binary(literal(1f64), Plus, decl_unit());
|
let radd = binary(f64_to_float_literal(1f64), Plus, decl_unit());
|
||||||
let rsub = binary(literal(1f64), Minus, decl_unit());
|
let rsub = binary(f64_to_float_literal(1f64), Minus, decl_unit());
|
||||||
let rmul = binary(literal(1f64), Star, decl_unit());
|
let rmul = binary(f64_to_float_literal(1f64), Star, decl_unit());
|
||||||
let rdiv = binary(literal(1f64), Slash, decl_unit());
|
let rdiv = binary(f64_to_float_literal(1f64), Slash, decl_unit());
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ladd.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
ladd.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Minus, literal(1f64))
|
*binary(decl_unit(), Minus, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lsub.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
lsub.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Plus, literal(1f64))
|
*binary(decl_unit(), Plus, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lmul.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
lmul.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Slash, literal(1f64))
|
*binary(decl_unit(), Slash, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ldiv.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
ldiv.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Star, literal(1f64))
|
*binary(decl_unit(), Star, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
radd.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
radd.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Minus, literal(1f64))
|
*binary(decl_unit(), Minus, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rsub.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
rsub.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*unary(Minus, binary(decl_unit(), Plus, literal(1f64)))
|
*unary(Minus, binary(decl_unit(), Plus, f64_to_float_literal(1f64)))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rmul.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
rmul.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Slash, literal(1f64))
|
*binary(decl_unit(), Slash, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rdiv.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
rdiv.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(decl_unit(), Star, literal(1f64))
|
*binary(decl_unit(), Star, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,14 +514,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_fn_call() {
|
fn test_fn_call() {
|
||||||
let call_with_literal = binary(fn_call("f", vec![*literal(2f64)]), Plus, decl_unit());
|
let call_with_literal = binary(fn_call("f", vec![*f64_to_float_literal(2f64)]), Plus, decl_unit());
|
||||||
let call_with_decl_unit = fn_call("f", vec![*decl_unit()]);
|
let call_with_decl_unit = fn_call("f", vec![*decl_unit()]);
|
||||||
let call_with_decl_unit_and_literal =
|
let call_with_decl_unit_and_literal =
|
||||||
fn_call("f", vec![*binary(decl_unit(), Plus, literal(2f64))]);
|
fn_call("f", vec![*binary(decl_unit(), Plus, f64_to_float_literal(2f64))]);
|
||||||
let decl = fn_decl(
|
let decl = fn_decl(
|
||||||
"f",
|
"f",
|
||||||
vec![String::from("x")],
|
vec![String::from("x")],
|
||||||
binary(var("x"), Plus, literal(1f64)),
|
binary(var("x"), Plus, f64_to_float_literal(1f64)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
@ -530,22 +530,22 @@ mod tests {
|
|||||||
call_with_literal
|
call_with_literal
|
||||||
.invert(&mut symbol_table, DECL_UNIT)
|
.invert(&mut symbol_table, DECL_UNIT)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
*binary(decl_unit(), Minus, fn_call("f", vec![*literal(2f64)])),
|
*binary(decl_unit(), Minus, fn_call("f", vec![*f64_to_float_literal(2f64)])),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
call_with_decl_unit
|
call_with_decl_unit
|
||||||
.invert(&mut symbol_table, DECL_UNIT)
|
.invert(&mut symbol_table, DECL_UNIT)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
*binary(decl_unit(), Minus, literal(1f64))
|
*binary(decl_unit(), Minus, f64_to_float_literal(1f64))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
call_with_decl_unit_and_literal
|
call_with_decl_unit_and_literal
|
||||||
.invert(&mut symbol_table, DECL_UNIT)
|
.invert(&mut symbol_table, DECL_UNIT)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
*binary(
|
*binary(
|
||||||
binary(decl_unit(), Minus, literal(1f64)),
|
binary(decl_unit(), Minus, f64_to_float_literal(1f64)),
|
||||||
Minus,
|
Minus,
|
||||||
literal(2f64)
|
f64_to_float_literal(2f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -554,34 +554,34 @@ mod tests {
|
|||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_group() {
|
fn test_group() {
|
||||||
let group_x = binary(
|
let group_x = binary(
|
||||||
group(binary(decl_unit(), Plus, literal(3f64))),
|
group(binary(decl_unit(), Plus, f64_to_float_literal(3f64))),
|
||||||
Star,
|
Star,
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
);
|
);
|
||||||
let group_unary_minus = binary(
|
let group_unary_minus = binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Minus,
|
Minus,
|
||||||
group(binary(decl_unit(), Plus, literal(3f64))),
|
group(binary(decl_unit(), Plus, f64_to_float_literal(3f64))),
|
||||||
);
|
);
|
||||||
let x_group_add = binary(
|
let x_group_add = binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Star,
|
Star,
|
||||||
group(binary(decl_unit(), Plus, literal(3f64))),
|
group(binary(decl_unit(), Plus, f64_to_float_literal(3f64))),
|
||||||
);
|
);
|
||||||
let x_group_sub = binary(
|
let x_group_sub = binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Star,
|
Star,
|
||||||
group(binary(decl_unit(), Minus, literal(3f64))),
|
group(binary(decl_unit(), Minus, f64_to_float_literal(3f64))),
|
||||||
);
|
);
|
||||||
let x_group_mul = binary(
|
let x_group_mul = binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Star,
|
Star,
|
||||||
group(binary(decl_unit(), Star, literal(3f64))),
|
group(binary(decl_unit(), Star, f64_to_float_literal(3f64))),
|
||||||
);
|
);
|
||||||
let x_group_div = binary(
|
let x_group_div = binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Star,
|
Star,
|
||||||
group(binary(decl_unit(), Slash, literal(3f64))),
|
group(binary(decl_unit(), Slash, f64_to_float_literal(3f64))),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
@ -591,10 +591,10 @@ mod tests {
|
|||||||
binary(
|
binary(
|
||||||
decl_unit(),
|
decl_unit(),
|
||||||
Minus,
|
Minus,
|
||||||
binary(literal(2f64), Star, literal(3f64))
|
binary(f64_to_float_literal(2f64), Star, f64_to_float_literal(3f64))
|
||||||
),
|
),
|
||||||
Slash,
|
Slash,
|
||||||
literal(2f64)
|
f64_to_float_literal(2f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -603,12 +603,12 @@ mod tests {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
*binary(
|
*binary(
|
||||||
binary(
|
binary(
|
||||||
binary(decl_unit(), Minus, literal(2f64)),
|
binary(decl_unit(), Minus, f64_to_float_literal(2f64)),
|
||||||
Minus,
|
Minus,
|
||||||
binary(literal(-1f64), Star, literal(3f64))
|
binary(f64_to_float_literal(-1f64), Star, f64_to_float_literal(3f64))
|
||||||
),
|
),
|
||||||
Slash,
|
Slash,
|
||||||
literal(-1f64)
|
f64_to_float_literal(-1f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -617,10 +617,10 @@ mod tests {
|
|||||||
binary(
|
binary(
|
||||||
decl_unit(),
|
decl_unit(),
|
||||||
Minus,
|
Minus,
|
||||||
binary(literal(2f64), Star, literal(3f64))
|
binary(f64_to_float_literal(2f64), Star, f64_to_float_literal(3f64))
|
||||||
),
|
),
|
||||||
Slash,
|
Slash,
|
||||||
literal(2f64)
|
f64_to_float_literal(2f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -629,26 +629,26 @@ mod tests {
|
|||||||
binary(
|
binary(
|
||||||
decl_unit(),
|
decl_unit(),
|
||||||
Plus,
|
Plus,
|
||||||
binary(literal(2f64), Star, literal(3f64))
|
binary(f64_to_float_literal(2f64), Star, f64_to_float_literal(3f64))
|
||||||
),
|
),
|
||||||
Slash,
|
Slash,
|
||||||
literal(2f64)
|
f64_to_float_literal(2f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x_group_mul.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
x_group_mul.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(
|
*binary(
|
||||||
binary(decl_unit(), Slash, literal(3f64)),
|
binary(decl_unit(), Slash, f64_to_float_literal(3f64)),
|
||||||
Slash,
|
Slash,
|
||||||
literal(2f64)
|
f64_to_float_literal(2f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x_group_div.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
x_group_div.invert(&mut symbol_table, DECL_UNIT).unwrap(),
|
||||||
*binary(
|
*binary(
|
||||||
binary(decl_unit(), Star, literal(3f64)),
|
binary(decl_unit(), Star, f64_to_float_literal(3f64)),
|
||||||
Slash,
|
Slash,
|
||||||
literal(2f64)
|
f64_to_float_literal(2f64)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ impl KalkValue {
|
|||||||
if let KalkValue::Number(real, _, unit) = self {
|
if let KalkValue::Number(real, _, unit) = self {
|
||||||
let result = crate::interpreter::convert_unit(
|
let result = crate::interpreter::convert_unit(
|
||||||
context,
|
context,
|
||||||
&Expr::Literal(primitive!(real)),
|
&Expr::Literal(real.clone()),
|
||||||
unit.as_ref(),
|
unit.as_ref(),
|
||||||
Some(&to_unit.to_string()),
|
Some(&to_unit.to_string()),
|
||||||
);
|
);
|
||||||
@ -1503,32 +1503,47 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_to_string_pretty() {
|
fn test_to_string_pretty() {
|
||||||
let in_out = vec![
|
let in_out = vec![
|
||||||
(0.99999, 0.0, "0.99999 ≈ 1"),
|
(float!(0.99999), float!(0.0), "0.99999 ≈ 1"),
|
||||||
(-0.99999, 0.0, "-0.99999 ≈ -1"),
|
(float!(-0.99999), float!(0.0), "-0.99999 ≈ -1"),
|
||||||
(0.0, 0.99999, "0.99999i ≈ i"),
|
(float!(0.0), float!(0.99999), "0.99999i ≈ i"),
|
||||||
(0.000000001, 0.0, "10^-9 ≈ 0"),
|
(float!(0.000000001), float!(0.0), "10^-9 ≈ 0"),
|
||||||
(0.0, 0.000000001, "10^-9 i ≈ 0"),
|
(float!(0.0), float!(0.000000001), "10^-9 i ≈ 0"),
|
||||||
(0.99999, 0.999999, "0.99999 + 0.999999i ≈ 1 + i"),
|
(
|
||||||
(1.0, 0.99999, "1 + 0.99999i ≈ 1 + i"),
|
float!(0.99999),
|
||||||
(-0.99999, 0.999999, "-0.99999 + 0.999999i ≈ -1 + i"),
|
float!(0.999999),
|
||||||
(0.99999, -0.999999, "0.99999 - 0.999999i ≈ 1 - i"),
|
"0.99999 + 0.999999i ≈ 1 + i",
|
||||||
(-1.0, 0.99999, "-1 + 0.99999i ≈ -1 + i"),
|
),
|
||||||
(1.0, -0.99999, "1 - 0.99999i ≈ 1 - i"),
|
(float!(1.0), float!(0.99999), "1 + 0.99999i ≈ 1 + i"),
|
||||||
(-0.99999, 1.0, "-0.99999 + i ≈ -1 + i"),
|
(
|
||||||
(0.99999, -1.0, "0.99999 - i ≈ 1 - i"),
|
float!(-0.99999),
|
||||||
(0.000000001, 0.000000001, "10^-9 + 10^-9 i ≈ 0"),
|
float!(0.999999),
|
||||||
(1.0, 0.000000001, "1 + 10^-9 i ≈ 1"),
|
"-0.99999 + 0.999999i ≈ -1 + i",
|
||||||
(0.000000001, 1.0, "10^-9 + i ≈ i"),
|
),
|
||||||
(-1.0, 0.000000001, "-1 + 10^-9 i ≈ -1"),
|
(
|
||||||
(0.000000001, -1.0, "10^-9 - i ≈ -i"),
|
float!(0.99999),
|
||||||
(10e-17, 1.0, "i"),
|
float!(-0.999999),
|
||||||
(1.0, 10e-17, "1"),
|
"0.99999 - 0.999999i ≈ 1 - i",
|
||||||
(10e-16, 0.0, "0"),
|
),
|
||||||
(3.00000000004, 0.0, "3"),
|
(float!(-1.0), float!(0.99999), "-1 + 0.99999i ≈ -1 + i"),
|
||||||
|
(float!(1.0), float!(-0.99999), "1 - 0.99999i ≈ 1 - i"),
|
||||||
|
(float!(-0.99999), float!(1.0), "-0.99999 + i ≈ -1 + i"),
|
||||||
|
(float!(0.99999), float!(-1.0), "0.99999 - i ≈ 1 - i"),
|
||||||
|
(
|
||||||
|
float!(0.000000001),
|
||||||
|
float!(0.000000001),
|
||||||
|
"10^-9 + 10^-9 i ≈ 0",
|
||||||
|
),
|
||||||
|
(float!(1.0), float!(0.000000001), "1 + 10^-9 i ≈ 1"),
|
||||||
|
(float!(0.000000001), float!(1.0), "10^-9 + i ≈ i"),
|
||||||
|
(float!(-1.0), float!(0.000000001), "-1 + 10^-9 i ≈ -1"),
|
||||||
|
(float!(0.000000001), float!(-1.0), "10^-9 - i ≈ -i"),
|
||||||
|
(float!(10e-17), float!(1.0), "i"),
|
||||||
|
(float!(1.0), float!(10e-17), "1"),
|
||||||
|
(float!(10e-16), float!(0.0), "0"),
|
||||||
|
(float!(3.00000000004), float!(0.0), "3"),
|
||||||
];
|
];
|
||||||
for (real, imaginary, output) in in_out {
|
for (real, imaginary, output) in in_out {
|
||||||
let result =
|
let result = KalkValue::Number(real, imaginary, None).to_string_pretty();
|
||||||
KalkValue::Number(float!(real), float!(imaginary), None).to_string_pretty();
|
|
||||||
assert_eq!(output, result);
|
assert_eq!(output, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,14 @@ impl KalkValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_float(&self) -> f64 {
|
||||||
|
self.to_f64()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn imaginary_to_float(&self) -> f64 {
|
||||||
|
self.imaginary_to_f64()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn imaginary_to_f64(&self) -> f64 {
|
pub fn imaginary_to_f64(&self) -> f64 {
|
||||||
if let KalkValue::Number(_, imaginary, _) = self {
|
if let KalkValue::Number(_, imaginary, _) = self {
|
||||||
*imaginary
|
*imaginary
|
||||||
|
@ -9,6 +9,14 @@ impl KalkValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_float(&self) -> Float {
|
||||||
|
if let KalkValue::Number(real, _, _) = self {
|
||||||
|
real.clone()
|
||||||
|
} else {
|
||||||
|
crate::float!(f64::NAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn imaginary_to_f64(&self) -> f64 {
|
pub fn imaginary_to_f64(&self) -> f64 {
|
||||||
if let KalkValue::Number(_, imaginary, _) = self {
|
if let KalkValue::Number(_, imaginary, _) = self {
|
||||||
imaginary.to_f64_round(rug::float::Round::Nearest)
|
imaginary.to_f64_round(rug::float::Round::Nearest)
|
||||||
@ -17,6 +25,15 @@ impl KalkValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn imaginary_to_float(&self) -> Float {
|
||||||
|
if let KalkValue::Number(_, img, _) = self {
|
||||||
|
img.clone()
|
||||||
|
} else {
|
||||||
|
use crate::float;
|
||||||
|
float!(f64::NAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn values(self) -> (Float, Float) {
|
pub fn values(self) -> (Float, Float) {
|
||||||
if let KalkValue::Number(real, imaginary, _) = self {
|
if let KalkValue::Number(real, imaginary, _) = self {
|
||||||
(real, imaginary)
|
(real, imaginary)
|
||||||
|
@ -8,6 +8,7 @@ use crate::float;
|
|||||||
use crate::interpreter;
|
use crate::interpreter;
|
||||||
use crate::kalk_value::KalkValue;
|
use crate::kalk_value::KalkValue;
|
||||||
use crate::lexer::TokenKind;
|
use crate::lexer::TokenKind;
|
||||||
|
use crate::test_helpers::f64_to_float_literal;
|
||||||
|
|
||||||
pub fn derive_func(
|
pub fn derive_func(
|
||||||
context: &mut interpreter::Context,
|
context: &mut interpreter::Context,
|
||||||
@ -65,7 +66,7 @@ pub fn integrate_with_unknown_variable(
|
|||||||
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
|
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
|
||||||
context.symbol_table.set(Stmt::VarDecl(
|
context.symbol_table.set(Stmt::VarDecl(
|
||||||
Identifier::from_full_name(&format!("d{}", integration_variable.unwrap())),
|
Identifier::from_full_name(&format!("d{}", integration_variable.unwrap())),
|
||||||
Box::new(Expr::Literal(1f64)),
|
f64_to_float_literal(1f64),
|
||||||
));
|
));
|
||||||
|
|
||||||
Ok(integrate(context, a, b, expr, integration_variable.unwrap())?.round_if_needed())
|
Ok(integrate(context, a, b, expr, integration_variable.unwrap())?.round_if_needed())
|
||||||
@ -242,13 +243,13 @@ mod tests {
|
|||||||
Identifier::from_full_name("f"),
|
Identifier::from_full_name("f"),
|
||||||
vec![String::from("x")],
|
vec![String::from("x")],
|
||||||
binary(
|
binary(
|
||||||
literal(2.5f64),
|
f64_to_float_literal(2.5f64),
|
||||||
Star,
|
Star,
|
||||||
binary(var("x"), Power, literal(3f64)),
|
binary(var("x"), Power, f64_to_float_literal(3f64)),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
let call = Stmt::Expr(fn_call("f'", vec![*literal(12.3456f64)]));
|
let call = Stmt::Expr(fn_call("f'", vec![*f64_to_float_literal(12.3456f64)]));
|
||||||
assert!(cmp(
|
assert!(cmp(
|
||||||
context.interpret(vec![call]).unwrap().unwrap().to_f64(),
|
context.interpret(vec![call]).unwrap().unwrap().to_f64(),
|
||||||
1143.10379f64
|
1143.10379f64
|
||||||
@ -264,12 +265,16 @@ mod tests {
|
|||||||
vec![String::from("x")],
|
vec![String::from("x")],
|
||||||
binary(
|
binary(
|
||||||
binary(
|
binary(
|
||||||
literal(1.5f64),
|
f64_to_float_literal(1.5f64),
|
||||||
Star,
|
Star,
|
||||||
binary(var("x"), Power, literal(2f64)),
|
binary(var("x"), Power, f64_to_float_literal(2f64)),
|
||||||
),
|
),
|
||||||
Plus,
|
Plus,
|
||||||
binary(binary(var("x"), Power, literal(2f64)), Star, var("i")),
|
binary(
|
||||||
|
binary(var("x"), Power, f64_to_float_literal(2f64)),
|
||||||
|
Star,
|
||||||
|
var("i"),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -287,12 +292,12 @@ mod tests {
|
|||||||
Identifier::from_full_name("f"),
|
Identifier::from_full_name("f"),
|
||||||
vec![String::from("x")],
|
vec![String::from("x")],
|
||||||
binary(
|
binary(
|
||||||
binary(literal(3f64), Star, var("x")),
|
binary(f64_to_float_literal(3f64), Star, var("x")),
|
||||||
Plus,
|
Plus,
|
||||||
binary(
|
binary(
|
||||||
literal(0.5f64),
|
f64_to_float_literal(0.5f64),
|
||||||
Star,
|
Star,
|
||||||
binary(var("x"), Power, literal(3f64)),
|
binary(var("x"), Power, f64_to_float_literal(3f64)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -313,8 +318,8 @@ mod tests {
|
|||||||
let mut context = get_context(&mut symbol_table);
|
let mut context = get_context(&mut symbol_table);
|
||||||
let result = super::integrate_with_unknown_variable(
|
let result = super::integrate_with_unknown_variable(
|
||||||
&mut context,
|
&mut context,
|
||||||
&literal(2f64),
|
&f64_to_float_literal(2f64),
|
||||||
&literal(4f64),
|
&f64_to_float_literal(4f64),
|
||||||
&binary(var("x"), Star, var("dx")),
|
&binary(var("x"), Star, var("dx")),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -326,8 +331,14 @@ mod tests {
|
|||||||
fn test_integrate() {
|
fn test_integrate() {
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
let mut context = get_context(&mut symbol_table);
|
let mut context = get_context(&mut symbol_table);
|
||||||
let result =
|
let result = super::integrate(
|
||||||
super::integrate(&mut context, &literal(2f64), &literal(4f64), &var("x"), "x").unwrap();
|
&mut context,
|
||||||
|
&f64_to_float_literal(2f64),
|
||||||
|
&f64_to_float_literal(4f64),
|
||||||
|
&var("x"),
|
||||||
|
"x",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert!(cmp(result.to_f64(), 6f64));
|
assert!(cmp(result.to_f64(), 6f64));
|
||||||
}
|
}
|
||||||
@ -338,7 +349,7 @@ mod tests {
|
|||||||
let mut context = get_context(&mut symbol_table);
|
let mut context = get_context(&mut symbol_table);
|
||||||
let result = super::integrate(
|
let result = super::integrate(
|
||||||
&mut context,
|
&mut context,
|
||||||
&literal(2f64),
|
&f64_to_float_literal(2f64),
|
||||||
&ast::build_literal_ast(&KalkValue::Number(float!(3f64), float!(4f64), None)),
|
&ast::build_literal_ast(&KalkValue::Number(float!(3f64), float!(4f64), None)),
|
||||||
&binary(var("x"), Star, var("i")),
|
&binary(var("x"), Star, var("i")),
|
||||||
"x",
|
"x",
|
||||||
@ -353,7 +364,11 @@ mod tests {
|
|||||||
fn test_find_root() {
|
fn test_find_root() {
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
let mut context = get_context(&mut symbol_table);
|
let mut context = get_context(&mut symbol_table);
|
||||||
let ast = &*binary(binary(var("x"), Power, literal(3f64)), Plus, literal(3f64));
|
let ast = &*binary(
|
||||||
|
binary(var("x"), Power, f64_to_float_literal(3f64)),
|
||||||
|
Plus,
|
||||||
|
f64_to_float_literal(3f64),
|
||||||
|
);
|
||||||
let result = super::find_root(&mut context, ast, "x").unwrap();
|
let result = super::find_root(&mut context, ast, "x").unwrap();
|
||||||
|
|
||||||
assert!(cmp(result.to_f64(), -1.4422495709));
|
assert!(cmp(result.to_f64(), -1.4422495709));
|
||||||
|
@ -193,9 +193,9 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
advance(context);
|
advance(context);
|
||||||
// Yeah, a bit hacky, but there's no `true` keyword...
|
// Yeah, a bit hacky, but there's no `true` keyword...
|
||||||
let true_expr = Expr::Binary(
|
let true_expr = Expr::Binary(
|
||||||
Box::new(Expr::Literal(1f64)),
|
Box::new(Expr::Literal(crate::float!(1f64))),
|
||||||
TokenKind::Equals,
|
TokenKind::Equals,
|
||||||
Box::new(Expr::Literal(1f64)),
|
Box::new(Expr::Literal(crate::float!(1f64))),
|
||||||
);
|
);
|
||||||
pieces.push(crate::ast::ConditionalPiece {
|
pieces.push(crate::ast::ConditionalPiece {
|
||||||
expr: left_expr,
|
expr: left_expr,
|
||||||
@ -332,7 +332,7 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
context.symbol_table.get_mut().set(Stmt::FnDecl(
|
context.symbol_table.get_mut().set(Stmt::FnDecl(
|
||||||
identifier.clone(),
|
identifier.clone(),
|
||||||
parameters.clone(),
|
parameters.clone(),
|
||||||
Box::new(Expr::Literal(1f64)),
|
Box::new(Expr::Literal(crate::float!(1f64))),
|
||||||
));
|
));
|
||||||
let right = if match_token(context, TokenKind::OpenBrace) {
|
let right = if match_token(context, TokenKind::OpenBrace) {
|
||||||
parse_piecewise(context)?
|
parse_piecewise(context)?
|
||||||
@ -528,7 +528,7 @@ fn parse_primary(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?,
|
TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?,
|
||||||
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
|
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
|
||||||
TokenKind::Identifier => parse_identifier(context)?,
|
TokenKind::Identifier => parse_identifier(context)?,
|
||||||
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
|
TokenKind::Literal => Expr::Literal(crate::float!(string_to_num(&advance(context).value)?)),
|
||||||
TokenKind::True => {
|
TokenKind::True => {
|
||||||
advance(context);
|
advance(context);
|
||||||
Expr::Boolean(true)
|
Expr::Boolean(true)
|
||||||
@ -633,7 +633,16 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
let mut log_base = None;
|
let mut log_base = None;
|
||||||
if identifier.full_name.starts_with("log") {
|
if identifier.full_name.starts_with("log") {
|
||||||
if let Some(lowered) = identifier.get_lowered_part() {
|
if let Some(lowered) = identifier.get_lowered_part() {
|
||||||
if let Ok(lowered_float) = lowered.parse::<f64>() {
|
#[cfg(feature = "rug")]
|
||||||
|
fn parse_float_from_str(s: &str) -> Option<rug::Float> {
|
||||||
|
rug::Float::parse(s).map(|valid| crate::float!(valid)).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rug"))]
|
||||||
|
fn parse_float_from_str(s: &str) -> Option<f64> {
|
||||||
|
s.parse::<f64>().ok()
|
||||||
|
}
|
||||||
|
if let Some(lowered_float) = parse_float_from_str(lowered) {
|
||||||
log_base = Some(Expr::Literal(lowered_float));
|
log_base = Some(Expr::Literal(lowered_float));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -831,11 +840,11 @@ mod tests {
|
|||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
context.symbol_table.get_mut().insert(Stmt::VarDecl(
|
context.symbol_table.get_mut().insert(Stmt::VarDecl(
|
||||||
Identifier::from_full_name("x"),
|
Identifier::from_full_name("x"),
|
||||||
literal(1f64),
|
f64_to_float_literal(1f64),
|
||||||
));
|
));
|
||||||
context.symbol_table.get_mut().insert(Stmt::VarDecl(
|
context.symbol_table.get_mut().insert(Stmt::VarDecl(
|
||||||
Identifier::from_full_name("y"),
|
Identifier::from_full_name("y"),
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
));
|
));
|
||||||
|
|
||||||
// xy²
|
// xy²
|
||||||
@ -851,7 +860,7 @@ mod tests {
|
|||||||
Stmt::Expr(binary(
|
Stmt::Expr(binary(
|
||||||
var("x"),
|
var("x"),
|
||||||
Star,
|
Star,
|
||||||
binary(var("y"), Power, literal(2f64))
|
binary(var("y"), Power, f64_to_float_literal(2f64))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -878,15 +887,19 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(tokens).unwrap(),
|
parse(tokens).unwrap(),
|
||||||
Stmt::Expr(binary(
|
Stmt::Expr(binary(
|
||||||
literal(1f64),
|
f64_to_float_literal(1f64),
|
||||||
Plus,
|
Plus,
|
||||||
binary(
|
binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Star,
|
Star,
|
||||||
group(binary(
|
group(binary(
|
||||||
literal(3f64),
|
f64_to_float_literal(3f64),
|
||||||
Minus,
|
Minus,
|
||||||
binary(literal(4f64), Slash, literal(5f64))
|
binary(
|
||||||
|
f64_to_float_literal(4f64),
|
||||||
|
Slash,
|
||||||
|
f64_to_float_literal(5f64)
|
||||||
|
)
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
@ -913,16 +926,20 @@ mod tests {
|
|||||||
parse(tokens).unwrap(),
|
parse(tokens).unwrap(),
|
||||||
Stmt::Expr(binary(
|
Stmt::Expr(binary(
|
||||||
binary(
|
binary(
|
||||||
literal(1f64),
|
f64_to_float_literal(1f64),
|
||||||
Star,
|
Star,
|
||||||
binary(
|
binary(
|
||||||
literal(2f64),
|
f64_to_float_literal(2f64),
|
||||||
Power,
|
Power,
|
||||||
binary(literal(3f64), Power, literal(4f64)),
|
binary(
|
||||||
|
f64_to_float_literal(3f64),
|
||||||
|
Power,
|
||||||
|
f64_to_float_literal(4f64)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Plus,
|
Plus,
|
||||||
literal(5f64)
|
f64_to_float_literal(5f64)
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -939,7 +956,11 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(tokens).unwrap(),
|
parse(tokens).unwrap(),
|
||||||
Stmt::Expr(binary(literal(10f64), Power, unary(Minus, literal(1f64)))),
|
Stmt::Expr(binary(
|
||||||
|
f64_to_float_literal(10f64),
|
||||||
|
Power,
|
||||||
|
unary(Minus, f64_to_float_literal(1f64))
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,9 +980,13 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(tokens).unwrap(),
|
parse(tokens).unwrap(),
|
||||||
Stmt::Expr(binary(
|
Stmt::Expr(binary(
|
||||||
binary(literal(1f64), Percent, literal(1f64)),
|
binary(
|
||||||
|
f64_to_float_literal(1f64),
|
||||||
|
Percent,
|
||||||
|
f64_to_float_literal(1f64)
|
||||||
|
),
|
||||||
Plus,
|
Plus,
|
||||||
unary(Percent, literal(5f64))
|
unary(Percent, f64_to_float_literal(5f64))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -979,7 +1004,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_with_context(&mut context, tokens).unwrap(),
|
parse_with_context(&mut context, tokens).unwrap(),
|
||||||
Stmt::Expr(unit("a", literal(1f64)))
|
Stmt::Expr(unit("a", f64_to_float_literal(1f64)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,7 +1024,7 @@ mod tests {
|
|||||||
parse(tokens).unwrap(),
|
parse(tokens).unwrap(),
|
||||||
Stmt::VarDecl(
|
Stmt::VarDecl(
|
||||||
Identifier::from_full_name("x"),
|
Identifier::from_full_name("x"),
|
||||||
binary(literal(1f64), Plus, literal(2f64))
|
binary(f64_to_float_literal(1f64), Plus, f64_to_float_literal(2f64))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1024,7 +1049,7 @@ mod tests {
|
|||||||
Stmt::FnDecl(
|
Stmt::FnDecl(
|
||||||
Identifier::from_full_name("f"),
|
Identifier::from_full_name("f"),
|
||||||
vec![String::from("f-x")],
|
vec![String::from("f-x")],
|
||||||
binary(literal(1f64), Plus, param_var("f", "x"))
|
binary(f64_to_float_literal(1f64), Plus, param_var("f", "x"))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1050,7 +1075,7 @@ mod tests {
|
|||||||
context.symbol_table.get_mut().set(Stmt::FnDecl(
|
context.symbol_table.get_mut().set(Stmt::FnDecl(
|
||||||
Identifier::from_full_name("f"),
|
Identifier::from_full_name("f"),
|
||||||
vec![String::from("x")],
|
vec![String::from("x")],
|
||||||
literal(1f64),
|
f64_to_float_literal(1f64),
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1058,10 +1083,14 @@ mod tests {
|
|||||||
Stmt::Expr(binary(
|
Stmt::Expr(binary(
|
||||||
Box::new(Expr::FnCall(
|
Box::new(Expr::FnCall(
|
||||||
Identifier::from_full_name("f"),
|
Identifier::from_full_name("f"),
|
||||||
vec![*binary(literal(1f64), Plus, literal(2f64))]
|
vec![*binary(
|
||||||
|
f64_to_float_literal(1f64),
|
||||||
|
Plus,
|
||||||
|
f64_to_float_literal(2f64)
|
||||||
|
)]
|
||||||
)),
|
)),
|
||||||
Plus,
|
Plus,
|
||||||
literal(3f64)
|
f64_to_float_literal(3f64)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ fn to_angle_unit(context: &mut interpreter::Context, x: KalkValue, angle_unit: &
|
|||||||
"rad" => x,
|
"rad" => x,
|
||||||
_ => interpreter::convert_unit(
|
_ => interpreter::convert_unit(
|
||||||
context,
|
context,
|
||||||
&Expr::Literal(x.to_f64()),
|
&Expr::Literal(x.to_float()),
|
||||||
Some(&String::from("rad")),
|
Some(&String::from("rad")),
|
||||||
Some(&angle_unit.to_string()),
|
Some(&angle_unit.to_string()),
|
||||||
)
|
)
|
||||||
@ -259,7 +259,7 @@ fn from_angle_unit(
|
|||||||
"rad" => x,
|
"rad" => x,
|
||||||
_ => interpreter::convert_unit(
|
_ => interpreter::convert_unit(
|
||||||
context,
|
context,
|
||||||
&Expr::Literal(x.to_f64()),
|
&Expr::Literal(x.to_float()),
|
||||||
Some(&angle_unit.to_string()),
|
Some(&angle_unit.to_string()),
|
||||||
Some(&String::from("rad")),
|
Some(&String::from("rad")),
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,7 @@ impl SymbolTable {
|
|||||||
Identifier::from_full_name("i"),
|
Identifier::from_full_name("i"),
|
||||||
Box::new(Expr::FnCall(
|
Box::new(Expr::FnCall(
|
||||||
Identifier::from_full_name("sqrt"),
|
Identifier::from_full_name("sqrt"),
|
||||||
vec![Expr::Literal(-1f64)],
|
vec![Expr::Literal(crate::float!(-1f64))],
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -17,6 +17,15 @@ pub fn cmp(x: f64, y: f64) -> bool {
|
|||||||
(x - y).abs() < 0.0001
|
(x - y).abs() < 0.0001
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn f64_to_float_literal(x: f64) -> Box<Expr> {
|
||||||
|
literal(crate::float!(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rug")]
|
||||||
|
pub fn literal(value: rug::Float) -> Box<Expr> {
|
||||||
|
Box::new(Expr::Literal(value))
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "rug"))]
|
||||||
pub fn literal(value: f64) -> Box<Expr> {
|
pub fn literal(value: f64) -> Box<Expr> {
|
||||||
Box::new(Expr::Literal(value))
|
Box::new(Expr::Literal(value))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user