Renamed CalcError to KalkError

This commit is contained in:
PaddiM8 2022-03-27 21:32:50 +02:00
parent b9a6bfaab2
commit 3228573828
6 changed files with 160 additions and 161 deletions

View File

@ -3,11 +3,10 @@ Overview of features
Groups: (), ⌈⌉, ⌊⌋, []
Pre-defined functions and constants
User-defined functions and variables
User-defined units (experimental and limited)
Understands fairly ambiguous syntax. Eg. 2sinx + 2xy
Syntax highlighting
Completion for special symbols on tab
Sum functions
Sum/prod functions
Operators
+, -, *, /

View File

@ -2,7 +2,7 @@ use crate::{
ast::{ConditionalPiece, Expr, Identifier, RangedVar, Stmt},
inverter,
lexer::TokenKind,
parser::{self, CalcError},
parser::{self, KalkError},
prelude,
symbol_table::SymbolTable,
};
@ -25,7 +25,7 @@ pub(crate) struct Context<'a> {
pub(crate) fn analyse_stmt(
symbol_table: &mut SymbolTable,
statement: Stmt,
) -> Result<Stmt, CalcError> {
) -> Result<Stmt, KalkError> {
let mut context = Context {
symbol_table,
current_function_name: None,
@ -77,7 +77,7 @@ pub(crate) fn analyse_stmt(
})
}
fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, CalcError> {
fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, KalkError> {
Ok(
if let Expr::Binary(left, TokenKind::Equals, right) = value {
match *left {
@ -125,11 +125,11 @@ fn analyse_stmt_expr(context: &mut Context, value: Expr) -> Result<Stmt, CalcErr
}
Expr::Var(identifier) if !context.in_conditional => {
if inverter::contains_var(context.symbol_table, &right, &identifier.full_name) {
return Err(CalcError::VariableReferencesItself);
return Err(KalkError::VariableReferencesItself);
}
if prelude::is_constant(&identifier.full_name) {
return Err(CalcError::UnableToOverrideConstant(identifier.pure_name));
return Err(KalkError::UnableToOverrideConstant(identifier.pure_name));
}
let result =
@ -155,7 +155,7 @@ fn build_fn_decl_from_scratch(
identifier_expr: Expr,
parameter_expr: Expr,
right: Expr,
) -> Result<Stmt, CalcError> {
) -> Result<Stmt, KalkError> {
Ok(match identifier_expr {
Expr::Var(identifier) if !prelude::is_prelude_func(&identifier.full_name) => {
// Check if all the expressions in the parameter_expr are
@ -229,7 +229,7 @@ fn build_fn_decl_from_scratch(
})
}
fn analyse_expr(context: &mut Context, expr: Expr) -> Result<Expr, CalcError> {
fn analyse_expr(context: &mut Context, expr: Expr) -> Result<Expr, KalkError> {
Ok(match expr {
Expr::Binary(left, op, right) => analyse_binary(context, *left, op, *right)?,
Expr::Unary(op, value) => Expr::Unary(op, Box::new(analyse_expr(context, *value)?)),
@ -291,7 +291,7 @@ fn analyse_binary(
left: Expr,
op: TokenKind,
right: Expr,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
let previous_in_conditional = context.in_conditional;
if op == TokenKind::And || op == TokenKind::Or {
context.in_conditional = true;
@ -335,7 +335,7 @@ fn analyse_binary(
// If the inverted expression still contains the variable,
// the equation solving failed.
if inverter::contains_var(context.symbol_table, &inverted, var_name) {
return Err(CalcError::UnableToSolveEquation);
return Err(KalkError::UnableToSolveEquation);
}
context.symbol_table.insert(Stmt::VarDecl(
@ -440,7 +440,7 @@ fn analyse_comparison_with_var(
var: Expr,
op: TokenKind,
right: Expr,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
let right = analyse_expr(context, right)?;
if context.comprehension_vars.is_none() {
@ -503,7 +503,7 @@ fn analyse_var(
identifier: Identifier,
adjacent_factor: Option<Expr>,
adjacent_exponent: Option<Expr>,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
let adjacent_factor = if let Some(adjacent_factor) = adjacent_factor {
Some(analyse_expr(context, adjacent_factor)?)
} else {
@ -582,7 +582,7 @@ fn with_adjacent(
expr: Expr,
factor: Option<Expr>,
exponent: Option<Expr>,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
if let Some(factor) = factor {
Ok(Expr::Binary(
Box::new(expr),
@ -600,7 +600,7 @@ fn with_adjacent(
}
}
fn build_indexed_var(context: &mut Context, identifier: Identifier) -> Result<Expr, CalcError> {
fn build_indexed_var(context: &mut Context, identifier: Identifier) -> Result<Expr, KalkError> {
let underscore_pos = identifier.pure_name.find('_').unwrap();
let var_name = &identifier.pure_name[0..underscore_pos];
let lowered = &identifier.pure_name[underscore_pos + 1..];
@ -621,7 +621,7 @@ fn build_dx(
context: &mut Context,
name_without_dx: &str,
char_after_d: char,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
if name_without_dx.is_empty() {
Ok(Expr::Var(Identifier::from_full_name(&format!(
"d{}",
@ -649,7 +649,7 @@ fn build_split_up_vars(
identifier: Identifier,
adjacent_factor: Option<Expr>,
adjacent_exponent: Option<Expr>,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
let mut chars: Vec<char> = identifier.pure_name.chars().collect();
let last_char = chars.pop().unwrap_or_default();
let identifier_without_last: String = chars.iter().collect();
@ -737,7 +737,7 @@ fn analyse_fn(
context: &mut Context,
identifier: Identifier,
arguments: Vec<Expr>,
) -> Result<Expr, CalcError> {
) -> Result<Expr, KalkError> {
let is_integral = identifier.pure_name == "integrate";
let prev_in_integral = context.in_integral;
if is_integral {

View File

@ -7,13 +7,13 @@ use crate::float;
use crate::interpreter;
use crate::kalk_value::KalkValue;
use crate::lexer::TokenKind;
use crate::parser::CalcError;
use crate::parser::KalkError;
pub fn derive_func(
context: &mut interpreter::Context,
name: &Identifier,
argument: KalkValue,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
const H: f64 = 0.000001;
let unit = argument.get_unit().cloned();
@ -45,7 +45,7 @@ pub fn integrate_with_unknown_variable(
a: &Expr,
b: &Expr,
expr: &Expr,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let mut integration_variable: Option<&str> = None;
// integral(a, b, expr dx)
@ -59,7 +59,7 @@ pub fn integrate_with_unknown_variable(
}
if integration_variable.is_none() {
return Err(CalcError::ExpectedDx);
return Err(KalkError::ExpectedDx);
}
// "dx" is still in the expression. Set dx = 1, so that it doesn't affect the expression value.
@ -77,7 +77,7 @@ pub fn integrate(
b: &Expr,
expr: &Expr,
integration_variable: &str,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
Ok(simpsons_rule(context, a, b, expr, integration_variable)?.round_if_needed())
}
@ -88,7 +88,7 @@ fn simpsons_rule(
b_expr: &Expr,
expr: &Expr,
integration_variable: &str,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let mut result_real = float!(0);
let mut result_imaginary = float!(0);
let original_variable_value = context

View File

@ -3,7 +3,7 @@ use crate::ast::{Identifier, RangedVar};
use crate::calculation_result::CalculationResult;
use crate::kalk_value::KalkValue;
use crate::lexer::TokenKind;
use crate::parser::CalcError;
use crate::parser::KalkError;
use crate::parser::DECL_UNIT;
use crate::symbol_table::SymbolTable;
use crate::{as_number_or_zero, calculus};
@ -44,7 +44,7 @@ impl<'a> Context<'a> {
pub fn interpret(
&mut self,
statements: Vec<Stmt>,
) -> Result<Option<CalculationResult>, CalcError> {
) -> Result<Option<CalculationResult>, KalkError> {
for (i, stmt) in statements.iter().enumerate() {
let num = eval_stmt(self, stmt)?;
@ -80,7 +80,7 @@ struct SumVar {
value: i128,
}
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, CalcError> {
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, KalkError> {
match stmt {
Stmt::VarDecl(_, _) => eval_var_decl_stmt(context, stmt),
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(),
@ -89,20 +89,20 @@ fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, CalcError>
}
}
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, CalcError> {
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt) -> Result<KalkValue, KalkError> {
context.symbol_table.insert(stmt.clone());
Ok(KalkValue::from(1))
}
fn eval_fn_decl_stmt() -> Result<KalkValue, CalcError> {
fn eval_fn_decl_stmt() -> Result<KalkValue, KalkError> {
Ok(KalkValue::from(1)) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
}
fn eval_unit_decl_stmt() -> Result<KalkValue, CalcError> {
fn eval_unit_decl_stmt() -> Result<KalkValue, KalkError> {
Ok(KalkValue::from(1))
}
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkValue, CalcError> {
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkValue, KalkError> {
eval_expr(context, expr, None)
}
@ -110,11 +110,11 @@ pub(crate) fn eval_expr(
context: &mut Context,
expr: &Expr,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
#[cfg(not(target_arch = "wasm32"))]
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
if elapsed.as_millis() >= timeout {
return Err(CalcError::TimedOut);
return Err(KalkError::TimedOut);
}
}
@ -144,7 +144,7 @@ fn eval_binary_expr(
op: &TokenKind,
right_expr: &Expr,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
if let TokenKind::ToKeyword = op {
// TODO: When the unit conversion function takes a Float instead of Expr,
// move this to the match statement further down.
@ -201,14 +201,14 @@ fn eval_unary_expr(
op: &TokenKind,
expr: &Expr,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let num = eval_expr(context, expr, unit)?;
match op {
TokenKind::Minus => Ok(num.mul(context, KalkValue::from(-1f64))),
TokenKind::Percent => Ok(num.mul(context, KalkValue::from(0.01f64))),
TokenKind::Exclamation => Ok(prelude::special_funcs::factorial(num)),
_ => Err(CalcError::InvalidOperator),
_ => Err(KalkError::InvalidOperator),
}
}
@ -216,7 +216,7 @@ fn eval_unit_expr(
context: &mut Context,
identifier: &str,
expr: &Expr,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let angle_unit = &context.angle_unit.clone();
if (identifier == "rad" || identifier == "deg") && angle_unit != identifier {
return convert_unit(
@ -235,11 +235,11 @@ pub fn convert_unit(
expr: &Expr,
from_unit: Option<&String>,
to_unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let (from_unit, to_unit) = if let (Some(from_unit), Some(to_unit)) = (from_unit, to_unit) {
(from_unit, to_unit)
} else {
return Err(CalcError::InvalidUnit);
return Err(KalkError::InvalidUnit);
};
if let Some(Stmt::UnitDecl(_, _, unit_def)) =
@ -253,7 +253,7 @@ pub fn convert_unit(
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, None)?);
Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone())))
} else {
Err(CalcError::InvalidUnit)
Err(KalkError::InvalidUnit)
}
}
@ -261,7 +261,7 @@ fn eval_var_expr(
context: &mut Context,
identifier: &Identifier,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
// If there is a constant with this name, return a literal expression with its value
if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
return eval_expr(context, &Expr::Literal(*value), unit);
@ -284,7 +284,7 @@ fn eval_var_expr(
if let Some(Stmt::VarDecl(_, expr)) = var_decl {
eval_expr(context, &expr, unit)
} else {
Err(CalcError::UndefinedVar(identifier.full_name.clone()))
Err(KalkError::UndefinedVar(identifier.full_name.clone()))
}
}
@ -294,7 +294,7 @@ fn eval_literal_expr(
context: &mut Context,
value: f64,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let mut float = float!(value);
float.set_prec(context.precision);
@ -307,7 +307,7 @@ fn eval_literal_expr(
context: &mut Context,
value: f64,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
Ok(KalkValue::Number(float!(value), float!(0), unit.cloned()))
}
@ -315,7 +315,7 @@ fn eval_group_expr(
context: &mut Context,
expr: &Expr,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
eval_expr(context, expr, unit)
}
@ -324,7 +324,7 @@ pub(crate) fn eval_fn_call_expr(
identifier: &Identifier,
expressions: &[Expr],
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
// Special functions
match identifier.full_name.as_ref() {
"sum" | "prod" => {
@ -333,7 +333,7 @@ pub(crate) fn eval_fn_call_expr(
if let Expr::Var(var_identifier) = &**left {
// Make sure exactly 3 arguments were supplied.
if expressions.len() != 3 {
return Err(CalcError::IncorrectAmountOfArguments(
return Err(KalkError::IncorrectAmountOfArguments(
3,
"sum/prod".into(),
expressions.len(),
@ -369,10 +369,10 @@ pub(crate) fn eval_fn_call_expr(
if let Expr::Var(integration_variable) = &expressions[3] {
&integration_variable.full_name[1..]
} else {
return Err(CalcError::ExpectedDx);
return Err(KalkError::ExpectedDx);
},
),
_ => Err(CalcError::IncorrectAmountOfArguments(
_ => Err(KalkError::IncorrectAmountOfArguments(
3,
"integrate".into(),
expressions.len(),
@ -496,7 +496,7 @@ pub(crate) fn eval_fn_call_expr(
match stmt_definition {
Some(Stmt::FnDecl(_, arguments, fn_body)) => {
if arguments.len() != expressions.len() {
return Err(CalcError::IncorrectAmountOfArguments(
return Err(KalkError::IncorrectAmountOfArguments(
arguments.len(),
identifier.full_name.clone(),
expressions.len(),
@ -549,7 +549,7 @@ pub(crate) fn eval_fn_call_expr(
fn_value
}
_ => Err(CalcError::UndefinedFn(identifier.full_name.clone())),
_ => Err(KalkError::UndefinedFn(identifier.full_name.clone())),
}
}
@ -561,7 +561,7 @@ fn eval_loop(
end_expr: &Expr,
expression: &Expr,
unit: Option<String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
if context.sum_variables.is_none() {
context.sum_variables = Some(Vec::new());
}
@ -611,7 +611,7 @@ fn eval_piecewise(
context: &mut Context,
pieces: &[crate::ast::ConditionalPiece],
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
for piece in pieces {
if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? {
if condition_is_true {
@ -620,10 +620,10 @@ fn eval_piecewise(
}
}
Err(CalcError::PiecewiseConditionsAreFalse)
Err(KalkError::PiecewiseConditionsAreFalse)
}
fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, CalcError> {
fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, KalkError> {
let mut eval_values = Vec::new();
for value in values {
eval_values.push(eval_expr(context, value, None)?);
@ -632,7 +632,7 @@ fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, Calc
Ok(KalkValue::Vector(eval_values))
}
fn eval_matrix(context: &mut Context, rows: &[Vec<Expr>]) -> Result<KalkValue, CalcError> {
fn eval_matrix(context: &mut Context, rows: &[Vec<Expr>]) -> Result<KalkValue, KalkError> {
let mut eval_rows = Vec::new();
for row in rows {
let mut eval_row = Vec::new();
@ -651,12 +651,12 @@ fn eval_indexer(
var: &Expr,
index_expressions: &[Expr],
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
) -> Result<KalkValue, KalkError> {
let var_value = eval_expr(context, var, unit)?;
match var_value {
KalkValue::Vector(values) => {
if index_expressions.len() != 1 {
return Err(CalcError::IncorrectAmountOfIndexes(
return Err(KalkError::IncorrectAmountOfIndexes(
index_expressions.len(),
1,
));
@ -666,7 +666,7 @@ fn eval_indexer(
if let Some(value) = values.get(index - 1) {
Ok(value.clone())
} else {
Err(CalcError::ItemOfIndexDoesNotExist(vec![index]))
Err(KalkError::ItemOfIndexDoesNotExist(vec![index]))
}
}
KalkValue::Matrix(rows) => {
@ -676,18 +676,18 @@ fn eval_indexer(
return if let Some(row) = rows.get(row_index - 1) {
Ok(KalkValue::Vector(row.clone()))
} else {
Err(CalcError::ItemOfIndexDoesNotExist(vec![row_index]))
Err(KalkError::ItemOfIndexDoesNotExist(vec![row_index]))
};
}
if indices.len() != 2 {
return Err(CalcError::IncorrectAmountOfIndexes(indices.len(), 2));
return Err(KalkError::IncorrectAmountOfIndexes(indices.len(), 2));
}
let row_index = indices[0];
let column_index = indices[1];
if row_index == 0 || column_index == 0 {
return Err(CalcError::ItemOfIndexDoesNotExist(vec![
return Err(KalkError::ItemOfIndexDoesNotExist(vec![
row_index,
column_index,
]));
@ -699,26 +699,26 @@ fn eval_indexer(
}
}
Err(CalcError::ItemOfIndexDoesNotExist(vec![
Err(KalkError::ItemOfIndexDoesNotExist(vec![
row_index,
column_index,
]))
}
_ => Err(CalcError::CanOnlyIndexX),
_ => Err(KalkError::CanOnlyIndexX),
}
}
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, CalcError> {
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, KalkError> {
let mut indices = Vec::new();
for expr in expressions {
let value = eval_expr(context, expr, None)?;
if value.has_imaginary() {
return Err(CalcError::CannotIndexByImaginary);
return Err(KalkError::CannotIndexByImaginary);
}
let index = value.to_f64() as usize;
if index == 0 {
return Err(CalcError::ItemOfIndexDoesNotExist(vec![index]));
return Err(KalkError::ItemOfIndexDoesNotExist(vec![index]));
}
indices.push(index);
@ -732,9 +732,9 @@ fn eval_comprehension(
left: &Expr,
conditions: &[Expr],
vars: &[RangedVar],
) -> Result<Vec<KalkValue>, CalcError> {
) -> Result<Vec<KalkValue>, KalkError> {
if vars.len() != conditions.len() {
return Err(CalcError::InvalidComprehension(String::from("Expected a new variable to be introduced for every condition (conditions are comma separated).")));
return Err(KalkError::InvalidComprehension(String::from("Expected a new variable to be introduced for every condition (conditions are comma separated).")));
}
let condition = conditions.first().unwrap();
@ -806,7 +806,7 @@ mod tests {
);
}
fn interpret_with_unit(stmt: Stmt) -> Result<Option<CalculationResult>, CalcError> {
fn interpret_with_unit(stmt: Stmt) -> Result<Option<CalculationResult>, KalkError> {
let mut symbol_table = SymbolTable::new();
symbol_table
.insert(DEG_RAD_UNIT.clone())
@ -815,7 +815,7 @@ mod tests {
context(&mut symbol_table, "rad").interpret(vec![stmt])
}
fn interpret(stmt: Stmt) -> Result<Option<KalkValue>, CalcError> {
fn interpret(stmt: Stmt) -> Result<Option<KalkValue>, KalkError> {
if let Some(result) = interpret_with_unit(stmt)? {
Ok(Some(result.get_value()))
} else {
@ -976,7 +976,7 @@ mod tests {
assert_eq!(
interpret(stmt),
Err(CalcError::UndefinedVar(String::from("x")))
Err(KalkError::UndefinedVar(String::from("x")))
);
}
@ -1016,7 +1016,7 @@ mod tests {
assert_eq!(
interpret(stmt),
Err(CalcError::UndefinedFn(String::from("f")))
Err(KalkError::UndefinedFn(String::from("f")))
);
}

View File

@ -1,7 +1,7 @@
use crate::ast::Identifier;
use crate::ast::{Expr, Stmt};
use crate::lexer::TokenKind;
use crate::parser::CalcError;
use crate::parser::KalkError;
use crate::prelude;
use crate::symbol_table::SymbolTable;
use lazy_static::lazy_static;
@ -44,7 +44,7 @@ impl Expr {
&self,
symbol_table: &mut SymbolTable,
unknown_var: &str,
) -> Result<Self, CalcError> {
) -> Result<Self, KalkError> {
let target_expr = Expr::Var(Identifier::from_full_name(unknown_var));
let result = invert(target_expr, symbol_table, self, unknown_var);
@ -56,7 +56,7 @@ impl Expr {
symbol_table: &mut SymbolTable,
target_expr: Expr,
unknown_var: &str,
) -> Result<Self, CalcError> {
) -> Result<Self, KalkError> {
let x = invert(target_expr, symbol_table, self, unknown_var)?;
Ok(x.0)
}
@ -67,7 +67,7 @@ fn invert(
symbol_table: &mut SymbolTable,
expr: &Expr,
unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> {
) -> Result<(Expr, Expr), KalkError> {
match expr {
Expr::Binary(left, op, right) => {
invert_binary(target_expr, symbol_table, left, op, right, unknown_var)
@ -86,12 +86,12 @@ fn invert(
unknown_var,
),
Expr::Literal(_) => Ok((target_expr, expr.clone())),
Expr::Piecewise(_) => Err(CalcError::UnableToInvert(String::from("Piecewise"))),
Expr::Vector(_) => Err(CalcError::UnableToInvert(String::from("Vector"))),
Expr::Matrix(_) => Err(CalcError::UnableToInvert(String::from("Matrix"))),
Expr::Indexer(_, _) => Err(CalcError::UnableToInvert(String::from("Inverter"))),
Expr::Piecewise(_) => Err(KalkError::UnableToInvert(String::from("Piecewise"))),
Expr::Vector(_) => Err(KalkError::UnableToInvert(String::from("Vector"))),
Expr::Matrix(_) => Err(KalkError::UnableToInvert(String::from("Matrix"))),
Expr::Indexer(_, _) => Err(KalkError::UnableToInvert(String::from("Inverter"))),
Expr::Comprehension(_, _, _) => {
Err(CalcError::UnableToInvert(String::from("Comprehension")))
Err(KalkError::UnableToInvert(String::from("Comprehension")))
}
}
}
@ -103,7 +103,7 @@ fn invert_binary(
op: &TokenKind,
right: &Expr,
unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> {
) -> Result<(Expr, Expr), KalkError> {
let op_inv = match op {
TokenKind::Plus => TokenKind::Minus,
TokenKind::Minus => {
@ -194,7 +194,7 @@ fn invert_binary(
)
};
}
_ => return Err(CalcError::UnableToInvert(String::new())),
_ => return Err(KalkError::UnableToInvert(String::new())),
};
// If the left expression contains the unit, invert the right one instead,
@ -203,7 +203,7 @@ fn invert_binary(
// But if the right expression *also* contains the unit,
// throw an error, since it can't handle this yet.
if contains_var(symbol_table, right, unknown_var) {
return Err(CalcError::UnableToInvert(String::from(
return Err(KalkError::UnableToInvert(String::from(
"Expressions with several instances of an unknown variable (this might be supported in the future). Try simplifying the expression.",
)));
}
@ -233,14 +233,14 @@ fn invert_binary(
)
}
fn invert_unary(target_expr: Expr, op: &TokenKind, expr: &Expr) -> Result<(Expr, Expr), CalcError> {
fn invert_unary(target_expr: Expr, op: &TokenKind, expr: &Expr) -> Result<(Expr, Expr), KalkError> {
match op {
TokenKind::Minus => Ok((
// Make the target expression negative
Expr::Unary(TokenKind::Minus, Box::new(target_expr)),
expr.clone(), // And then continue inverting the inner-expression.
)),
_ => Err(CalcError::UnableToInvert(String::new())),
_ => Err(KalkError::UnableToInvert(String::new())),
}
}
@ -250,7 +250,7 @@ fn invert_unit(
identifier: &str,
expr: &Expr,
unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> {
) -> Result<(Expr, Expr), KalkError> {
let x = Expr::Binary(
Box::new(target_expr),
TokenKind::ToKeyword,
@ -264,7 +264,7 @@ fn invert_var(
symbol_table: &mut SymbolTable,
identifier: &Identifier,
unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> {
) -> Result<(Expr, Expr), KalkError> {
if identifier.full_name == unknown_var {
Ok((target_expr, Expr::Var(identifier.clone())))
} else if let Some(Stmt::VarDecl(_, var_expr)) =
@ -282,7 +282,7 @@ fn invert_fn_call(
identifier: &Identifier,
arguments: &[Expr],
unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> {
) -> Result<(Expr, Expr), KalkError> {
// If prelude function
match arguments.len() {
1 => {
@ -310,7 +310,7 @@ fn invert_fn_call(
);
}
_ => {
return Err(CalcError::UnableToInvert(format!(
return Err(KalkError::UnableToInvert(format!(
"Function '{}'",
identifier.full_name
)));
@ -321,7 +321,7 @@ fn invert_fn_call(
}
2 => {
if prelude::BINARY_FUNCS.contains_key(identifier.full_name.as_ref() as &str) {
return Err(CalcError::UnableToInvert(format!(
return Err(KalkError::UnableToInvert(format!(
"Function '{}'",
identifier.full_name
)));
@ -336,12 +336,12 @@ fn invert_fn_call(
{
(parameters, body)
} else {
return Err(CalcError::UndefinedFn(identifier.full_name.clone()));
return Err(KalkError::UndefinedFn(identifier.full_name.clone()));
};
// Make sure the input is valid.
if parameters.len() != arguments.len() {
return Err(CalcError::IncorrectAmountOfArguments(
return Err(KalkError::IncorrectAmountOfArguments(
parameters.len(),
identifier.full_name.clone(),
arguments.len(),
@ -404,7 +404,7 @@ pub fn contains_var(symbol_table: &SymbolTable, expr: &Expr, var_name: &str) ->
}
/// Multiply an expression into a group.
fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, KalkError> {
match base_expr {
Expr::Binary(left, op, right) => match op {
// If + or -, multiply the expression with each term.
@ -419,7 +419,7 @@ fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
*op,
right.clone(),
)),
_ => Err(CalcError::UnableToInvert(String::new())),
_ => Err(KalkError::UnableToInvert(String::new())),
},
// If it's a literal, just multiply them together.
Expr::Literal(_) | Expr::Var(_) => Ok(Expr::Binary(
@ -427,10 +427,10 @@ fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
TokenKind::Star,
Box::new(base_expr.clone()),
)),
Expr::Group(_) => Err(CalcError::UnableToInvert(String::from(
Expr::Group(_) => Err(KalkError::UnableToInvert(String::from(
"Parenthesis multiplied with parenthesis (this should be possible in the future).",
))),
_ => Err(CalcError::UnableToInvert(String::new())),
_ => Err(KalkError::UnableToInvert(String::new())),
}
}

View File

@ -88,7 +88,7 @@ impl Default for Context {
/// Error that occured during parsing or evaluation.
#[derive(Debug, Clone, PartialEq)]
pub enum CalcError {
pub enum KalkError {
CannotIndexByImaginary,
CanOnlyIndexX,
Expected(String),
@ -116,42 +116,42 @@ pub enum CalcError {
Unknown,
}
impl ToString for CalcError {
impl ToString for KalkError {
fn to_string(&self) -> String {
match self {
CalcError::CannotIndexByImaginary => String::from("Cannot index by imaginary numbers."),
CalcError::CanOnlyIndexX => String::from("Indexing (getting an item with a specific index) is only possible on vectors and matrices."),
CalcError::Expected(description) => format!("Expected: {}", description),
CalcError::ExpectedDx => String::from("Expected eg. dx, to specify for which variable the operation is being done to. Example with integration: ∫(0, 1, x dx) or ∫(0, 1, x, dx). You may need to put parenthesis around the expression before dx/dy/du/etc."),
CalcError::ExpectedIf => String::from("Expected 'if', with a condition after it."),
CalcError::IncorrectAmountOfArguments(expected, func, got) => format!(
KalkError::CannotIndexByImaginary => String::from("Cannot index by imaginary numbers."),
KalkError::CanOnlyIndexX => String::from("Indexing (getting an item with a specific index) is only possible on vectors and matrices."),
KalkError::Expected(description) => format!("Expected: {}", description),
KalkError::ExpectedDx => String::from("Expected eg. dx, to specify for which variable the operation is being done to. Example with integration: ∫(0, 1, x dx) or ∫(0, 1, x, dx). You may need to put parenthesis around the expression before dx/dy/du/etc."),
KalkError::ExpectedIf => String::from("Expected 'if', with a condition after it."),
KalkError::IncorrectAmountOfArguments(expected, func, got) => format!(
"Expected {} arguments for function {}, but got {}.",
expected, func, got
),
CalcError::IncorrectAmountOfIndexes(expected, got) => format!(
KalkError::IncorrectAmountOfIndexes(expected, got) => format!(
"Expected {} indexes but got {}.",
expected, got
),
CalcError::ItemOfIndexDoesNotExist(indexes) => format!("Item of index ⟦{}⟧ does not exist.", indexes.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(", ")),
CalcError::InconsistentColumnWidths => String::from("Inconsistent column widths. Matrix columns must be the same size."),
CalcError::InvalidComprehension(x) => format!("Invalid comprehension: {}", x),
CalcError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
CalcError::InvalidOperator => String::from("Invalid operator."),
CalcError::InvalidUnit => String::from("Invalid unit."),
CalcError::TimedOut => String::from("Operation took too long."),
CalcError::VariableReferencesItself => String::from("Variable references itself."),
CalcError::PiecewiseConditionsAreFalse => String::from("All the conditions in the piecewise are false."),
CalcError::UnexpectedToken(got, expected) => {
KalkError::ItemOfIndexDoesNotExist(indexes) => format!("Item of index ⟦{}⟧ does not exist.", indexes.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(", ")),
KalkError::InconsistentColumnWidths => String::from("Inconsistent column widths. Matrix columns must be the same size."),
KalkError::InvalidComprehension(x) => format!("Invalid comprehension: {}", x),
KalkError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
KalkError::InvalidOperator => String::from("Invalid operator."),
KalkError::InvalidUnit => String::from("Invalid unit."),
KalkError::TimedOut => String::from("Operation took too long."),
KalkError::VariableReferencesItself => String::from("Variable references itself."),
KalkError::PiecewiseConditionsAreFalse => String::from("All the conditions in the piecewise are false."),
KalkError::UnexpectedToken(got, expected) => {
format!("Unexpected token: '{:?}', expected '{:?}'.", got, expected)
}
CalcError::UnableToInvert(msg) => format!("Unable to invert: {}", msg),
CalcError::UndefinedFn(name) => format!("Undefined function: '{}'.", name),
CalcError::UndefinedVar(name) => format!("Undefined variable: '{}'.", name),
CalcError::UnableToParseExpression => String::from("Unable to parse expression."),
CalcError::UnableToSolveEquation => String::from("Unable to solve equation."),
CalcError::UnableToOverrideConstant(name) => format!("Unable to override constant: '{}'.", name),
CalcError::UnrecognizedBase => String::from("Unrecognized base."),
CalcError::Unknown => String::from("Unknown error."),
KalkError::UnableToInvert(msg) => format!("Unable to invert: {}", msg),
KalkError::UndefinedFn(name) => format!("Undefined function: '{}'.", name),
KalkError::UndefinedVar(name) => format!("Undefined variable: '{}'.", name),
KalkError::UnableToParseExpression => String::from("Unable to parse expression."),
KalkError::UnableToSolveEquation => String::from("Unable to solve equation."),
KalkError::UnableToOverrideConstant(name) => format!("Unable to override constant: '{}'.", name),
KalkError::UnrecognizedBase => String::from("Unrecognized base."),
KalkError::Unknown => String::from("Unknown error."),
}
}
}
@ -163,7 +163,7 @@ pub fn eval(
context: &mut Context,
input: &str,
#[cfg(feature = "rug")] precision: u32,
) -> Result<Option<CalculationResult>, CalcError> {
) -> Result<Option<CalculationResult>, KalkError> {
let statements = parse(context, input)?;
let symbol_table = context.symbol_table.get_mut();
@ -186,7 +186,7 @@ pub fn eval(
/// Parse expressions/declarations and return a syntax tree.
///
/// `None` will be returned if the last statement is a declaration.
pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, CalcError> {
pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, KalkError> {
let mut lexer = Lexer::new(input);
context.tokens = lexer.lex();
context.pos = 0;
@ -211,7 +211,7 @@ pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, CalcError>
Ok(statements)
}
fn parse_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
fn parse_stmt(context: &mut Context) -> Result<Stmt, KalkError> {
if match_token(context, TokenKind::UnitKeyword) {
parse_unit_decl_stmt(context)
} else {
@ -219,7 +219,7 @@ fn parse_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
}
}
fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_piecewise(context: &mut Context) -> Result<Expr, KalkError> {
advance(context);
skip_newlines(context);
@ -250,7 +250,7 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
reached_otherwise = true;
} else {
return Err(CalcError::ExpectedIf);
return Err(KalkError::ExpectedIf);
}
if match_token(context, TokenKind::Semicolon) {
@ -269,7 +269,7 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
Ok(Expr::Piecewise(pieces))
}
fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, KalkError> {
advance(context); // Unit keyword
let identifier = advance(context).clone();
consume(context, TokenKind::Equals)?;
@ -283,7 +283,7 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
let base_unit = if let Some(base_unit) = &context.unit_decl_base_unit {
base_unit.clone()
} else {
return Err(CalcError::InvalidUnit);
return Err(KalkError::InvalidUnit);
};
// Automatically create a second unit decl with the expression inverted.
@ -302,11 +302,11 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
Ok(stmt)
}
fn parse_expr(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_expr(context: &mut Context) -> Result<Expr, KalkError> {
parse_or(context)
}
fn parse_comprehension(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_comprehension(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_or(context)?;
if match_token(context, TokenKind::Colon) {
@ -319,7 +319,7 @@ fn parse_comprehension(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_or(context)?;
if match_token(context, TokenKind::Comma) {
@ -332,7 +332,7 @@ fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_or(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_or(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_and(context)?;
if match_token(context, TokenKind::Or) {
@ -345,7 +345,7 @@ fn parse_or(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_and(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_and(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_comparison(context)?;
if match_token(context, TokenKind::And) {
@ -358,7 +358,7 @@ fn parse_and(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_comparison(context: &mut Context) -> Result<Expr, KalkError> {
let mut left = parse_to(context)?;
// Equality check
@ -460,7 +460,7 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_to(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_to(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_term(context)?;
if match_token(context, TokenKind::ToKeyword) {
@ -477,7 +477,7 @@ fn parse_to(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_term(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_term(context: &mut Context) -> Result<Expr, KalkError> {
let mut left = parse_factor(context)?;
while match_token(context, TokenKind::Plus) || match_token(context, TokenKind::Minus) {
@ -491,7 +491,7 @@ fn parse_term(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_factor(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_factor(context: &mut Context) -> Result<Expr, KalkError> {
let mut left = parse_unit(context)?;
if let Expr::Unary(TokenKind::Percent, percent_left) = left.clone() {
@ -531,7 +531,7 @@ fn parse_factor(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_unit(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_unit(context: &mut Context) -> Result<Expr, KalkError> {
let expr = parse_exponent(context)?;
if match_token(context, TokenKind::Identifier) {
@ -547,7 +547,7 @@ fn parse_unit(context: &mut Context) -> Result<Expr, CalcError> {
Ok(expr)
}
fn parse_exponent(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_exponent(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_unary(context)?;
if match_token(context, TokenKind::Power) {
@ -559,7 +559,7 @@ fn parse_exponent(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_unary(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_unary(context: &mut Context) -> Result<Expr, KalkError> {
if match_token(context, TokenKind::Minus) {
let op = advance(context).kind;
let expr = Box::new(parse_unary(context)?);
@ -574,7 +574,7 @@ fn parse_unary(context: &mut Context) -> Result<Expr, CalcError> {
}
}
fn parse_indexer(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_indexer(context: &mut Context) -> Result<Expr, KalkError> {
let left = parse_factorial(context)?;
if match_token(context, TokenKind::OpenDoubleBracket) {
@ -593,7 +593,7 @@ fn parse_indexer(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left)
}
fn parse_factorial(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_factorial(context: &mut Context) -> Result<Expr, KalkError> {
let expr = parse_primary(context)?;
Ok(if match_token(context, TokenKind::Exclamation) {
@ -604,19 +604,19 @@ fn parse_factorial(context: &mut Context) -> Result<Expr, CalcError> {
})
}
fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_primary(context: &mut Context) -> Result<Expr, KalkError> {
let expr = match peek(context).kind {
TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?,
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
TokenKind::Identifier => parse_identifier(context)?,
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
_ => return Err(CalcError::UnableToParseExpression),
_ => return Err(KalkError::UnableToParseExpression),
};
Ok(expr)
}
fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_group_fn(context: &mut Context) -> Result<Expr, KalkError> {
let name = match &peek(context).kind {
TokenKind::Pipe => "abs",
TokenKind::OpenCeil => "ceil",
@ -634,7 +634,7 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
}
}
fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_vector(context: &mut Context) -> Result<Expr, KalkError> {
let kind = advance(context).kind;
if kind == TokenKind::OpenBracket {
@ -660,7 +660,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
{
if let Some(columns) = column_count {
if columns != items_in_row {
return Err(CalcError::InconsistentColumnWidths);
return Err(KalkError::InconsistentColumnWidths);
}
} else {
column_count = Some(items_in_row);
@ -676,7 +676,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
}
if peek(context).kind == TokenKind::Eof {
return Err(CalcError::Expected(String::from(
return Err(KalkError::Expected(String::from(
"Closing group symbol, eg. )",
)));
}
@ -699,7 +699,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
}
}
fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
let identifier = Identifier::from_full_name(&advance(context).value);
let mut log_base = None;
@ -775,12 +775,12 @@ fn advance(context: &mut Context) -> &Token {
previous(context)
}
fn consume(context: &mut Context, kind: TokenKind) -> Result<&Token, CalcError> {
fn consume(context: &mut Context, kind: TokenKind) -> Result<&Token, KalkError> {
if match_token(context, kind) {
return Ok(advance(context));
}
Err(CalcError::UnexpectedToken(peek(context).kind, kind))
Err(KalkError::UnexpectedToken(peek(context).kind, kind))
}
fn is_at_end(context: &Context) -> bool {
@ -793,16 +793,16 @@ fn skip_newlines(context: &mut Context) {
}
}
fn string_to_num(value: &str) -> Result<f64, CalcError> {
fn string_to_num(value: &str) -> Result<f64, KalkError> {
let base = get_base(value)?;
if let Some(result) = crate::radix::parse_float_radix(&value.replace(" ", ""), base) {
Ok(result)
} else {
Err(CalcError::InvalidNumberLiteral(value.into()))
Err(KalkError::InvalidNumberLiteral(value.into()))
}
}
fn get_base(value: &str) -> Result<u8, CalcError> {
fn get_base(value: &str) -> Result<u8, KalkError> {
let underscore_pos = if let Some(i) = value.find('_') {
i
} else {
@ -813,7 +813,7 @@ fn get_base(value: &str) -> Result<u8, CalcError> {
if let Some(base) = crate::text_utils::parse_subscript(subscript) {
Ok(base)
} else {
Err(CalcError::UnrecognizedBase)
Err(KalkError::UnrecognizedBase)
}
}
@ -825,7 +825,7 @@ mod tests {
use crate::test_helpers::*;
use wasm_bindgen_test::*;
fn parse_with_context(context: &mut Context, tokens: Vec<Token>) -> Result<Stmt, CalcError> {
fn parse_with_context(context: &mut Context, tokens: Vec<Token>) -> Result<Stmt, KalkError> {
context.tokens = tokens;
context.pos = 0;
@ -834,7 +834,7 @@ mod tests {
analysis::analyse_stmt(symbol_table, parsed)
}
fn parse(tokens: Vec<Token>) -> Result<Stmt, CalcError> {
fn parse(tokens: Vec<Token>) -> Result<Stmt, KalkError> {
let mut context = Context::new();
context.tokens = tokens;
context.pos = 0;