refacto(*): manage errors without panics

This commit is contained in:
gbrochar 2023-08-11 16:36:17 +02:00
parent c4f2288861
commit 258a4189c0
3 changed files with 29 additions and 19 deletions

View File

@ -3,13 +3,20 @@ use std::process;
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("Error: You need to run this program with exactly 1 argument");
process::exit(1);
}
let equation = computorv1::parse(&args[1]).unwrap_or_else(|e| { let equation = computorv1::parse(&args[1]).unwrap_or_else(|e| {
println!("Error during parsing: {e}"); println!("Error during parsing: {e}");
process::exit(1); process::exit(1);
}); });
println!("{:?}", equation); println!("{:?}", equation);
let is_equation = computorv1::maths::evaluator::is_equation(&equation); let is_equation = computorv1::maths::evaluator::is_equation(&equation);
let evaluated = computorv1::maths::evaluator::evaluate(equation); let evaluated = computorv1::maths::evaluator::evaluate(equation).unwrap_or_else(|e| {
println!("Error during evaluation: {e}");
process::exit(1);
});
computorv1::pretty(&evaluated); computorv1::pretty(&evaluated);
if is_equation { if is_equation {
computorv1::maths::solver::solve(evaluated); computorv1::maths::solver::solve(evaluated);

View File

@ -69,15 +69,15 @@ fn mul(lhs: Vec<GaussianRational>, rhs: &Vec<GaussianRational>) -> Vec<GaussianR
res res
} }
fn exp(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> { fn exp(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Result<Vec<GaussianRational>, String> {
if rhs.len() != 1 { if rhs.len() != 1 {
panic!("Eh t'y es fou mon gate puissance d'inconnu !"); return Err(format!("exponential only supports natural exponents, unknown exponents aren't supported"));
} }
if rhs[0].imaginary.numerator != 0 { if rhs[0].imaginary.numerator != 0 {
panic!("Diablerie une puissance complexe !"); return Err(format!("exponential only supports natural exponents, complex exponents aren't supported"));
} }
if rhs[0].real.denominator != 1 { if rhs[0].real.denominator != 1 {
panic!("MON DIEU UNE PUISSANCE DE RATIONNEL"); return Err(format!("exponential only supports natural exponents, rational exponents aren't supported"));
} }
let mut res = Vec::new(); let mut res = Vec::new();
let pow = rhs[0].real.numerator; let pow = rhs[0].real.numerator;
@ -85,7 +85,7 @@ fn exp(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRa
for _ in 0..pow { for _ in 0..pow {
res = mul(res, &lhs); res = mul(res, &lhs);
} }
res Ok(res)
} }
fn check_div(lhs: &Vec<GaussianRational>, rhs: &Vec<GaussianRational>) -> bool { fn check_div(lhs: &Vec<GaussianRational>, rhs: &Vec<GaussianRational>) -> bool {
@ -97,12 +97,12 @@ fn check_div(lhs: &Vec<GaussianRational>, rhs: &Vec<GaussianRational>) -> bool {
true true
} }
fn div(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> { fn div(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Result<Vec<GaussianRational>, String> {
if rhs.len() > lhs.len() { if rhs.len() > lhs.len() {
panic!("faut pas diviser par plus grande puissance d'inconnu que sois meme :$"); return Err(format!("division supported if the divisor to be of same or smaller degree than the dividend."));
} }
if !check_div(&lhs, &rhs) { if !check_div(&lhs, &rhs) {
panic!("Moi je sais pas faire heing"); return Err(format!("division supported if the divisor has only one non zero coefficient"));
} }
let denominator = *rhs.last().unwrap(); let denominator = *rhs.last().unwrap();
@ -117,17 +117,18 @@ fn div(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRa
res[res_i] = lhs[i] / denominator; res[res_i] = lhs[i] / denominator;
} }
res Ok(res)
} }
fn calculate(operator: Token, lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> { fn calculate(operator: Token, lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Result<Vec<GaussianRational>, String> {
match operator { match operator {
Token::Addition() => add(lhs, rhs), Token::Addition() => Ok(add(lhs, rhs)),
Token::Substraction() => sub(lhs, rhs), Token::Substraction() => Ok(sub(lhs, rhs)),
Token::Multiplication() => mul(lhs, &rhs), Token::Multiplication() => Ok(mul(lhs, &rhs)),
Token::Division() => div(lhs, rhs), Token::Division() => div(lhs, rhs),
Token::Exponentiation() => exp(lhs, rhs), Token::Exponentiation() => exp(lhs, rhs),
Token::Equal() => sub(lhs, rhs), Token::Equal() => Ok(sub(lhs, rhs)),
Token::Modulo() => Err(format!("modulo isn't suported yet by this program.")),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -140,11 +141,11 @@ fn calculate_unary(operator: Token, operand: Vec<GaussianRational>) -> Vec<Gauss
} }
} }
pub fn evaluate(ast: Node) -> Vec<GaussianRational> { pub fn evaluate(ast: Node) -> Result<Vec<GaussianRational>, String> {
match ast { match ast {
Node::Binary { operator, lhs, rhs } => calculate(operator, evaluate(*lhs), evaluate(*rhs)), Node::Binary { operator, lhs, rhs } => calculate(operator, evaluate(*lhs)?, evaluate(*rhs)?),
Node::Unary { operator, operand } => calculate_unary(operator, evaluate(*operand)), Node::Unary { operator, operand } => Ok(calculate_unary(operator, evaluate(*operand)?)),
Node::Leaf(value) => value, Node::Leaf(value) => Ok(value),
} }
} }

View File

@ -35,6 +35,8 @@ pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> {
for i in (1..equation.len()).rev() { for i in (1..equation.len()).rev() {
if equation[i] == zero() { if equation[i] == zero() {
equation.pop(); equation.pop();
} else {
break;
} }
} }
crate::pretty(&equation); crate::pretty(&equation);