use crate::iteration::comprehension::ast::Comprehension;
pub fn apply(ast: &Comprehension) -> Option<Comprehension> {
let Comprehension::Order { child: outer_child, strategy: outer_strat, truncation: outer_trunc } = ast else {
return None;
};
let Comprehension::Order { child: inner_child, truncation: None, .. } = outer_child.as_ref() else {
return None;
};
Some(Comprehension::Order {
child: inner_child.clone(),
strategy: *outer_strat,
truncation: *outer_trunc,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::iteration::comprehension::source::{LiteralValue, Source};
use crate::iteration::comprehension::strategy::StrategyName;
fn clause(name: &str, vs: &[i64]) -> Comprehension {
Comprehension::clause(
name,
Source::Literal {
values: vs.iter().map(|n| LiteralValue::Int(*n)).collect(),
},
)
}
#[test]
fn r7_folds_two_orders_when_inner_untruncated() {
let inner = clause("k", &[1, 2, 3]);
let o1 = Comprehension::order(inner.clone(), StrategyName::Shuffle, None);
let o2 = Comprehension::order(o1, StrategyName::Halton, Some(2));
let result = apply(&o2).unwrap();
match result {
Comprehension::Order { child, strategy: StrategyName::Halton, truncation: Some(2) } => {
assert_eq!(&*child, &inner);
}
other => panic!("expected Order(Halton, Some(2)) → clause, got {other:?}"),
}
}
#[test]
fn r7_does_not_fire_when_inner_truncated() {
let inner = clause("k", &[1, 2, 3]);
let o1 = Comprehension::order(inner, StrategyName::Shuffle, Some(2));
let o2 = Comprehension::order(o1, StrategyName::Halton, Some(1));
assert_eq!(apply(&o2), None);
}
#[test]
fn r7_does_not_fire_for_single_order() {
let ast = Comprehension::order(clause("k", &[1]), StrategyName::Lex, None);
assert_eq!(apply(&ast), None);
}
}