Store number literals as f64

This commit is contained in:
PaddiM8 2020-12-13 15:52:22 +01:00
parent 4ddb2bf33f
commit 56145c2f45
7 changed files with 148 additions and 122 deletions

View File

@ -19,5 +19,5 @@ pub enum Expr {
Var(String), Var(String),
Group(Box<Expr>), Group(Box<Expr>),
FnCall(String, Vec<Expr>), FnCall(String, Vec<Expr>),
Literal(String), Literal(f64),
} }

View File

@ -32,13 +32,13 @@ impl<'a> Context<'a> {
String::from("ans"), String::from("ans"),
Box::new(Expr::Unit( Box::new(Expr::Unit(
num.unit.clone(), num.unit.clone(),
Box::new(Expr::Literal(num.value.clone().to_string())), Box::new(Expr::Literal(num.value.to_f64())),
)), )),
) )
} else { } else {
Stmt::VarDecl( Stmt::VarDecl(
String::from("ans"), String::from("ans"),
Box::new(Expr::Literal(num.value.clone().to_string())), Box::new(Expr::Literal(num.value.to_f64())),
) )
}); });
@ -85,7 +85,7 @@ fn eval_expr(context: &mut Context, expr: &Expr, unit: &str) -> Result<KalkNum,
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), Expr::Literal(value) => eval_literal_expr(context, *value, unit),
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) => {
eval_fn_call_expr(context, identifier, expressions, unit) eval_fn_call_expr(context, identifier, expressions, unit)
@ -200,7 +200,7 @@ fn eval_var_expr(
) -> Result<KalkNum, CalcError> { ) -> Result<KalkNum, CalcError> {
// 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()), unit); return eval_expr(context, &Expr::Literal(*value), unit);
} }
// Look for the variable in the symbol table // Look for the variable in the symbol table
@ -211,14 +211,11 @@ fn eval_var_expr(
} }
} }
fn eval_literal_expr(context: &mut Context, value: &str, unit: &str) -> Result<KalkNum, CalcError> { fn eval_literal_expr(context: &mut Context, value: f64, unit: &str) -> Result<KalkNum, CalcError> {
match Float::parse(value) { Ok(KalkNum::new(
Ok(parsed_value) => Ok(KalkNum::new( Float::with_val(context.precision, value),
Float::with_val(context.precision, parsed_value),
unit.into(), unit.into(),
)), ))
Err(_) => Err(CalcError::InvalidNumberLiteral(value.into())),
}
} }
fn eval_group_expr(context: &mut Context, expr: &Expr, unit: &str) -> Result<KalkNum, CalcError> { fn eval_group_expr(context: &mut Context, expr: &Expr, unit: &str) -> Result<KalkNum, CalcError> {
@ -269,7 +266,7 @@ fn eval_fn_call_expr(
let mut sum = Float::with_val(context.precision, 0); let mut sum = Float::with_val(context.precision, 0);
for n in start..=end { for n in start..=end {
let n_expr = Expr::Literal(n.to_string()); let n_expr = Expr::Literal(n as f64);
// Update the variable "n" in the symbol table on every iteration, // Update the variable "n" in the symbol table on every iteration,
// then calculate the expression and add it to the total sum. // then calculate the expression and add it to the total sum.
@ -328,7 +325,7 @@ mod tests {
binary( binary(
var(crate::parser::DECL_UNIT), var(crate::parser::DECL_UNIT),
TokenKind::Star, TokenKind::Star,
literal("180"), literal(180f64),
), ),
TokenKind::Slash, TokenKind::Slash,
var("pi"), var("pi"),
@ -340,7 +337,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("180"), literal(180f64),
), ),
); );
} }
@ -370,18 +367,18 @@ mod tests {
#[test] #[test]
fn test_literal() { fn test_literal() {
let stmt = Stmt::Expr(literal("1")); let stmt = Stmt::Expr(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("2"), Plus, literal("3"))); let add = Stmt::Expr(binary(literal(2f64), Plus, literal(3f64)));
let sub = Stmt::Expr(binary(literal("2"), Minus, literal("3"))); let sub = Stmt::Expr(binary(literal(2f64), Minus, literal(3f64)));
let mul = Stmt::Expr(binary(literal("2"), Star, literal("3"))); let mul = Stmt::Expr(binary(literal(2f64), Star, literal(3f64)));
let div = Stmt::Expr(binary(literal("2"), Slash, literal("4"))); let div = Stmt::Expr(binary(literal(2f64), Slash, literal(4f64)));
let pow = Stmt::Expr(binary(literal("2"), Power, literal("3"))); let pow = Stmt::Expr(binary(literal(2f64), Power, 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);
@ -393,9 +390,9 @@ mod tests {
#[test] #[test]
fn test_percent() { fn test_percent() {
let stmt = Stmt::Expr(binary( let stmt = Stmt::Expr(binary(
literal("5"), literal(5f64),
Percent, Percent,
group(binary(literal("3"), Plus, unary(Percent, literal("2")))), group(binary(literal(3f64), Plus, unary(Percent, literal(2f64)))),
)); ));
assert!(cmp(interpret(stmt).unwrap().unwrap(), 1.94f64)); assert!(cmp(interpret(stmt).unwrap().unwrap(), 1.94f64));
@ -403,8 +400,8 @@ mod tests {
#[test] #[test]
fn test_unary() { fn test_unary() {
let neg = Stmt::Expr(unary(Minus, literal("1"))); let neg = Stmt::Expr(unary(Minus, literal(1f64)));
let fact = Stmt::Expr(unary(Exclamation, literal("5"))); let fact = Stmt::Expr(unary(Exclamation, 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);
@ -412,9 +409,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("1"))])); let rad_explicit = Stmt::Expr(fn_call("sin", vec![*unit("rad", literal(1f64))]));
let deg_explicit = Stmt::Expr(fn_call("sin", vec![*unit("deg", literal("1"))])); let deg_explicit = Stmt::Expr(fn_call("sin", vec![*unit("deg", literal(1f64))]));
let implicit = Stmt::Expr(fn_call("sin", vec![*literal("1")])); let implicit = Stmt::Expr(fn_call("sin", vec![*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));
@ -449,7 +446,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("1"))); symbol_table.insert(var_decl("x", literal(1f64)));
let mut context = Context::new(&mut symbol_table, "rad", PRECISION); let mut context = Context::new(&mut symbol_table, "rad", PRECISION);
assert_eq!( assert_eq!(
@ -470,7 +467,7 @@ mod tests {
#[test] #[test]
fn test_var_decl() { fn test_var_decl() {
let stmt = var_decl("x", literal("1")); let stmt = var_decl("x", literal(1f64));
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
Context::new(&mut symbol_table, "rad", PRECISION) Context::new(&mut symbol_table, "rad", PRECISION)
.interpret(vec![stmt]) .interpret(vec![stmt])
@ -481,14 +478,14 @@ mod tests {
#[test] #[test]
fn test_fn() { fn test_fn() {
let stmt = Stmt::Expr(fn_call("f", vec![*literal("1")])); let stmt = Stmt::Expr(fn_call("f", vec![*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("2")), binary(var("x"), TokenKind::Plus, literal(2f64)),
)); ));
let mut context = Context::new(&mut symbol_table, "rad", PRECISION); let mut context = Context::new(&mut symbol_table, "rad", PRECISION);
@ -500,7 +497,7 @@ mod tests {
#[test] #[test]
fn test_undefined_fn() { fn test_undefined_fn() {
let stmt = Stmt::Expr(fn_call("f", vec![*literal("1")])); let stmt = Stmt::Expr(fn_call("f", vec![*literal(1f64)]));
assert_eq!( assert_eq!(
interpret(stmt), interpret(stmt),
@ -508,15 +505,15 @@ mod tests {
); );
} }
#[test_case("1", "2", 9f64)] #[test_case(1f64, 2f64, 9f64)]
#[test_case("1.2", "2.3", 9f64)] #[test_case(1.2f64, 2.3f64, 9f64)]
fn test_sum_fn(start: &str, to: &str, result: f64) { fn test_sum_fn(start: f64, to: f64, result: f64) {
let stmt = Stmt::Expr(fn_call( let stmt = Stmt::Expr(fn_call(
"sum", "sum",
vec![ vec![
*literal(start), *literal(start),
*literal(to), *literal(to),
*binary(var("n"), TokenKind::Plus, literal("3")), *binary(var("n"), TokenKind::Plus, literal(3f64)),
], ],
)); ));

View File

@ -86,7 +86,7 @@ fn invert_binary(
symbol_table, symbol_table,
left, left,
&TokenKind::Plus, &TokenKind::Plus,
&multiply_into(&Expr::Literal(String::from("-1")), inside_group)?, &multiply_into(&Expr::Literal(-1f64), inside_group)?,
); );
} }
@ -231,7 +231,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(String::from("2"))), Box::new(Expr::Literal(2f64)),
), ),
arguments[0].clone(), arguments[0].clone(),
)); ));
@ -361,49 +361,49 @@ mod tests {
#[test] #[test]
fn test_binary() { fn test_binary() {
let ladd = binary(decl_unit(), Plus, literal("1")); let ladd = binary(decl_unit(), Plus, literal(1f64));
let lsub = binary(decl_unit(), Minus, literal("1")); let lsub = binary(decl_unit(), Minus, literal(1f64));
let lmul = binary(decl_unit(), Star, literal("1")); let lmul = binary(decl_unit(), Star, literal(1f64));
let ldiv = binary(decl_unit(), Slash, literal("1")); let ldiv = binary(decl_unit(), Slash, literal(1f64));
let radd = binary(literal("1"), Plus, decl_unit()); let radd = binary(literal(1f64), Plus, decl_unit());
let rsub = binary(literal("1"), Minus, decl_unit()); let rsub = binary(literal(1f64), Minus, decl_unit());
let rmul = binary(literal("1"), Star, decl_unit()); let rmul = binary(literal(1f64), Star, decl_unit());
let rdiv = binary(literal("1"), Slash, decl_unit()); let rdiv = binary(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).unwrap(), ladd.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Minus, literal("1")) *binary(decl_unit(), Minus, literal(1f64))
); );
assert_eq!( assert_eq!(
lsub.invert(&mut symbol_table).unwrap(), lsub.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Plus, literal("1")) *binary(decl_unit(), Plus, literal(1f64))
); );
assert_eq!( assert_eq!(
lmul.invert(&mut symbol_table).unwrap(), lmul.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Slash, literal("1")) *binary(decl_unit(), Slash, literal(1f64))
); );
assert_eq!( assert_eq!(
ldiv.invert(&mut symbol_table).unwrap(), ldiv.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Star, literal("1")) *binary(decl_unit(), Star, literal(1f64))
); );
assert_eq!( assert_eq!(
radd.invert(&mut symbol_table).unwrap(), radd.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Minus, literal("1")) *binary(decl_unit(), Minus, literal(1f64))
); );
assert_eq!( assert_eq!(
rsub.invert(&mut symbol_table).unwrap(), rsub.invert(&mut symbol_table).unwrap(),
*unary(Minus, binary(decl_unit(), Plus, literal("1"))) *unary(Minus, binary(decl_unit(), Plus, literal(1f64)))
); );
assert_eq!( assert_eq!(
rmul.invert(&mut symbol_table).unwrap(), rmul.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Slash, literal("1")) *binary(decl_unit(), Slash, literal(1f64))
); );
assert_eq!( assert_eq!(
rdiv.invert(&mut symbol_table).unwrap(), rdiv.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Star, literal("1")) *binary(decl_unit(), Star, literal(1f64))
); );
} }
@ -417,34 +417,34 @@ mod tests {
#[test] #[test]
fn test_fn_call() { fn test_fn_call() {
let call_with_literal = binary(fn_call("f", vec![*literal("2")]), Plus, decl_unit()); let call_with_literal = binary(fn_call("f", vec![*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("2"))]); fn_call("f", vec![*binary(decl_unit(), Plus, 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("1")), binary(var("x"), Plus, literal(1f64)),
); );
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
symbol_table.insert(decl); symbol_table.insert(decl);
assert_eq!( assert_eq!(
call_with_literal.invert(&mut symbol_table).unwrap(), call_with_literal.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Minus, fn_call("f", vec![*literal("2")])), *binary(decl_unit(), Minus, fn_call("f", vec![*literal(2f64)])),
); );
assert_eq!( assert_eq!(
call_with_decl_unit.invert(&mut symbol_table).unwrap(), call_with_decl_unit.invert(&mut symbol_table).unwrap(),
*binary(decl_unit(), Minus, literal("1")) *binary(decl_unit(), Minus, literal(1f64))
); );
assert_eq!( assert_eq!(
call_with_decl_unit_and_literal call_with_decl_unit_and_literal
.invert(&mut symbol_table) .invert(&mut symbol_table)
.unwrap(), .unwrap(),
*binary( *binary(
binary(decl_unit(), Minus, literal("1")), binary(decl_unit(), Minus, literal(1f64)),
Minus, Minus,
literal("2") literal(2f64)
) )
); );
} }
@ -452,84 +452,100 @@ mod tests {
#[test] #[test]
fn test_group() { fn test_group() {
let group_x = binary( let group_x = binary(
group(binary(decl_unit(), Plus, literal("3"))), group(binary(decl_unit(), Plus, literal(3f64))),
Star, Star,
literal("2"), literal(2f64),
); );
let group_unary_minus = binary( let group_unary_minus = binary(
literal("2"), literal(2f64),
Minus, Minus,
group(binary(decl_unit(), Plus, literal("3"))), group(binary(decl_unit(), Plus, literal(3f64))),
); );
let x_group_add = binary( let x_group_add = binary(
literal("2"), literal(2f64),
Star, Star,
group(binary(decl_unit(), Plus, literal("3"))), group(binary(decl_unit(), Plus, literal(3f64))),
); );
let x_group_sub = binary( let x_group_sub = binary(
literal("2"), literal(2f64),
Star, Star,
group(binary(decl_unit(), Minus, literal("3"))), group(binary(decl_unit(), Minus, literal(3f64))),
); );
let x_group_mul = binary( let x_group_mul = binary(
literal("2"), literal(2f64),
Star, Star,
group(binary(decl_unit(), Star, literal("3"))), group(binary(decl_unit(), Star, literal(3f64))),
); );
let x_group_div = binary( let x_group_div = binary(
literal("2"), literal(2f64),
Star, Star,
group(binary(decl_unit(), Slash, literal("3"))), group(binary(decl_unit(), Slash, literal(3f64))),
); );
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
assert_eq!( assert_eq!(
group_x.invert(&mut symbol_table).unwrap(), group_x.invert(&mut symbol_table).unwrap(),
*binary( *binary(
binary(decl_unit(), Minus, binary(literal("2"), Star, literal("3"))), binary(
decl_unit(),
Minus,
binary(literal(2f64), Star, literal(3f64))
),
Slash, Slash,
literal("2") literal(2f64)
) )
); );
assert_eq!( assert_eq!(
group_unary_minus.invert(&mut symbol_table).unwrap(), group_unary_minus.invert(&mut symbol_table).unwrap(),
*binary( *binary(
binary( binary(
binary(decl_unit(), Minus, literal("2")), binary(decl_unit(), Minus, literal(2f64)),
Minus, Minus,
binary(literal("-1"), Star, literal("3")) binary(literal(-1f64), Star, literal(3f64))
), ),
Slash, Slash,
literal("-1") literal(-1f64)
) )
); );
assert_eq!( assert_eq!(
x_group_add.invert(&mut symbol_table).unwrap(), x_group_add.invert(&mut symbol_table).unwrap(),
*binary( *binary(
binary(decl_unit(), Minus, binary(literal("2"), Star, literal("3"))), binary(
decl_unit(),
Minus,
binary(literal(2f64), Star, literal(3f64))
),
Slash, Slash,
literal("2") literal(2f64)
) )
); );
assert_eq!( assert_eq!(
x_group_sub.invert(&mut symbol_table).unwrap(), x_group_sub.invert(&mut symbol_table).unwrap(),
*binary( *binary(
binary(decl_unit(), Plus, binary(literal("2"), Star, literal("3"))), binary(
decl_unit(),
Plus,
binary(literal(2f64), Star, literal(3f64))
),
Slash, Slash,
literal("2") literal(2f64)
) )
); );
assert_eq!( assert_eq!(
x_group_mul.invert(&mut symbol_table).unwrap(), x_group_mul.invert(&mut symbol_table).unwrap(),
*binary( *binary(
binary(decl_unit(), Slash, literal("3")), binary(decl_unit(), Slash, literal(3f64)),
Slash, Slash,
literal("2") literal(2f64)
) )
); );
assert_eq!( assert_eq!(
x_group_div.invert(&mut symbol_table).unwrap(), x_group_div.invert(&mut symbol_table).unwrap(),
*binary(binary(decl_unit(), Star, literal("3")), Slash, literal("2")) *binary(
binary(decl_unit(), Star, literal(3f64)),
Slash,
literal(2f64)
)
); );
} }

View File

@ -95,7 +95,7 @@ impl KalkNum {
) -> Option<KalkNum> { ) -> Option<KalkNum> {
let result = crate::interpreter::convert_unit( let result = crate::interpreter::convert_unit(
context, context,
&Expr::Literal(self.value.to_string()), // TODO: Store as f64, jeez... &Expr::Literal(self.value.to_f64()),
&self.unit, &self.unit,
to_unit, to_unit,
); );

View File

@ -339,7 +339,7 @@ fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> {
TokenKind::OpenParenthesis => parse_group(context)?, TokenKind::OpenParenthesis => parse_group(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(advance(context).value.clone()), TokenKind::Literal => Expr::Literal(advance(context).value.parse::<f64>().unwrap()),
_ => return Err(CalcError::UnableToParseExpression), _ => return Err(CalcError::UnableToParseExpression),
}; };
@ -375,7 +375,7 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
if match_token(context, TokenKind::Literal) { if match_token(context, TokenKind::Literal) {
// If there is a function with this name, parse it as a function, with the next token as the argument. // If there is a function with this name, parse it as a function, with the next token as the argument.
if context.symbol_table.contains_fn(&identifier.value) { if context.symbol_table.contains_fn(&identifier.value) {
let parameter = Expr::Literal(advance(context).value.clone()); let parameter = Expr::Literal(advance(context).value.parse::<f64>().unwrap());
return Ok(Expr::FnCall(identifier.value, vec![parameter])); return Ok(Expr::FnCall(identifier.value, vec![parameter]));
} }
} }
@ -508,15 +508,15 @@ mod tests {
assert_eq!( assert_eq!(
parse(tokens).unwrap(), parse(tokens).unwrap(),
Stmt::Expr(binary( Stmt::Expr(binary(
literal("1"), literal(1f64),
Plus, Plus,
binary( binary(
literal("2"), literal(2f64),
Star, Star,
group(binary( group(binary(
literal("3"), literal(3f64),
Minus, Minus,
binary(literal("4"), Slash, literal("5")) binary(literal(4f64), Slash, literal(5f64))
)) ))
) )
)) ))
@ -542,16 +542,16 @@ mod tests {
parse(tokens).unwrap(), parse(tokens).unwrap(),
Stmt::Expr(binary( Stmt::Expr(binary(
binary( binary(
literal("1"), literal(1f64),
Star, Star,
binary( binary(
literal("2"), literal(2f64),
Power, Power,
binary(literal("3"), Power, literal("4")), binary(literal(3f64), Power, literal(4f64)),
), ),
), ),
Plus, Plus,
literal("5") literal(5f64)
)), )),
); );
} }
@ -571,9 +571,9 @@ mod tests {
assert_eq!( assert_eq!(
parse(tokens).unwrap(), parse(tokens).unwrap(),
Stmt::Expr(binary( Stmt::Expr(binary(
binary(literal("1"), Percent, literal("1"),), binary(literal(1f64), Percent, literal(1f64)),
Plus, Plus,
unary(Percent, literal("5")) unary(Percent, literal(5f64))
)) ))
); );
} }
@ -589,7 +589,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("1"))) Stmt::Expr(unit("a", literal(1f64)))
); );
} }
@ -606,7 +606,10 @@ mod tests {
assert_eq!( assert_eq!(
parse(tokens).unwrap(), parse(tokens).unwrap(),
Stmt::VarDecl(String::from("x"), binary(literal("1"), Plus, literal("2"))) Stmt::VarDecl(
String::from("x"),
binary(literal(1f64), Plus, literal(2f64))
)
); );
} }
@ -629,7 +632,7 @@ mod tests {
Stmt::FnDecl( Stmt::FnDecl(
String::from("f"), String::from("f"),
vec![String::from("x")], vec![String::from("x")],
binary(literal("1"), Plus, literal("2")) binary(literal(1f64), Plus, literal(2f64))
) )
); );
} }
@ -654,7 +657,7 @@ mod tests {
context.symbol_table.set(Stmt::FnDecl( context.symbol_table.set(Stmt::FnDecl(
String::from("f"), String::from("f"),
vec![String::from("x")], vec![String::from("x")],
literal("1"), literal(1f64),
)); ));
assert_eq!( assert_eq!(
@ -662,10 +665,10 @@ mod tests {
Stmt::Expr(binary( Stmt::Expr(binary(
Box::new(Expr::FnCall( Box::new(Expr::FnCall(
String::from("f"), String::from("f"),
vec![*binary(literal("1"), Plus, literal("2"))] vec![*binary(literal(1f64), Plus, literal(2f64))]
)), )),
Plus, Plus,
literal("3") literal(3f64)
)) ))
); );
} }

