use crate::scripting::nodes::{node::Node, traits::NodeVisitor};
pub struct IfConditionTransform;
impl IfConditionTransform {
pub fn new() -> Self {
Self
}
fn transform_cond(&self, node: &mut Node) {
match node {
Node::Superior(data) => {
for c in data.children.iter_mut() {
self.transform_cond(c);
}
let left = data.children[0].clone();
let right = data.children[1].clone();
data.children.clear();
data.children
.push(Node::new_subtract_with_values(left, right));
data.children.push(Node::new_constant(0.0));
}
Node::SuperiorOrEqual(data) => {
for c in data.children.iter_mut() {
self.transform_cond(c);
}
let left = data.children[0].clone();
let right = data.children[1].clone();
data.children.clear();
data.children
.push(Node::new_subtract_with_values(left, right));
data.children.push(Node::new_constant(0.0));
}
Node::Inferior(data) => {
for c in data.children.iter_mut() {
self.transform_cond(c);
}
let left = data.children[1].clone();
let right = data.children[0].clone();
*node = Node::new_superior_with_values(
Node::new_subtract_with_values(left, right),
Node::new_constant(0.0),
);
}
Node::InferiorOrEqual(data) => {
for c in data.children.iter_mut() {
self.transform_cond(c);
}
let left = data.children[1].clone();
let right = data.children[0].clone();
*node = Node::new_superior_or_equal_with_values(
Node::new_subtract_with_values(left, right),
Node::new_constant(0.0),
);
}
Node::Equal(data) => {
for c in data.children.iter_mut() {
self.transform_cond(c);
}
let left = data.children[0].clone();
let right = data.children[1].clone();
data.children.clear();
data.children
.push(Node::new_subtract_with_values(left, right));
data.children.push(Node::new_constant(0.0));
}
Node::NotEqual(data) => {
for c in &mut data.children {
self.transform_cond(c);
}
let left = data.children[0].clone();
let right = data.children[1].clone();
*node = Node::new_not_with_value(Node::new_equal_with_values(
Node::new_subtract_with_values(left, right),
Node::new_constant(0.0),
));
}
Node::And(data) | Node::Or(data) | Node::Not(data) => {
for c in data.children.iter_mut() {
self.transform_cond(c);
}
}
Node::Constant(_)
| Node::True
| Node::False
| Node::String(_)
| Node::Spot(_)
| Node::Df(_)
| Node::RateIndex(_) => {}
_ => {
for c in node.children_mut().iter_mut() {
self.transform_cond(c);
}
}
}
}
}
impl Default for IfConditionTransform {
fn default() -> Self {
Self::new()
}
}
impl NodeVisitor for IfConditionTransform {
type Output = ();
fn visit(&self, node: &mut Node) {
match node {
Node::If(data) => {
if let Some(cond) = data.children.get_mut(0) {
self.transform_cond(cond);
}
for c in data.children.iter_mut().skip(1) {
self.visit(c);
}
}
Node::Constant(_)
| Node::True
| Node::False
| Node::String(_)
| Node::Spot(_)
| Node::Df(_)
| Node::RateIndex(_) => {}
_ => {
for c in node.children_mut().iter_mut() {
self.visit(c);
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::scripting::parsing::{lexer::Lexer, parser::Parser};
#[test]
fn test_transform_inferior() {
let script = "if a < 1 { b = 2; }".to_string();
let tokens = Lexer::new(script).tokenize().unwrap();
let mut expr = Parser::new(tokens).parse().unwrap();
let transformer = IfConditionTransform::new();
transformer.visit(&mut expr);
let cond = match &expr {
Node::Base(b) => match &b.children[0] {
Node::If(data) => &data.children[0],
_ => panic!("expected if"),
},
_ => panic!("expected base"),
};
let expected = Node::new_superior_with_values(
Node::new_subtract_with_values(
Node::new_constant(1.0),
Node::new_variable("a".to_string()),
),
Node::new_constant(0.0),
);
assert_eq!(*cond, expected);
}
}