Checkpoint 2 (seems to compile now)

This commit is contained in:
Book-reader 2025-09-06 15:36:22 +12:00
parent cd493f8d32
commit 86c6c96909

View file

@ -20,11 +20,11 @@ pub struct Calculation {
pub fn calculate(query: &str) -> Option<Calculation> { pub fn calculate(query: &str) -> Option<Calculation> {
debug!("Got query {}", query); debug!("Got query {}", query);
let mut parser = Parser::new(Lexer::new(query)); let mut parser = Parser::new(Lexer::new(query));
let tree = parser.parse()?; let mut tree = parser.parse()?;
let res = tree.eval(); let res = tree.eval();
debug!("Calculation: {}", query); debug!("Calculation: {}", query);
debug!("Tree: {:?}", tree); // debug!("Tree: {:?}", tree);
debug!("Result: {}", res); debug!("Result: {}", res);
Some(Calculation {equation: query.to_string(), result: res.to_string()}) Some(Calculation {equation: query.to_string(), result: res.to_string()})
} }
@ -38,7 +38,7 @@ enum Token {
Func(Func),*/ Func(Func),*/
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum Op { enum Op {
Add, Add,
Subtract, Subtract,
@ -74,7 +74,7 @@ impl Op {
} }
} }
fn apply_to(&self, args: &Vec<Expr>) -> BigFloat { fn apply_to(&self, args: &mut Vec<Expr>) -> BigFloat {
match args.len() { match args.len() {
1 => match self { 1 => match self {
Op::Subtract => { Op::Subtract => {
@ -113,12 +113,12 @@ impl Op {
2 => match self { 2 => match self {
Op::LParen => args[0].eval(), Op::LParen => args[0].eval(),
Op::RParen => args[0].eval(), Op::RParen => args[0].eval(),
Op::Add => args[0].eval().add(&args[1].eval(), PRECISION, RoundingMode::None), Op::Add => args[0].eval().add(&mut args[1].eval(), PRECISION, RoundingMode::None),
Op::Subtract => args[0].eval().sub(&args[1].eval(), PRECISION, RoundingMode::None), Op::Subtract => args[0].eval().sub(&mut args[1].eval(), PRECISION, RoundingMode::None),
Op::Multiply => args[0].eval().mul(&args[1].eval(), PRECISION, RoundingMode::None), Op::Multiply => args[0].eval().mul(&mut args[1].eval(), PRECISION, RoundingMode::None),
Op::Divide => args[0].eval().div(&args[1].eval(), PRECISION, RoundingMode::None), Op::Divide => args[0].eval().div(&mut args[1].eval(), PRECISION, RoundingMode::None),
Op::Exponent => args[0].eval().pow(&args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()), Op::Exponent => args[0].eval().pow(&mut args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
Op::Func(Func::Log) => args[0].eval().log(&args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()), Op::Func(Func::Log) => args[0].eval().log(&mut args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
_ => { _ => {
error!("Got 2 params for {:?} which only expects 1 (should not be possible)", self); error!("Got 2 params for {:?} which only expects 1 (should not be possible)", self);
astro_float::NAN astro_float::NAN
@ -134,11 +134,11 @@ impl Op {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
enum Atom { enum Atom {
Number(BigFloat), // TODO: use the high precision floats library instead Number(BigFloat),
Const(Const), Const(Const),
} }
impl Atom { /*impl Atom {
fn get_val(&self) -> BigFloat { fn get_val(&self) -> BigFloat {
match self { match self {
Atom::Number(val) => *val, Atom::Number(val) => *val,
@ -150,9 +150,20 @@ impl Atom {
} }
} }
} }
}*/
impl Const {
fn get_val(&self) -> BigFloat {
match self {
Const::Pi => CONST_CACHE.lock().unwrap().pi(PRECISION, RoundingMode::None),
Const::E => CONST_CACHE.lock().unwrap().e(PRECISION, RoundingMode::None),
Const::Inf => astro_float::INF_POS,
Const::Nan => astro_float::NAN,
}
}
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum Func { enum Func {
Sine, Sine,
Cosine, Cosine,
@ -190,7 +201,7 @@ impl Func {
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum Const { enum Const {
Pi, Pi,
E, E,
@ -211,7 +222,7 @@ impl Const {
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum ParseErr { enum ParseErr {
Eof, Eof,
Invalid, Invalid,
@ -295,13 +306,14 @@ impl Lexer<'_> {
} }
fn next(&mut self) -> Result<Token, ParseErr> { fn next(&mut self) -> Result<Token, ParseErr> {
let val = mem::replace(&mut self.next_tok, self._next()); let res = self._next();
let val = mem::replace(&mut self.next_tok, res);
// self.next_tok = self._next(); // self.next_tok = self._next();
val val
} }
fn peek(&mut self) -> Result<Token, ParseErr> { fn peek(&mut self) -> &Result<Token, ParseErr> {
self.next_tok &self.next_tok
} }
// TODO: replace with iterator so I can do parser.parse(lexer.iter()) and parse does lex_iter.next() & such // TODO: replace with iterator so I can do parser.parse(lexer.iter()) and parse does lex_iter.next() & such
@ -373,14 +385,14 @@ impl Parser<'_> {
debug!("loop start"); debug!("loop start");
let op: Op = match self.lex.peek() { let op: Op = match self.lex.peek() {
Err(ParseErr::Eof) => break, Err(ParseErr::Eof) => break,
Err(e) => { debug!("In expr got err {:?}", e); Err(e) }, Err(e) => { debug!("In expr got err {:?}", e); Err(*e) },
Ok(tok) => match tok { Ok(tok) => match tok {
Token::Op(op) => match op { Token::Op(op) => match op {
Op::RParen => { Op::RParen => {
debug!("got RParen"); debug!("got RParen");
break; break;
}, },
_ => Ok(op), _ => Ok(*op),
} }
v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) }, v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
} }
@ -403,15 +415,31 @@ impl Parser<'_> {
#[derive(Debug)] #[derive(Debug)]
enum Expr { enum Expr {
Evaluated,
Atom(Atom), Atom(Atom),
Node(Op, Vec<Expr>), Node(Op, Vec<Expr>),
} }
impl Expr { impl Expr {
fn eval(&self) -> BigFloat { fn eval(&mut self) -> BigFloat {
let res = match (self) { let res = match self {
Expr::Atom(at) => at.get_val(), Expr::Atom(_) => {
Expr::Node(op, exprs) => op.apply_to(exprs), let v = mem::replace(self, Expr::Evaluated);
if let Expr::Atom(at) = v {
match at {
Atom::Number(n) => n,
Atom::Const(c) => c.get_val(),
}
} else {
unreachable!();
}
// at.get_val()
}
Expr::Node(op, exprs) => {
*self = Expr::Atom(Atom::Number(op.apply_to(exprs)));
self.eval()
}
Expr::Evaluated => unreachable!("Tried to evaluate an already evaluated node"),
}; };
// debug!("{:?} evaluated to {}", self, res); // debug!("{:?} evaluated to {}", self, res);
res res