diff --git a/kalk/src/interpreter.rs b/kalk/src/interpreter.rs index 1ad54eb..f5330b8 100644 --- a/kalk/src/interpreter.rs +++ b/kalk/src/interpreter.rs @@ -235,3 +235,56 @@ fn eval_fn_call_expr( _ => Err(format!("Undefined function: '{}'.", identifier)), } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::lexer::TokenKind::*; + use crate::test_helpers::*; + + const PRECISION: u32 = 53; + + fn interpret(stmt: Stmt) -> Result, String> { + let mut symbol_table = SymbolTable::new(); + let mut context = Context::new(&mut symbol_table, &Unit::Radians, PRECISION); + context.interpret(vec![stmt]) + } + + #[test] + fn test_literal() { + let stmt = Stmt::Expr(literal("1")); + + assert_eq!( + interpret(stmt).unwrap().unwrap(), + Float::with_val(PRECISION, 1) + ); + } + + #[test] + fn test_binary() { + let add = Stmt::Expr(binary(literal("2"), Plus, literal("3"))); + let sub = Stmt::Expr(binary(literal("2"), Minus, literal("3"))); + let mul = Stmt::Expr(binary(literal("2"), Star, literal("3"))); + let div = Stmt::Expr(binary(literal("2"), Slash, literal("4"))); + let pow = Stmt::Expr(binary(literal("2"), Power, literal("3"))); + + assert_eq!(interpret(add).unwrap().unwrap(), 5); + assert_eq!(interpret(sub).unwrap().unwrap(), -1); + assert_eq!(interpret(mul).unwrap().unwrap(), 6); + assert_eq!(interpret(div).unwrap().unwrap(), 0.5); + assert_eq!(interpret(pow).unwrap().unwrap(), 8); + } + + #[test] + fn test_unary() { + let neg = Stmt::Expr(unary(Minus, literal("1"))); + let fact = Stmt::Expr(unary(Exclamation, literal("5"))); + let fact_dec = Stmt::Expr(unary(Exclamation, literal("5.2"))); + + assert_eq!(interpret(neg).unwrap().unwrap(), -1); + assert_eq!(interpret(fact).unwrap().unwrap(), 120); + + let fact_dec_result = interpret(fact_dec).unwrap().unwrap(); + assert!(fact_dec_result > 169.406 && fact_dec_result < 169.407); + } +} diff --git a/kalk/src/lib.rs b/kalk/src/lib.rs index 27362af..ed5fbe9 100644 --- a/kalk/src/lib.rs +++ b/kalk/src/lib.rs @@ -4,3 +4,4 @@ mod lexer; pub mod parser; mod prelude; mod symbol_table; +mod test_helpers; diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index 47f6f89..d4fb686 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -310,6 +310,7 @@ fn is_at_end(context: &mut Context) -> bool { mod tests { use super::*; use crate::lexer::{Token, TokenKind::*}; + use crate::test_helpers::*; use test_case::test_case; fn parse_with_context(context: &mut Context, tokens: Vec) -> Result { @@ -325,33 +326,6 @@ mod tests { parse_stmt(&mut context) } - fn token(kind: TokenKind, value: &str) -> Token { - Token { - kind, - value: value.into(), - } - } - - fn literal(value: &str) -> Box { - Box::new(Expr::Literal(value.into())) - } - - fn var(identifier: &str) -> Box { - Box::new(Expr::Var(identifier.into())) - } - - fn binary(left: Box, op: TokenKind, right: Box) -> Box { - Box::new(Expr::Binary(left, op, right)) - } - - fn unary(op: TokenKind, expr: Box) -> Box { - Box::new(Expr::Unary(op, expr)) - } - - fn group(expr: Box) -> Box { - Box::new(Expr::Group(expr)) - } - #[test] fn test_var() { // x diff --git a/kalk/src/test_helpers.rs b/kalk/src/test_helpers.rs new file mode 100644 index 0000000..0b1101c --- /dev/null +++ b/kalk/src/test_helpers.rs @@ -0,0 +1,31 @@ +#![allow(dead_code)] +use crate::ast::Expr; +use crate::lexer::Token; +use crate::lexer::TokenKind; + +pub fn token(kind: TokenKind, value: &str) -> Token { + Token { + kind, + value: value.into(), + } +} + +pub fn literal(value: &str) -> Box { + Box::new(Expr::Literal(value.into())) +} + +pub fn var(identifier: &str) -> Box { + Box::new(Expr::Var(identifier.into())) +} + +pub fn binary(left: Box, op: TokenKind, right: Box) -> Box { + Box::new(Expr::Binary(left, op, right)) +} + +pub fn unary(op: TokenKind, expr: Box) -> Box { + Box::new(Expr::Unary(op, expr)) +} + +pub fn group(expr: Box) -> Box { + Box::new(Expr::Group(expr)) +}