Renamed CalcError to KalkError

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

View File

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

View File

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

View File

@ -7,13 +7,13 @@ use crate::float;
use crate::interpreter; use crate::interpreter;
use crate::kalk_value::KalkValue; use crate::kalk_value::KalkValue;
use crate::lexer::TokenKind; use crate::lexer::TokenKind;
use crate::parser::CalcError; use crate::parser::KalkError;
pub fn derive_func( pub fn derive_func(
context: &mut interpreter::Context, context: &mut interpreter::Context,
name: &Identifier, name: &Identifier,
argument: KalkValue, argument: KalkValue,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
const H: f64 = 0.000001; const H: f64 = 0.000001;
let unit = argument.get_unit().cloned(); let unit = argument.get_unit().cloned();
@ -45,7 +45,7 @@ pub fn integrate_with_unknown_variable(
a: &Expr, a: &Expr,
b: &Expr, b: &Expr,
expr: &Expr, expr: &Expr,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
let mut integration_variable: Option<&str> = None; let mut integration_variable: Option<&str> = None;
// integral(a, b, expr dx) // integral(a, b, expr dx)
@ -59,7 +59,7 @@ pub fn integrate_with_unknown_variable(
} }
if integration_variable.is_none() { 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. // "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, b: &Expr,
expr: &Expr, expr: &Expr,
integration_variable: &str, integration_variable: &str,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
Ok(simpsons_rule(context, a, b, expr, integration_variable)?.round_if_needed()) Ok(simpsons_rule(context, a, b, expr, integration_variable)?.round_if_needed())
} }
@ -88,7 +88,7 @@ fn simpsons_rule(
b_expr: &Expr, b_expr: &Expr,
expr: &Expr, expr: &Expr,
integration_variable: &str, integration_variable: &str,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
let mut result_real = float!(0); let mut result_real = float!(0);
let mut result_imaginary = float!(0); let mut result_imaginary = float!(0);
let original_variable_value = context let original_variable_value = context

View File

@ -3,7 +3,7 @@ use crate::ast::{Identifier, RangedVar};
use crate::calculation_result::CalculationResult; use crate::calculation_result::CalculationResult;
use crate::kalk_value::KalkValue; use crate::kalk_value::KalkValue;
use crate::lexer::TokenKind; use crate::lexer::TokenKind;
use crate::parser::CalcError; use crate::parser::KalkError;
use crate::parser::DECL_UNIT; use crate::parser::DECL_UNIT;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use crate::{as_number_or_zero, calculus}; use crate::{as_number_or_zero, calculus};
@ -44,7 +44,7 @@ impl<'a> Context<'a> {
pub fn interpret( pub fn interpret(
&mut self, &mut self,
statements: Vec<Stmt>, statements: Vec<Stmt>,
) -> Result<Option<CalculationResult>, CalcError> { ) -> Result<Option<CalculationResult>, KalkError> {
for (i, stmt) in statements.iter().enumerate() { for (i, stmt) in statements.iter().enumerate() {
let num = eval_stmt(self, stmt)?; let num = eval_stmt(self, stmt)?;
@ -80,7 +80,7 @@ struct SumVar {
value: i128, 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 { match stmt {
Stmt::VarDecl(_, _) => eval_var_decl_stmt(context, stmt), Stmt::VarDecl(_, _) => eval_var_decl_stmt(context, stmt),
Stmt::FnDecl(_, _, _) => eval_fn_decl_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()); context.symbol_table.insert(stmt.clone());
Ok(KalkValue::from(1)) 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. 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)) 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) eval_expr(context, expr, None)
} }
@ -110,11 +110,11 @@ pub(crate) fn eval_expr(
context: &mut Context, context: &mut Context,
expr: &Expr, expr: &Expr,
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) { if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
if elapsed.as_millis() >= timeout { if elapsed.as_millis() >= timeout {
return Err(CalcError::TimedOut); return Err(KalkError::TimedOut);
} }
} }
@ -144,7 +144,7 @@ fn eval_binary_expr(
op: &TokenKind, op: &TokenKind,
right_expr: &Expr, right_expr: &Expr,
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
if let TokenKind::ToKeyword = op { if let TokenKind::ToKeyword = op {
// TODO: When the unit conversion function takes a Float instead of Expr, // TODO: When the unit conversion function takes a Float instead of Expr,
// move this to the match statement further down. // move this to the match statement further down.
@ -201,14 +201,14 @@ fn eval_unary_expr(
op: &TokenKind, op: &TokenKind,
expr: &Expr, expr: &Expr,
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
let num = eval_expr(context, expr, unit)?; let num = eval_expr(context, expr, unit)?;
match op { match op {
TokenKind::Minus => Ok(num.mul(context, KalkValue::from(-1f64))), TokenKind::Minus => Ok(num.mul(context, KalkValue::from(-1f64))),
TokenKind::Percent => Ok(num.mul(context, KalkValue::from(0.01f64))), TokenKind::Percent => Ok(num.mul(context, KalkValue::from(0.01f64))),
TokenKind::Exclamation => Ok(prelude::special_funcs::factorial(num)), 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, context: &mut Context,
identifier: &str, identifier: &str,
expr: &Expr, expr: &Expr,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
let angle_unit = &context.angle_unit.clone(); let angle_unit = &context.angle_unit.clone();
if (identifier == "rad" || identifier == "deg") && angle_unit != identifier { if (identifier == "rad" || identifier == "deg") && angle_unit != identifier {
return convert_unit( return convert_unit(
@ -235,11 +235,11 @@ pub fn convert_unit(
expr: &Expr, expr: &Expr,
from_unit: Option<&String>, from_unit: Option<&String>,
to_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) { let (from_unit, to_unit) = if let (Some(from_unit), Some(to_unit)) = (from_unit, to_unit) {
(from_unit, to_unit) (from_unit, to_unit)
} else { } else {
return Err(CalcError::InvalidUnit); return Err(KalkError::InvalidUnit);
}; };
if let Some(Stmt::UnitDecl(_, _, unit_def)) = 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)?); let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, None)?);
Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone()))) Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone())))
} else { } else {
Err(CalcError::InvalidUnit) Err(KalkError::InvalidUnit)
} }
} }
@ -261,7 +261,7 @@ fn eval_var_expr(
context: &mut Context, context: &mut Context,
identifier: &Identifier, identifier: &Identifier,
unit: Option<&String>, 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 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) { if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
return eval_expr(context, &Expr::Literal(*value), unit); return eval_expr(context, &Expr::Literal(*value), unit);
@ -284,7 +284,7 @@ fn eval_var_expr(
if let Some(Stmt::VarDecl(_, expr)) = var_decl { if let Some(Stmt::VarDecl(_, expr)) = var_decl {
eval_expr(context, &expr, unit) eval_expr(context, &expr, unit)
} else { } 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, context: &mut Context,
value: f64, value: f64,
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
let mut float = float!(value); let mut float = float!(value);
float.set_prec(context.precision); float.set_prec(context.precision);
@ -307,7 +307,7 @@ fn eval_literal_expr(
context: &mut Context, context: &mut Context,
value: f64, value: f64,
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
Ok(KalkValue::Number(float!(value), float!(0), unit.cloned())) Ok(KalkValue::Number(float!(value), float!(0), unit.cloned()))
} }
@ -315,7 +315,7 @@ fn eval_group_expr(
context: &mut Context, context: &mut Context,
expr: &Expr, expr: &Expr,
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
eval_expr(context, expr, unit) eval_expr(context, expr, unit)
} }
@ -324,7 +324,7 @@ pub(crate) fn eval_fn_call_expr(
identifier: &Identifier, identifier: &Identifier,
expressions: &[Expr], expressions: &[Expr],
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
// Special functions // Special functions
match identifier.full_name.as_ref() { match identifier.full_name.as_ref() {
"sum" | "prod" => { "sum" | "prod" => {
@ -333,7 +333,7 @@ pub(crate) fn eval_fn_call_expr(
if let Expr::Var(var_identifier) = &**left { if let Expr::Var(var_identifier) = &**left {
// Make sure exactly 3 arguments were supplied. // Make sure exactly 3 arguments were supplied.
if expressions.len() != 3 { if expressions.len() != 3 {
return Err(CalcError::IncorrectAmountOfArguments( return Err(KalkError::IncorrectAmountOfArguments(
3, 3,
"sum/prod".into(), "sum/prod".into(),
expressions.len(), expressions.len(),
@ -369,10 +369,10 @@ pub(crate) fn eval_fn_call_expr(
if let Expr::Var(integration_variable) = &expressions[3] { if let Expr::Var(integration_variable) = &expressions[3] {
&integration_variable.full_name[1..] &integration_variable.full_name[1..]
} else { } else {
return Err(CalcError::ExpectedDx); return Err(KalkError::ExpectedDx);
}, },
), ),
_ => Err(CalcError::IncorrectAmountOfArguments( _ => Err(KalkError::IncorrectAmountOfArguments(
3, 3,
"integrate".into(), "integrate".into(),
expressions.len(), expressions.len(),
@ -496,7 +496,7 @@ pub(crate) fn eval_fn_call_expr(
match stmt_definition { match stmt_definition {
Some(Stmt::FnDecl(_, arguments, fn_body)) => { Some(Stmt::FnDecl(_, arguments, fn_body)) => {
if arguments.len() != expressions.len() { if arguments.len() != expressions.len() {
return Err(CalcError::IncorrectAmountOfArguments( return Err(KalkError::IncorrectAmountOfArguments(
arguments.len(), arguments.len(),
identifier.full_name.clone(), identifier.full_name.clone(),
expressions.len(), expressions.len(),
@ -549,7 +549,7 @@ pub(crate) fn eval_fn_call_expr(
fn_value 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, end_expr: &Expr,
expression: &Expr, expression: &Expr,
unit: Option<String>, unit: Option<String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
if context.sum_variables.is_none() { if context.sum_variables.is_none() {
context.sum_variables = Some(Vec::new()); context.sum_variables = Some(Vec::new());
} }
@ -611,7 +611,7 @@ fn eval_piecewise(
context: &mut Context, context: &mut Context,
pieces: &[crate::ast::ConditionalPiece], pieces: &[crate::ast::ConditionalPiece],
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
for piece in pieces { for piece in pieces {
if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? { if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? {
if condition_is_true { 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(); let mut eval_values = Vec::new();
for value in values { for value in values {
eval_values.push(eval_expr(context, value, None)?); 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)) 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(); let mut eval_rows = Vec::new();
for row in rows { for row in rows {
let mut eval_row = Vec::new(); let mut eval_row = Vec::new();
@ -651,12 +651,12 @@ fn eval_indexer(
var: &Expr, var: &Expr,
index_expressions: &[Expr], index_expressions: &[Expr],
unit: Option<&String>, unit: Option<&String>,
) -> Result<KalkValue, CalcError> { ) -> Result<KalkValue, KalkError> {
let var_value = eval_expr(context, var, unit)?; let var_value = eval_expr(context, var, unit)?;
match var_value { match var_value {
KalkValue::Vector(values) => { KalkValue::Vector(values) => {
if index_expressions.len() != 1 { if index_expressions.len() != 1 {
return Err(CalcError::IncorrectAmountOfIndexes( return Err(KalkError::IncorrectAmountOfIndexes(
index_expressions.len(), index_expressions.len(),
1, 1,
)); ));
@ -666,7 +666,7 @@ fn eval_indexer(
if let Some(value) = values.get(index - 1) { if let Some(value) = values.get(index - 1) {
Ok(value.clone()) Ok(value.clone())
} else { } else {
Err(CalcError::ItemOfIndexDoesNotExist(vec![index])) Err(KalkError::ItemOfIndexDoesNotExist(vec![index]))
} }
} }
KalkValue::Matrix(rows) => { KalkValue::Matrix(rows) => {
@ -676,18 +676,18 @@ fn eval_indexer(
return if let Some(row) = rows.get(row_index - 1) { return if let Some(row) = rows.get(row_index - 1) {
Ok(KalkValue::Vector(row.clone())) Ok(KalkValue::Vector(row.clone()))
} else { } else {
Err(CalcError::ItemOfIndexDoesNotExist(vec![row_index])) Err(KalkError::ItemOfIndexDoesNotExist(vec![row_index]))
}; };
} }
if indices.len() != 2 { if indices.len() != 2 {
return Err(CalcError::IncorrectAmountOfIndexes(indices.len(), 2)); return Err(KalkError::IncorrectAmountOfIndexes(indices.len(), 2));
} }
let row_index = indices[0]; let row_index = indices[0];
let column_index = indices[1]; let column_index = indices[1];
if row_index == 0 || column_index == 0 { if row_index == 0 || column_index == 0 {
return Err(CalcError::ItemOfIndexDoesNotExist(vec![ return Err(KalkError::ItemOfIndexDoesNotExist(vec![
row_index, row_index,
column_index, column_index,
])); ]));
@ -699,26 +699,26 @@ fn eval_indexer(
} }
} }
Err(CalcError::ItemOfIndexDoesNotExist(vec![ Err(KalkError::ItemOfIndexDoesNotExist(vec![
row_index, row_index,
column_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(); let mut indices = Vec::new();
for expr in expressions { for expr in expressions {
let value = eval_expr(context, expr, None)?; let value = eval_expr(context, expr, None)?;
if value.has_imaginary() { if value.has_imaginary() {
return Err(CalcError::CannotIndexByImaginary); return Err(KalkError::CannotIndexByImaginary);
} }
let index = value.to_f64() as usize; let index = value.to_f64() as usize;
if index == 0 { if index == 0 {
return Err(CalcError::ItemOfIndexDoesNotExist(vec![index])); return Err(KalkError::ItemOfIndexDoesNotExist(vec![index]));
} }
indices.push(index); indices.push(index);
@ -732,9 +732,9 @@ fn eval_comprehension(
left: &Expr, left: &Expr,
conditions: &[Expr], conditions: &[Expr],
vars: &[RangedVar], vars: &[RangedVar],
) -> Result<Vec<KalkValue>, CalcError> { ) -> Result<Vec<KalkValue>, KalkError> {
if vars.len() != conditions.len() { 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(); 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(); let mut symbol_table = SymbolTable::new();
symbol_table symbol_table
.insert(DEG_RAD_UNIT.clone()) .insert(DEG_RAD_UNIT.clone())
@ -815,7 +815,7 @@ mod tests {
context(&mut symbol_table, "rad").interpret(vec![stmt]) 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)? { if let Some(result) = interpret_with_unit(stmt)? {
Ok(Some(result.get_value())) Ok(Some(result.get_value()))
} else { } else {
@ -976,7 +976,7 @@ mod tests {
assert_eq!( assert_eq!(
interpret(stmt), interpret(stmt),
Err(CalcError::UndefinedVar(String::from("x"))) Err(KalkError::UndefinedVar(String::from("x")))
); );
} }
@ -1016,7 +1016,7 @@ mod tests {
assert_eq!( assert_eq!(
interpret(stmt), 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::Identifier;
use crate::ast::{Expr, Stmt}; use crate::ast::{Expr, Stmt};
use crate::lexer::TokenKind; use crate::lexer::TokenKind;
use crate::parser::CalcError; use crate::parser::KalkError;
use crate::prelude; use crate::prelude;
use crate::symbol_table::SymbolTable; use crate::symbol_table::SymbolTable;
use lazy_static::lazy_static; use lazy_static::lazy_static;
@ -44,7 +44,7 @@ impl Expr {
&self, &self,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
unknown_var: &str, unknown_var: &str,
) -> Result<Self, CalcError> { ) -> Result<Self, KalkError> {
let target_expr = Expr::Var(Identifier::from_full_name(unknown_var)); let target_expr = Expr::Var(Identifier::from_full_name(unknown_var));
let result = invert(target_expr, symbol_table, self, unknown_var); let result = invert(target_expr, symbol_table, self, unknown_var);
@ -56,7 +56,7 @@ impl Expr {
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
target_expr: Expr, target_expr: Expr,
unknown_var: &str, unknown_var: &str,
) -> Result<Self, CalcError> { ) -> Result<Self, KalkError> {
let x = invert(target_expr, symbol_table, self, unknown_var)?; let x = invert(target_expr, symbol_table, self, unknown_var)?;
Ok(x.0) Ok(x.0)
} }
@ -67,7 +67,7 @@ fn invert(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
expr: &Expr, expr: &Expr,
unknown_var: &str, unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> { ) -> Result<(Expr, Expr), KalkError> {
match expr { match expr {
Expr::Binary(left, op, right) => { Expr::Binary(left, op, right) => {
invert_binary(target_expr, symbol_table, left, op, right, unknown_var) invert_binary(target_expr, symbol_table, left, op, right, unknown_var)
@ -86,12 +86,12 @@ fn invert(
unknown_var, unknown_var,
), ),
Expr::Literal(_) => Ok((target_expr, expr.clone())), Expr::Literal(_) => Ok((target_expr, expr.clone())),
Expr::Piecewise(_) => Err(CalcError::UnableToInvert(String::from("Piecewise"))), Expr::Piecewise(_) => Err(KalkError::UnableToInvert(String::from("Piecewise"))),
Expr::Vector(_) => Err(CalcError::UnableToInvert(String::from("Vector"))), Expr::Vector(_) => Err(KalkError::UnableToInvert(String::from("Vector"))),
Expr::Matrix(_) => Err(CalcError::UnableToInvert(String::from("Matrix"))), Expr::Matrix(_) => Err(KalkError::UnableToInvert(String::from("Matrix"))),
Expr::Indexer(_, _) => Err(CalcError::UnableToInvert(String::from("Inverter"))), Expr::Indexer(_, _) => Err(KalkError::UnableToInvert(String::from("Inverter"))),
Expr::Comprehension(_, _, _) => { Expr::Comprehension(_, _, _) => {
Err(CalcError::UnableToInvert(String::from("Comprehension"))) Err(KalkError::UnableToInvert(String::from("Comprehension")))
} }
} }
} }
@ -103,7 +103,7 @@ fn invert_binary(
op: &TokenKind, op: &TokenKind,
right: &Expr, right: &Expr,
unknown_var: &str, unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> { ) -> Result<(Expr, Expr), KalkError> {
let op_inv = match op { let op_inv = match op {
TokenKind::Plus => TokenKind::Minus, TokenKind::Plus => TokenKind::Minus,
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, // 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, // 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_var(symbol_table, right, unknown_var) { 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.", "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 { match op {
TokenKind::Minus => Ok(( TokenKind::Minus => Ok((
// Make the target expression negative // Make the target expression negative
Expr::Unary(TokenKind::Minus, Box::new(target_expr)), Expr::Unary(TokenKind::Minus, Box::new(target_expr)),
expr.clone(), // And then continue inverting the inner-expression. 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, identifier: &str,
expr: &Expr, expr: &Expr,
unknown_var: &str, unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> { ) -> Result<(Expr, Expr), KalkError> {
let x = Expr::Binary( let x = Expr::Binary(
Box::new(target_expr), Box::new(target_expr),
TokenKind::ToKeyword, TokenKind::ToKeyword,
@ -264,7 +264,7 @@ fn invert_var(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
identifier: &Identifier, identifier: &Identifier,
unknown_var: &str, unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> { ) -> Result<(Expr, Expr), KalkError> {
if identifier.full_name == unknown_var { if identifier.full_name == unknown_var {
Ok((target_expr, Expr::Var(identifier.clone()))) Ok((target_expr, Expr::Var(identifier.clone())))
} else if let Some(Stmt::VarDecl(_, var_expr)) = } else if let Some(Stmt::VarDecl(_, var_expr)) =
@ -282,7 +282,7 @@ fn invert_fn_call(
identifier: &Identifier, identifier: &Identifier,
arguments: &[Expr], arguments: &[Expr],
unknown_var: &str, unknown_var: &str,
) -> Result<(Expr, Expr), CalcError> { ) -> Result<(Expr, Expr), KalkError> {
// If prelude function // If prelude function
match arguments.len() { match arguments.len() {
1 => { 1 => {
@ -310,7 +310,7 @@ fn invert_fn_call(
); );
} }
_ => { _ => {
return Err(CalcError::UnableToInvert(format!( return Err(KalkError::UnableToInvert(format!(
"Function '{}'", "Function '{}'",
identifier.full_name identifier.full_name
))); )));
@ -321,7 +321,7 @@ fn invert_fn_call(
} }
2 => { 2 => {
if prelude::BINARY_FUNCS.contains_key(identifier.full_name.as_ref() as &str) { if prelude::BINARY_FUNCS.contains_key(identifier.full_name.as_ref() as &str) {
return Err(CalcError::UnableToInvert(format!( return Err(KalkError::UnableToInvert(format!(
"Function '{}'", "Function '{}'",
identifier.full_name identifier.full_name
))); )));
@ -336,12 +336,12 @@ fn invert_fn_call(
{ {
(parameters, body) (parameters, body)
} else { } else {
return Err(CalcError::UndefinedFn(identifier.full_name.clone())); return Err(KalkError::UndefinedFn(identifier.full_name.clone()));
}; };
// Make sure the input is valid. // Make sure the input is valid.
if parameters.len() != arguments.len() { if parameters.len() != arguments.len() {
return Err(CalcError::IncorrectAmountOfArguments( return Err(KalkError::IncorrectAmountOfArguments(
parameters.len(), parameters.len(),
identifier.full_name.clone(), identifier.full_name.clone(),
arguments.len(), arguments.len(),
@ -404,7 +404,7 @@ pub fn contains_var(symbol_table: &SymbolTable, expr: &Expr, var_name: &str) ->
} }
/// Multiply an expression into a group. /// 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 { match base_expr {
Expr::Binary(left, op, right) => match op { Expr::Binary(left, op, right) => match op {
// If + or -, multiply the expression with each term. // If + or -, multiply the expression with each term.
@ -419,7 +419,7 @@ fn multiply_into(expr: &Expr, base_expr: &Expr) -> Result<Expr, CalcError> {
*op, *op,
right.clone(), right.clone(),
)), )),
_ => Err(CalcError::UnableToInvert(String::new())), _ => Err(KalkError::UnableToInvert(String::new())),
}, },
// If it's a literal, just multiply them together. // If it's a literal, just multiply them together.
Expr::Literal(_) | Expr::Var(_) => Ok(Expr::Binary( Expr::Literal(_) | Expr::Var(_) => Ok(Expr::Binary(
@ -427,10 +427,10 @@ 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::UnableToInvert(String::from( Expr::Group(_) => Err(KalkError::UnableToInvert(String::from(
"Parenthesis multiplied with parenthesis (this should be possible in the future).", "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. /// Error that occured during parsing or evaluation.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum CalcError { pub enum KalkError {
CannotIndexByImaginary, CannotIndexByImaginary,
CanOnlyIndexX, CanOnlyIndexX,
Expected(String), Expected(String),
@ -116,42 +116,42 @@ pub enum CalcError {
Unknown, Unknown,
} }
impl ToString for CalcError { impl ToString for KalkError {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
CalcError::CannotIndexByImaginary => String::from("Cannot index by imaginary numbers."), KalkError::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."), KalkError::CanOnlyIndexX => String::from("Indexing (getting an item with a specific index) is only possible on vectors and matrices."),
CalcError::Expected(description) => format!("Expected: {}", description), KalkError::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."), 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."),
CalcError::ExpectedIf => String::from("Expected 'if', with a condition after it."), KalkError::ExpectedIf => String::from("Expected 'if', with a condition after it."),
CalcError::IncorrectAmountOfArguments(expected, func, got) => format!( KalkError::IncorrectAmountOfArguments(expected, func, got) => format!(
"Expected {} arguments for function {}, but got {}.", "Expected {} arguments for function {}, but got {}.",
expected, func, got expected, func, got
), ),
CalcError::IncorrectAmountOfIndexes(expected, got) => format!( KalkError::IncorrectAmountOfIndexes(expected, got) => format!(
"Expected {} indexes but got {}.", "Expected {} indexes but got {}.",
expected, got expected, got
), ),
CalcError::ItemOfIndexDoesNotExist(indexes) => format!("Item of index ⟦{}⟧ does not exist.", indexes.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(", ")), KalkError::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."), KalkError::InconsistentColumnWidths => String::from("Inconsistent column widths. Matrix columns must be the same size."),
CalcError::InvalidComprehension(x) => format!("Invalid comprehension: {}", x), KalkError::InvalidComprehension(x) => format!("Invalid comprehension: {}", x),
CalcError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x), KalkError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
CalcError::InvalidOperator => String::from("Invalid operator."), KalkError::InvalidOperator => String::from("Invalid operator."),
CalcError::InvalidUnit => String::from("Invalid unit."), KalkError::InvalidUnit => String::from("Invalid unit."),
CalcError::TimedOut => String::from("Operation took too long."), KalkError::TimedOut => String::from("Operation took too long."),
CalcError::VariableReferencesItself => String::from("Variable references itself."), KalkError::VariableReferencesItself => String::from("Variable references itself."),
CalcError::PiecewiseConditionsAreFalse => String::from("All the conditions in the piecewise are false."), KalkError::PiecewiseConditionsAreFalse => String::from("All the conditions in the piecewise are false."),
CalcError::UnexpectedToken(got, expected) => { KalkError::UnexpectedToken(got, expected) => {
format!("Unexpected token: '{:?}', expected '{:?}'.", got, expected) format!("Unexpected token: '{:?}', expected '{:?}'.", got, expected)
} }
CalcError::UnableToInvert(msg) => format!("Unable to invert: {}", msg), KalkError::UnableToInvert(msg) => format!("Unable to invert: {}", msg),
CalcError::UndefinedFn(name) => format!("Undefined function: '{}'.", name), KalkError::UndefinedFn(name) => format!("Undefined function: '{}'.", name),
CalcError::UndefinedVar(name) => format!("Undefined variable: '{}'.", name), KalkError::UndefinedVar(name) => format!("Undefined variable: '{}'.", name),
CalcError::UnableToParseExpression => String::from("Unable to parse expression."), KalkError::UnableToParseExpression => String::from("Unable to parse expression."),
CalcError::UnableToSolveEquation => String::from("Unable to solve equation."), KalkError::UnableToSolveEquation => String::from("Unable to solve equation."),
CalcError::UnableToOverrideConstant(name) => format!("Unable to override constant: '{}'.", name), KalkError::UnableToOverrideConstant(name) => format!("Unable to override constant: '{}'.", name),
CalcError::UnrecognizedBase => String::from("Unrecognized base."), KalkError::UnrecognizedBase => String::from("Unrecognized base."),
CalcError::Unknown => String::from("Unknown error."), KalkError::Unknown => String::from("Unknown error."),
} }
} }
} }
@ -163,7 +163,7 @@ pub fn eval(
context: &mut Context, context: &mut Context,
input: &str, input: &str,
#[cfg(feature = "rug")] precision: u32, #[cfg(feature = "rug")] precision: u32,
) -> Result<Option<CalculationResult>, CalcError> { ) -> Result<Option<CalculationResult>, KalkError> {
let statements = parse(context, input)?; let statements = parse(context, input)?;
let symbol_table = context.symbol_table.get_mut(); let symbol_table = context.symbol_table.get_mut();
@ -186,7 +186,7 @@ pub fn eval(
/// Parse expressions/declarations and return a syntax tree. /// Parse expressions/declarations and return a syntax tree.
/// ///
/// `None` will be returned if the last statement is a declaration. /// `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); let mut lexer = Lexer::new(input);
context.tokens = lexer.lex(); context.tokens = lexer.lex();
context.pos = 0; context.pos = 0;
@ -211,7 +211,7 @@ pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, CalcError>
Ok(statements) 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) { if match_token(context, TokenKind::UnitKeyword) {
parse_unit_decl_stmt(context) parse_unit_decl_stmt(context)
} else { } 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); advance(context);
skip_newlines(context); skip_newlines(context);
@ -250,7 +250,7 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
reached_otherwise = true; reached_otherwise = true;
} else { } else {
return Err(CalcError::ExpectedIf); return Err(KalkError::ExpectedIf);
} }
if match_token(context, TokenKind::Semicolon) { if match_token(context, TokenKind::Semicolon) {
@ -269,7 +269,7 @@ fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
Ok(Expr::Piecewise(pieces)) 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 advance(context); // Unit keyword
let identifier = advance(context).clone(); let identifier = advance(context).clone();
consume(context, TokenKind::Equals)?; 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 { let base_unit = if let Some(base_unit) = &context.unit_decl_base_unit {
base_unit.clone() base_unit.clone()
} else { } else {
return Err(CalcError::InvalidUnit); return Err(KalkError::InvalidUnit);
}; };
// Automatically create a second unit decl with the expression inverted. // 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) Ok(stmt)
} }
fn parse_expr(context: &mut Context) -> Result<Expr, CalcError> { fn parse_expr(context: &mut Context) -> Result<Expr, KalkError> {
parse_or(context) 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)?; let left = parse_or(context)?;
if match_token(context, TokenKind::Colon) { if match_token(context, TokenKind::Colon) {
@ -319,7 +319,7 @@ fn parse_comprehension(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let left = parse_or(context)?;
if match_token(context, TokenKind::Comma) { if match_token(context, TokenKind::Comma) {
@ -332,7 +332,7 @@ fn parse_comprehension_comma(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let left = parse_and(context)?;
if match_token(context, TokenKind::Or) { if match_token(context, TokenKind::Or) {
@ -345,7 +345,7 @@ fn parse_or(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let left = parse_comparison(context)?;
if match_token(context, TokenKind::And) { if match_token(context, TokenKind::And) {
@ -358,7 +358,7 @@ fn parse_and(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let mut left = parse_to(context)?;
// Equality check // Equality check
@ -460,7 +460,7 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let left = parse_term(context)?;
if match_token(context, TokenKind::ToKeyword) { if match_token(context, TokenKind::ToKeyword) {
@ -477,7 +477,7 @@ fn parse_to(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let mut left = parse_factor(context)?;
while match_token(context, TokenKind::Plus) || match_token(context, TokenKind::Minus) { 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) 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)?; let mut left = parse_unit(context)?;
if let Expr::Unary(TokenKind::Percent, percent_left) = left.clone() { 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) 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)?; let expr = parse_exponent(context)?;
if match_token(context, TokenKind::Identifier) { if match_token(context, TokenKind::Identifier) {
@ -547,7 +547,7 @@ fn parse_unit(context: &mut Context) -> Result<Expr, CalcError> {
Ok(expr) 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)?; let left = parse_unary(context)?;
if match_token(context, TokenKind::Power) { if match_token(context, TokenKind::Power) {
@ -559,7 +559,7 @@ fn parse_exponent(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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) { if match_token(context, TokenKind::Minus) {
let op = advance(context).kind; let op = advance(context).kind;
let expr = Box::new(parse_unary(context)?); 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)?; let left = parse_factorial(context)?;
if match_token(context, TokenKind::OpenDoubleBracket) { if match_token(context, TokenKind::OpenDoubleBracket) {
@ -593,7 +593,7 @@ fn parse_indexer(context: &mut Context) -> Result<Expr, CalcError> {
Ok(left) 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)?; let expr = parse_primary(context)?;
Ok(if match_token(context, TokenKind::Exclamation) { 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 { let expr = match peek(context).kind {
TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?, TokenKind::OpenParenthesis | TokenKind::OpenBracket => parse_vector(context)?,
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?, TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
TokenKind::Identifier => parse_identifier(context)?, TokenKind::Identifier => parse_identifier(context)?,
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?), TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
_ => return Err(CalcError::UnableToParseExpression), _ => return Err(KalkError::UnableToParseExpression),
}; };
Ok(expr) 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 { let name = match &peek(context).kind {
TokenKind::Pipe => "abs", TokenKind::Pipe => "abs",
TokenKind::OpenCeil => "ceil", 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; let kind = advance(context).kind;
if kind == TokenKind::OpenBracket { if kind == TokenKind::OpenBracket {
@ -660,7 +660,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
{ {
if let Some(columns) = column_count { if let Some(columns) = column_count {
if columns != items_in_row { if columns != items_in_row {
return Err(CalcError::InconsistentColumnWidths); return Err(KalkError::InconsistentColumnWidths);
} }
} else { } else {
column_count = Some(items_in_row); 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 { if peek(context).kind == TokenKind::Eof {
return Err(CalcError::Expected(String::from( return Err(KalkError::Expected(String::from(
"Closing group symbol, eg. )", "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 identifier = Identifier::from_full_name(&advance(context).value);
let mut log_base = None; let mut log_base = None;
@ -775,12 +775,12 @@ fn advance(context: &mut Context) -> &Token {
previous(context) 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) { if match_token(context, kind) {
return Ok(advance(context)); 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 { 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)?; let base = get_base(value)?;
if let Some(result) = crate::radix::parse_float_radix(&value.replace(" ", ""), base) { if let Some(result) = crate::radix::parse_float_radix(&value.replace(" ", ""), base) {
Ok(result) Ok(result)
} else { } 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('_') { let underscore_pos = if let Some(i) = value.find('_') {
i i
} else { } else {
@ -813,7 +813,7 @@ fn get_base(value: &str) -> Result<u8, CalcError> {
if let Some(base) = crate::text_utils::parse_subscript(subscript) { if let Some(base) = crate::text_utils::parse_subscript(subscript) {
Ok(base) Ok(base)
} else { } else {
Err(CalcError::UnrecognizedBase) Err(KalkError::UnrecognizedBase)
} }
} }
@ -825,7 +825,7 @@ mod tests {
use crate::test_helpers::*; use crate::test_helpers::*;
use wasm_bindgen_test::*; 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.tokens = tokens;
context.pos = 0; context.pos = 0;
@ -834,7 +834,7 @@ mod tests {
analysis::analyse_stmt(symbol_table, parsed) 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(); let mut context = Context::new();
context.tokens = tokens; context.tokens = tokens;
context.pos = 0; context.pos = 0;