Implemented inversion for some prelude functions.

This commit is contained in:
PaddiM8 2020-06-18 16:20:18 +02:00
parent a2376c9998
commit 1fdfcc29c1
3 changed files with 79 additions and 8 deletions

View File

@ -2,8 +2,37 @@ use crate::ast::{Expr, Stmt};
use crate::lexer::TokenKind; use crate::lexer::TokenKind;
use crate::parser::CalcError; use crate::parser::CalcError;
use crate::parser::DECL_UNIT; use crate::parser::DECL_UNIT;
use crate::prelude;
use crate::symbol_table::SymbolTable; 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 { impl Expr {
pub fn invert(&self, symbol_table: &mut SymbolTable) -> Result<Self, CalcError> { pub fn invert(&self, symbol_table: &mut SymbolTable) -> Result<Self, CalcError> {
let target_expr = Expr::Var(DECL_UNIT.into()); let target_expr = Expr::Var(DECL_UNIT.into());
@ -111,8 +140,8 @@ fn invert_binary(
// But if the right expression *also* contains the unit, // But if the right expression *also* contains the unit,
// throw an error, since it can't handle this yet. // throw an error, since it can't handle this yet.
if contains_the_unit(symbol_table, right) { if contains_the_unit(symbol_table, right) {
return Err(CalcError::UnsupportedExpression(String::from( return Err(CalcError::UnableToInvert(String::from(
"Can't invert expressions with several instances of an unknown variable (yet). Try simplifying the expression.", "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, _identifier: &str,
_expr: &Expr, _expr: &Expr,
) -> Result<(Expr, Expr), CalcError> { ) -> Result<(Expr, Expr), CalcError> {
Err(CalcError::UnsupportedExpression(String::from( Err(CalcError::UnableToInvert(String::from(
"Cannot invert expressions containing other units (yet).", "Expressions containing other units (this should be supported in the future).",
))) )))
} }
@ -178,6 +207,48 @@ fn invert_fn_call(
identifier: &str, identifier: &str,
arguments: &Vec<Expr>, arguments: &Vec<Expr>,
) -> Result<(Expr, Expr), CalcError> { ) -> 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. // Get the function definition from the symbol table.
let (parameters, body) = let (parameters, body) =
if let Some(Stmt::FnDecl(_, parameters, body)) = symbol_table.get_fn(identifier).cloned() { 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<Expr, CalcError> {
TokenKind::Star, TokenKind::Star,
Box::new(base_expr.clone()), Box::new(base_expr.clone()),
)), )),
Expr::Group(_) => Err(CalcError::UnsupportedExpression(String::from( Expr::Group(_) => Err(CalcError::UnableToInvert(String::from(
"Cannot invert parenthesis multiplied with parenthesis (yet).", "Parenthesis multiplied with parenthesis (this should be possible in the future).",
))), ))),
_ => unimplemented!(), _ => unimplemented!(),
} }

View File

@ -70,7 +70,7 @@ pub enum CalcError {
UnexpectedToken(TokenKind), UnexpectedToken(TokenKind),
UndefinedFn(String), UndefinedFn(String),
UndefinedVar(String), UndefinedVar(String),
UnsupportedExpression(String), UnableToInvert(String),
Unknown, Unknown,
} }

View File

@ -94,9 +94,9 @@ fn print_calc_err(err: CalcError) {
InvalidOperator => format!("Invalid operator."), InvalidOperator => format!("Invalid operator."),
InvalidUnit => format!("Invalid unit."), InvalidUnit => format!("Invalid unit."),
UnexpectedToken(kind) => format!("Unexpected token: '{:?}'.", kind), UnexpectedToken(kind) => format!("Unexpected token: '{:?}'.", kind),
UnableToInvert(msg) => format!("Unable to invert: {}", msg),
UndefinedFn(name) => format!("Undefined function: '{}'.", name), UndefinedFn(name) => format!("Undefined function: '{}'.", name),
UndefinedVar(name) => format!("Undefined variable: '{}'.", name), UndefinedVar(name) => format!("Undefined variable: '{}'.", name),
UnsupportedExpression(msg) => format!("{}", msg),
Unknown => format!("Unknown error."), Unknown => format!("Unknown error."),
}); });
} }