refactor: replace duplicate eval code with macro

This commit is contained in:
electria 2026-10-20 17:42:50 -07:00
commit 570da21956
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs

View file

@ -89,9 +89,11 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
end -= 1; end -= 1;
} }
macro_rules! collapse_operator {
($operator:expr) => {
while let Some(operator) = nodes[start..end] while let Some(operator) = nodes[start..end]
.iter() .iter()
.position(|n| *n == Node::Operator(Operator::Exp)) .position(|n| *n == Node::Operator($operator))
{ {
let lhs = match nodes.remove(start + operator - 1) { let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n, Node::Number(n) => n,
@ -101,93 +103,21 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
match nodes.get_mut(start + operator) { match nodes.get_mut(start + operator) {
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)), None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
Some(Node::Number(n)) => n.pow_from(lhs), Some(Node::Number(n)) => $operator.for_float()(n, lhs),
Some(n) => return Err(Error::InvalidOperand(n.clone())), Some(n) => return Err(Error::InvalidOperand(n.clone())),
}; };
nodes.remove(start + operator - 1); nodes.remove(start + operator - 1);
end -= 1; end -= 1;
} }
while let Some(operator) = nodes[start..end]
.iter()
.position(|n| *n == Node::Operator(Operator::Div))
{
let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n,
n => return Err(Error::InvalidOperand(n)),
}; };
end -= 1;
match nodes.get_mut(start + operator) {
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
Some(Node::Number(n)) => n.div_from(lhs),
Some(n) => return Err(Error::InvalidOperand(n.clone())),
};
nodes.remove(start + operator - 1);
end -= 1;
} }
while let Some(operator) = nodes[start..end] collapse_operator!(Operator::Exp);
.iter() collapse_operator!(Operator::Div);
.position(|n| *n == Node::Operator(Operator::Mult)) collapse_operator!(Operator::Mult);
{ collapse_operator!(Operator::Minus);
let lhs = match nodes.remove(start + operator - 1) { collapse_operator!(Operator::Plus);
Node::Number(n) => n,
n => return Err(Error::InvalidOperand(n)),
};
end -= 1;
match nodes.get_mut(start + operator) {
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
Some(Node::Number(n)) => n.mul_from(lhs),
Some(n) => return Err(Error::InvalidOperand(n.clone())),
};
nodes.remove(start + operator - 1);
end -= 1;
}
while let Some(operator) = nodes[start..end]
.iter()
.position(|n| *n == Node::Operator(Operator::Minus))
{
let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n,
n => return Err(Error::InvalidOperand(n)),
};
end -= 1;
match nodes.get_mut(start + operator) {
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
Some(Node::Number(n)) => n.sub_from(lhs),
Some(n) => return Err(Error::InvalidOperand(n.clone())),
};
nodes.remove(start + operator - 1);
end -= 1;
}
while let Some(operator) = nodes[start..end]
.iter()
.position(|n| *n == Node::Operator(Operator::Plus))
{
let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n,
n => return Err(Error::InvalidOperand(n)),
};
end -= 1;
match nodes.get_mut(start + operator) {
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
Some(Node::Number(n)) => n.add_from(lhs),
Some(n) => return Err(Error::InvalidOperand(n.clone())),
};
nodes.remove(start + operator - 1);
end -= 1;
}
if nodes.len() > 1 { if nodes.len() > 1 {
nodes.remove(end); nodes.remove(end);
@ -200,18 +130,29 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
impl Function { impl Function {
fn for_float(&self) -> impl FnMut(&mut Float) { fn for_float(&self) -> impl FnMut(&mut Float) {
match self { match self {
Function::Sqrt => Float::sqrt_mut, Self::Sqrt => Float::sqrt_mut,
Function::Ln => Float::ln_mut, Self::Ln => Float::ln_mut,
Function::Sine => Float::sin_mut, Self::Sine => Float::sin_mut,
Function::ArcSine => Float::asin_mut, Self::ArcSine => Float::asin_mut,
Function::Cosine => Float::cos_mut, Self::Cosine => Float::cos_mut,
Function::ArcCosine => Float::acos_mut, Self::ArcCosine => Float::acos_mut,
Function::Tangent => Float::tan_mut, Self::Tangent => Float::tan_mut,
Function::ArcTangent => Float::atan_mut, Self::ArcTangent => Float::atan_mut,
Function::Secant => Float::sec_mut, Self::Secant => Float::sec_mut,
Function::CoSecant => Float::csc_mut, Self::CoSecant => Float::csc_mut,
}
}
}
impl Operator {
fn for_float(&self) -> impl FnMut(&mut Float, Float) {
match self {
Self::Plus => Float::add_from,
Self::Minus => Float::sub_from,
Self::Mult => Float::mul_from,
Self::Div => Float::div_from,
Self::Exp => Float::pow_from,
} }
} }
} }