Compare commits

..
2 changed files with 98 additions and 74 deletions

View file

@ -28,8 +28,8 @@ impl Nodes {
let len = nodes.len(); let len = nodes.len();
collapse_toplevel(nodes, len)?; collapse_toplevel(nodes, len)?;
match nodes.pop().unwrap() { match nodes.pop() {
Node::Number(n) => Ok(n), Some(Node::Number(n)) => Ok(n),
_ => Err(Error::CollapseFailed(self)), _ => Err(Error::CollapseFailed(self)),
} }
} }
@ -41,7 +41,7 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
.rposition(|n| *n == Node::ParenthesisStart) .rposition(|n| *n == Node::ParenthesisStart)
.unwrap_or(0); .unwrap_or(0);
while let Some((index, variant)) = nodes[start..end] while let Some((index, function)) = nodes[start..end]
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(i, n)| match n { .filter_map(|(i, n)| match n {
@ -58,20 +58,7 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
return Err(Error::MissingArgument(node.clone())); return Err(Error::MissingArgument(node.clone()));
}; };
match variant { function.for_float()(n);
Function::Sqrt => n.sqrt_mut(),
Function::Ln => n.ln_mut(),
Function::Sine => n.sin_mut(),
Function::ArcSine => n.asin_mut(),
Function::Cosine => n.cos_mut(),
Function::ArcCosine => n.acos_mut(),
Function::Tangent => n.tan_mut(),
Function::ArcTangent => n.atan_mut(),
Function::Secant => n.sec_mut(),
Function::CoSecant => n.csc_mut(),
};
nodes.remove(start + index); nodes.remove(start + index);
end -= 1; end -= 1;
@ -185,23 +172,54 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
Ok(()) Ok(())
} }
#[cfg(test)] impl Function {
use super::PREC; fn for_float(&self) -> impl FnMut(&mut Float) {
match self {
Function::Sqrt => Float::sqrt_mut,
#[test] Function::Ln => Float::ln_mut,
fn test() {
assert_eq!( Function::Sine => Float::sin_mut,
Nodes(vec![ Function::ArcSine => Float::asin_mut,
Node::Function(Function::Sine), Function::Cosine => Float::cos_mut,
Node::ParenthesisStart, Function::ArcCosine => Float::acos_mut,
Node::Number(Float::with_val(PREC, 2)), Function::Tangent => Float::tan_mut,
Node::ParenthesisEnd, Function::ArcTangent => Float::atan_mut,
Node::Operator(Operator::Plus), Function::Secant => Float::sec_mut,
Node::Number(Float::with_val(PREC, 1)) Function::CoSecant => Float::csc_mut,
]) }
.evaluate() }
.unwrap() }
.to_f64(),
1.9092974268256817, #[cfg(test)]
); mod tests {
use super::super::PREC;
use super::*;
use std::assert_matches;
#[test]
fn basic() {
assert_eq!(
Nodes(vec![
Node::Function(Function::Sine),
Node::ParenthesisStart,
Node::Number(Float::with_val(PREC, 2)),
Node::ParenthesisEnd,
Node::Operator(Operator::Plus),
Node::Number(Float::with_val(PREC, 1))
])
.evaluate()
.unwrap()
.to_f64(),
1.9092974268256817,
);
}
#[test]
fn zerosized() {
assert_matches!(
Nodes(vec![Node::ParenthesisStart, Node::ParenthesisEnd]).evaluate(),
Err(Error::CollapseFailed(Nodes(v))) if v.is_empty()
)
}
} }

View file

@ -195,43 +195,49 @@ impl FromStr for Nodes {
} }
} }
#[test] #[cfg(test)]
fn test() { mod tests {
assert_eq!( use super::*;
Nodes::from_str("sin(2) + 1").unwrap().as_ref(),
&[ #[test]
Node::Function(Function::Sine), fn basic() {
Node::ParenthesisStart, assert_eq!(
Node::from(2), Nodes::from_str("sin(2) + 1").unwrap().as_ref(),
Node::ParenthesisEnd, &[
Node::Operator(Operator::Plus), Node::Function(Function::Sine),
Node::from(1), Node::ParenthesisStart,
], Node::from(2),
) Node::ParenthesisEnd,
} Node::Operator(Operator::Plus),
#[test] Node::from(1),
fn test_e() { ],
assert_eq!( )
Nodes::from_str("5e * 5").unwrap().as_ref(), }
&[
Node::from(5), #[test]
Node::Operator(Operator::Mult), fn e_constant() {
Node::from(f64::consts::E), assert_eq!(
Node::Operator(Operator::Mult), Nodes::from_str("5e * 5").unwrap().as_ref(),
Node::from(5), &[
], Node::from(5),
) Node::Operator(Operator::Mult),
} Node::from(f64::consts::E),
#[test] Node::Operator(Operator::Mult),
fn test_unary_op() { Node::from(5),
assert_eq!( ],
Nodes::from_str("5(-5)").unwrap().as_ref(), )
&[ }
Node::from(5), #[test]
Node::Operator(Operator::Mult), fn unary_op() {
Node::ParenthesisStart, assert_eq!(
Node::from(-5), Nodes::from_str("5(-5)").unwrap().as_ref(),
Node::ParenthesisEnd, &[
], Node::from(5),
) Node::Operator(Operator::Mult),
Node::ParenthesisStart,
Node::from(-5),
Node::ParenthesisEnd,
],
)
}
} }