use std::{iter::repeat, rc::Rc};
use super::Goal;
use crate::core::{Fork, State, StateIter};
#[derive(Debug, Clone)]
pub struct Any {
goals: Vec<Rc<dyn Goal>>,
}
impl From<Vec<Rc<dyn Goal>>> for Any {
fn from(goals: Vec<Rc<dyn Goal>>) -> Self {
Any { goals }
}
}
impl FromIterator<Rc<dyn Goal>> for Any {
fn from_iter<T: IntoIterator<Item = Rc<dyn Goal>>>(iter: T) -> Self {
Any {
goals: iter.into_iter().collect(),
}
}
}
impl Goal for Any {
fn apply(&self, state: State) -> Option<State> {
state.fork(self.clone())
}
}
impl Fork for Any {
fn fork(&self, state: &State) -> StateIter {
let goals = self.goals.clone().into_iter();
let states = repeat(state.clone());
Box::new(goals.zip(states).flat_map(|(g, s)| g.apply(s).into_iter()))
}
}
#[macro_export]
macro_rules! any {
($($item:expr),* $(,)?) => {
{
let goals: Vec<std::rc::Rc<dyn $crate::goals::Goal>> = vec![$(std::rc::Rc::new($item)),*];
$crate::goals::Any::from(goals)
}
};
}
pub use any;
#[cfg(test)]
mod tests {
use crate::{
core::LVar,
core::Query,
goals::{both::both, fail::Fail, unify},
};
use super::any;
#[test]
fn both_succeed() {
let x = LVar::new();
let goal = any![unify(x, 5), unify(x, 7)];
let result = goal.query(x).collect::<Vec<_>>();
assert_eq!(result, vec![5, 7]);
}
#[test]
fn one_succeeds() {
let x = LVar::new();
let goal = any![unify(x, 5), both(Fail, unify(x, 7))];
let result = goal.query(x).collect::<Vec<_>>();
assert_eq!(result, vec![5]);
}
#[test]
fn all_fail() {
let x = LVar::new();
let goal = any![both(Fail, unify(x, 5)), both(Fail, unify(x, 7))];
let result = goal.query(x).collect::<Vec<_>>();
assert_eq!(result, vec![]);
}
}