use crate::iteration::comprehension::ast::Comprehension;
use crate::iteration::comprehension::strategy::StrategyName;
pub fn apply(ast: &Comprehension) -> Option<Comprehension> {
let Comprehension::Order { child, strategy: StrategyName::Lex, truncation: None } = ast else {
return None;
};
let Comprehension::Filter { child: filter_child, predicate } = child.as_ref() else {
return None;
};
Some(Comprehension::Filter {
child: Box::new(Comprehension::Order {
child: filter_child.clone(),
strategy: StrategyName::Lex,
truncation: None,
}),
predicate: predicate.clone(),
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::iteration::comprehension::source::{LiteralValue, Source};
fn clause(name: &str, vs: &[i64]) -> Comprehension {
Comprehension::clause(
name,
Source::Literal {
values: vs.iter().map(|n| LiteralValue::Int(*n)).collect(),
},
)
}
#[test]
fn r3_commutes_lex_none_with_filter() {
let inner = clause("k", &[1, 2, 3]);
let filtered = Comprehension::filter(inner.clone(), "{k} > 0");
let ast = Comprehension::order(filtered, StrategyName::Lex, None);
let result = apply(&ast).unwrap();
match result {
Comprehension::Filter { child, predicate } => {
assert_eq!(predicate, "{k} > 0");
match child.as_ref() {
Comprehension::Order { strategy: StrategyName::Lex, truncation: None, .. } => {}
other => panic!("expected order(Lex, None) inside, got {other:?}"),
}
}
other => panic!("expected outer Filter, got {other:?}"),
}
}
#[test]
fn r3_does_not_fire_with_truncation() {
let inner = clause("k", &[1, 2, 3]);
let filtered = Comprehension::filter(inner, "{k} > 0");
let ast = Comprehension::order(filtered, StrategyName::Lex, Some(2));
assert_eq!(apply(&ast), None);
}
#[test]
fn r3_does_not_fire_for_non_lex() {
let inner = clause("k", &[1, 2, 3]);
let filtered = Comprehension::filter(inner, "{k} > 0");
let ast = Comprehension::order(filtered, StrategyName::Halton, None);
assert_eq!(apply(&ast), None);
}
#[test]
fn r3_does_not_fire_without_filter_child() {
let inner = clause("k", &[1, 2, 3]);
let ast = Comprehension::order(inner, StrategyName::Lex, None);
assert_eq!(apply(&ast), None);
}
}