From 1fdfcc29c14e101b59f4bc9531fb9e1862b61ca2 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Thu, 18 Jun 2020 16:20:18 +0200 Subject: [PATCH] Implemented inversion for some prelude functions. --- kalk/src/inverter.rs | 83 +++++++++++++++++++++++++++++++++++++++--- kalk/src/parser.rs | 2 +- kalk_cli/src/output.rs | 2 +- 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/kalk/src/inverter.rs b/kalk/src/inverter.rs index d9570e6..bfced60 100644 --- a/kalk/src/inverter.rs +++ b/kalk/src/inverter.rs @@ -2,8 +2,37 @@ use crate::ast::{Expr, Stmt}; use crate::lexer::TokenKind; use crate::parser::CalcError; use crate::parser::DECL_UNIT; +use crate::prelude; use crate::symbol_table::SymbolTable; +pub const INVERSE_UNARY_FUNCS: phf::Map<&'static str, &'static str> = phf::phf_map! { + "cos" => "acos", + "cosec" => "acosec", + "cosech" => "cosech", + "cosh" => "acosh", + "cot" => "acot", + "coth" => "acoth", + "sec" => "asec", + "sech" => "asech", + "sin" => "asin", + "sinh" => "asinh", + "tan" => "atan", + "tanh" => "atanh", + + "acos" => "cos", + "acosec" => "cosec", + "acosech" => "cosech", + "acosh" => "cosh", + "acot" => "cot", + "acoth" => "coth", + "asec" => "sec", + "asech" => "sech", + "asin" => "sin", + "asinh" => "sinh", + "atan" => "tan", + "atanh" => "tanh", +}; + impl Expr { pub fn invert(&self, symbol_table: &mut SymbolTable) -> Result { let target_expr = Expr::Var(DECL_UNIT.into()); @@ -111,8 +140,8 @@ fn invert_binary( // But if the right expression *also* contains the unit, // throw an error, since it can't handle this yet. if contains_the_unit(symbol_table, right) { - return Err(CalcError::UnsupportedExpression(String::from( - "Can't invert expressions with several instances of an unknown variable (yet). Try simplifying the expression.", + return Err(CalcError::UnableToInvert(String::from( + "Expressions with several instances of an unknown variable (this might be supported in the future). Try simplifying the expression.", ))); } @@ -155,8 +184,8 @@ fn invert_unit( _identifier: &str, _expr: &Expr, ) -> Result<(Expr, Expr), CalcError> { - Err(CalcError::UnsupportedExpression(String::from( - "Cannot invert expressions containing other units (yet).", + Err(CalcError::UnableToInvert(String::from( + "Expressions containing other units (this should be supported in the future).", ))) } @@ -178,6 +207,48 @@ fn invert_fn_call( identifier: &str, arguments: &Vec, ) -> Result<(Expr, Expr), CalcError> { + // If prelude function + match arguments.len() { + 1 => { + if prelude::UNARY_FUNCS.contains_key(identifier) { + if let Some(fn_inv) = INVERSE_UNARY_FUNCS.get(identifier) { + return Ok(( + Expr::FnCall(fn_inv.to_string(), vec![target_expr]), + arguments[0].clone(), + )); + } else { + match identifier { + "sqrt" => { + return Ok(( + Expr::Binary( + Box::new(target_expr), + TokenKind::Power, + Box::new(Expr::Literal(String::from("2"))), + ), + arguments[0].clone(), + )); + } + _ => { + return Err(CalcError::UnableToInvert(format!( + "Function '{}'", + identifier + ))); + } + } + } + } + } + 2 => { + if prelude::BINARY_FUNCS.contains_key(identifier) { + return Err(CalcError::UnableToInvert(format!( + "Function '{}'", + identifier + ))); + } + } + _ => (), + } + // Get the function definition from the symbol table. let (parameters, body) = if let Some(Stmt::FnDecl(_, parameters, body)) = symbol_table.get_fn(identifier).cloned() { @@ -262,8 +333,8 @@ fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result { TokenKind::Star, Box::new(base_expr.clone()), )), - Expr::Group(_) => Err(CalcError::UnsupportedExpression(String::from( - "Cannot invert parenthesis multiplied with parenthesis (yet).", + Expr::Group(_) => Err(CalcError::UnableToInvert(String::from( + "Parenthesis multiplied with parenthesis (this should be possible in the future).", ))), _ => unimplemented!(), } diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index 446d522..84aef27 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -70,7 +70,7 @@ pub enum CalcError { UnexpectedToken(TokenKind), UndefinedFn(String), UndefinedVar(String), - UnsupportedExpression(String), + UnableToInvert(String), Unknown, } diff --git a/kalk_cli/src/output.rs b/kalk_cli/src/output.rs index 684f9be..fa5d9eb 100644 --- a/kalk_cli/src/output.rs +++ b/kalk_cli/src/output.rs @@ -94,9 +94,9 @@ fn print_calc_err(err: CalcError) { InvalidOperator => format!("Invalid operator."), InvalidUnit => format!("Invalid unit."), UnexpectedToken(kind) => format!("Unexpected token: '{:?}'.", kind), + UnableToInvert(msg) => format!("Unable to invert: {}", msg), UndefinedFn(name) => format!("Undefined function: '{}'.", name), UndefinedVar(name) => format!("Undefined variable: '{}'.", name), - UnsupportedExpression(msg) => format!("{}", msg), Unknown => format!("Unknown error."), }); }