use crate::ast::{ExprKind, Expression};
use std::collections::HashSet;
use super::walker::for_each_child;
pub(super) fn cv_core(expr: &Expression, vars: &mut HashSet<String>) {
match &expr.kind {
ExprKind::Variable(name) => {
vars.insert(name.clone());
}
ExprKind::Derivative { var, .. }
| ExprKind::PartialDerivative { var, .. }
| ExprKind::Integral { var, .. }
| ExprKind::ClosedIntegral { var, .. } => {
vars.insert(var.clone());
}
ExprKind::MultipleIntegral { vars: ivars, .. } => {
for v in ivars {
vars.insert(v.clone());
}
}
ExprKind::Limit { var, .. } => {
vars.insert(var.clone());
}
ExprKind::Sum { index, .. } | ExprKind::Product { index, .. } => {
vars.insert(index.clone());
}
ExprKind::ForAll { variable, .. } | ExprKind::Exists { variable, .. } => {
vars.insert(variable.clone());
}
ExprKind::SetBuilder { variable, .. } => {
vars.insert(variable.clone());
}
ExprKind::Tensor { indices, .. }
| ExprKind::KroneckerDelta { indices }
| ExprKind::LeviCivita { indices } => {
for idx in indices {
vars.insert(idx.name.clone());
}
}
ExprKind::Differential { var } => {
vars.insert(var.clone());
}
_ => {}
}
for_each_child(expr, |child| cv_core(child, vars));
}
pub(super) fn cv_contains(expr: &Expression, name: &str) -> bool {
let found = match &expr.kind {
ExprKind::Variable(n) => n == name,
ExprKind::Derivative { var, .. }
| ExprKind::PartialDerivative { var, .. }
| ExprKind::Integral { var, .. }
| ExprKind::ClosedIntegral { var, .. }
| ExprKind::Limit { var, .. } => var == name,
ExprKind::MultipleIntegral { vars, .. } => vars.iter().any(|v| v == name),
ExprKind::Sum { index, .. } | ExprKind::Product { index, .. } => index == name,
ExprKind::ForAll { variable, .. }
| ExprKind::Exists { variable, .. }
| ExprKind::SetBuilder { variable, .. } => variable == name,
ExprKind::Tensor { indices, .. }
| ExprKind::KroneckerDelta { indices }
| ExprKind::LeviCivita { indices } => indices.iter().any(|idx| idx.name == name),
ExprKind::Differential { var } => var == name,
_ => false,
};
if found {
return true;
}
let mut result = false;
for_each_child(expr, |child| {
if !result {
result = cv_contains(child, name);
}
});
result
}