View File

@ -9,15 +9,15 @@ use FuncType::*;
pub const INIT: &'static str = "unit deg = (rad*180)/pi"; pub const INIT: &'static str = "unit deg = (rad*180)/pi";
lazy_static! { lazy_static! {
pub static ref CONSTANTS: HashMap<&'static str, &'static str> = { pub static ref CONSTANTS: HashMap<&'static str, f64> = {
let mut m = HashMap::new(); let mut m = HashMap::new();
m.insert("pi", "3.14159265"); m.insert("pi", 3.14159265);
m.insert("π", "3.14159265"); m.insert("π", 3.14159265);
m.insert("e", "2.71828182"); m.insert("e", 2.71828182);
m.insert("tau", "6.28318530"); m.insert("tau", 6.28318530);
m.insert("τ", "6.28318530"); m.insert("τ", 6.28318530);
m.insert("phi", "1.61803398"); m.insert("phi", 1.61803398);
m.insert("ϕ", "1.61803398"); m.insert("ϕ", 1.61803398);
m m
}; };
pub static ref UNARY_FUNCS: HashMap<&'static str, (UnaryFuncInfo, &'static str)> = { pub static ref UNARY_FUNCS: HashMap<&'static str, (UnaryFuncInfo, &'static str)> = {
@ -154,7 +154,12 @@ fn to_angle_unit(context: &mut interpreter::Context, x: Float, angle_unit: &str)
match angle_unit { match angle_unit {
"rad" => x, "rad" => x,
_ => { _ => {
interpreter::convert_unit(context, &Expr::Literal(x.to_string()), "rad", angle_unit) interpreter::convert_unit(
context,
&Expr::Literal(x.to_f64_round(rug::float::Round::Nearest)),
"rad",
angle_unit,
)
.unwrap() .unwrap()
.value .value
} }
@ -165,7 +170,12 @@ fn from_angle_unit(context: &mut interpreter::Context, x: Float, angle_unit: &st
match angle_unit { match angle_unit {
"rad" => x, "rad" => x,
_ => { _ => {
interpreter::convert_unit(context, &Expr::Literal(x.to_string()), angle_unit, "rad") interpreter::convert_unit(
context,
&Expr::Literal(x.to_f64_round(rug::float::Round::Nearest)),
angle_unit,
"rad",
)
.unwrap() .unwrap()
.value .value
} }

View File

@ -12,8 +12,8 @@ pub fn token(kind: TokenKind, value: &str) -> Token {
} }
} }
pub fn literal(value: &str) -> Box<Expr> { pub fn literal(value: f64) -> Box<Expr> {
Box::new(Expr::Literal(value.into())) Box::new(Expr::Literal(value))
} }
pub fn var(identifier: &str) -> Box<Expr> { pub fn var(identifier: &str) -> Box<Expr> {