mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-22 13:08:35 +01:00
Implemented inversion for some prelude functions.
This commit is contained in:
parent
a2376c9998
commit
1fdfcc29c1
@ -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!(),
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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."),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user