From 23d49fbb6ad542050ab7ea10448818127e65af51 Mon Sep 17 00:00:00 2001 From: electria Date: Mon, 13 Jul 2026 19:37:29 -0700 Subject: [PATCH] refactor: modify numbers inplace this should improve performance I also happened to fix the lack of detail in the explicit panics --- src/parse.rs | 87 ++++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 13a656e..62ad56e 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use rug::{ Float, float::ParseFloatError, - ops::{CompleteRound, Pow}, + ops::{AddFrom, CompleteRound, DivFrom, MulFrom, PowFrom, SubFrom}, }; #[derive(Clone, Debug, thiserror::Error)] @@ -190,105 +190,90 @@ fn collapse_toplevel(nodes: &mut Vec, mut end: usize) { .iter() .position(|n| *n == Node::Operator(Operator::Exp)) { - let lhs = match &nodes[start..end][operator - 1] { + let lhs = match nodes.remove(start + operator - 1) { Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + n => panic!("operator has an invalid operand: {n:?}"), }; - let rhs = match &nodes[start..end][operator + 1] { - Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + end -= 1; + match &mut nodes[start..end][operator] { + Node::Number(n) => n.pow_from(lhs), + n => panic!("operator has an invalid operand: {n:?}"), }; - let number = lhs.pow(rhs).complete(PREC); - nodes.remove(start + operator - 1); - nodes.remove(start + operator - 1); - end -= 2; - nodes[start + operator - 1] = Node::Number(number); + end -= 1; } while let Some(operator) = nodes[start..end] .iter() .position(|n| *n == Node::Operator(Operator::Div)) { - let lhs = match &nodes[start..end][operator - 1] { + let lhs = match nodes.remove(start + operator - 1) { Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + n => panic!("operator has an invalid operand: {n:?}"), }; - let rhs = match &nodes[start..end][operator + 1] { - Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + end -= 1; + match &mut nodes[start..end][operator] { + Node::Number(n) => n.div_from(lhs), + n => panic!("operator has an invalid operand: {n:?}"), }; - let number = (lhs / rhs).complete(PREC); - nodes.remove(start + operator - 1); - nodes.remove(start + operator - 1); - end -= 2; - nodes[start + operator - 1] = Node::Number(number); + end -= 1; } while let Some(operator) = nodes[start..end] .iter() .position(|n| *n == Node::Operator(Operator::Mult)) { - let lhs = match &nodes[start..end][operator - 1] { + let lhs = match nodes.remove(start + operator - 1) { Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + n => panic!("operator has an invalid operand: {n:?}"), }; - let rhs = match &nodes[start..end][operator + 1] { - Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + end -= 1; + match &mut nodes[start..end][operator] { + Node::Number(n) => n.mul_from(lhs), + n => panic!("operator has an invalid operand: {n:?}"), }; - let number = (lhs * rhs).complete(PREC); - nodes.remove(start + operator - 1); - nodes.remove(start + operator - 1); - end -= 2; - nodes[start + operator - 1] = Node::Number(number); + end -= 1; } while let Some(operator) = nodes[start..end] .iter() .position(|n| *n == Node::Operator(Operator::Plus)) { - let lhs = match &nodes[start..end][operator - 1] { + let lhs = match nodes.remove(start + operator - 1) { Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + n => panic!("operator has an invalid operand: {n:?}"), }; - let rhs = match &nodes[start..end][operator + 1] { - Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + end -= 1; + match &mut nodes[start..end][operator] { + Node::Number(n) => n.add_from(lhs), + n => panic!("operator has an invalid operand: {n:?}"), }; - let number = (lhs + rhs).complete(PREC); - nodes.remove(start + operator - 1); - nodes.remove(start + operator - 1); - end -= 2; - nodes[start + operator - 1] = Node::Number(number); + end -= 1; } while let Some(operator) = nodes[start..end] .iter() .position(|n| *n == Node::Operator(Operator::Minus)) { - let lhs = match &nodes[start..end][operator - 1] { + let lhs = match nodes.remove(start + operator - 1) { Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + n => panic!("operator has an invalid operand: {n:?}"), }; - let rhs = match &nodes[start..end][operator + 1] { - Node::Number(n) => n, - _ => panic!("operator is missing an operand"), + end -= 1; + match &mut nodes[start..end][operator] { + Node::Number(n) => n.sub_from(lhs), + n => panic!("operator has an invalid operand: {n:?}"), }; - let number = (lhs - rhs).complete(PREC); - nodes.remove(start + operator - 1); - nodes.remove(start + operator - 1); - end -= 2; - nodes[start + operator - 1] = Node::Number(number); + end -= 1; } if nodes.len() > 1 {