1use crate::context::{AnswerResult, AnswerStream};
2use crate::logic::RootSearchFail;
3use crate::slg::SlgContextOps;
4use crate::table::AnswerIndex;
5use crate::tables::Tables;
6use crate::{TableIndex, TimeStamp};
7
8use chalk_ir::interner::Interner;
9use chalk_ir::{Goal, InEnvironment, Substitution, UCanonical};
10use tracing::debug;
11
12pub(crate) struct Forest<I: Interner> {
13    pub(crate) tables: Tables<I>,
14
15    pub(crate) clock: TimeStamp,
20}
21
22impl<I: Interner> Forest<I> {
23    pub fn new() -> Self {
24        Forest {
25            tables: Tables::new(),
26            clock: TimeStamp::default(),
27        }
28    }
29
30    pub(crate) fn increment_clock(&mut self) -> TimeStamp {
32        self.clock.increment();
33        self.clock
34    }
35
36    pub fn iter_answers<'f>(
41        &'f mut self,
42        context: &'f SlgContextOps<'f, I>,
43        goal: &UCanonical<InEnvironment<Goal<I>>>,
44    ) -> impl AnswerStream<I> + 'f {
45        let table = self.get_or_create_table_for_ucanonical_goal(context, goal.clone());
46        let answer = AnswerIndex::ZERO;
47        ForestSolver {
48            forest: self,
49            context,
50            table,
51            answer,
52        }
53    }
54}
55
56struct ForestSolver<'me, I: Interner> {
57    forest: &'me mut Forest<I>,
58    context: &'me SlgContextOps<'me, I>,
59    table: TableIndex,
60    answer: AnswerIndex,
61}
62
63impl<'me, I: Interner> AnswerStream<I> for ForestSolver<'me, I> {
64    fn peek_answer(&mut self, should_continue: impl Fn() -> bool) -> AnswerResult<I> {
68        loop {
69            match self
70                .forest
71                .root_answer(self.context, self.table, self.answer)
72            {
73                Ok(answer) => {
74                    debug!(answer = ?(&answer));
75                    return AnswerResult::Answer(answer);
76                }
77
78                Err(RootSearchFail::InvalidAnswer) => {
79                    self.answer.increment();
80                }
81                Err(RootSearchFail::Floundered) => {
82                    return AnswerResult::Floundered;
83                }
84
85                Err(RootSearchFail::NoMoreSolutions) => {
86                    return AnswerResult::NoMoreSolutions;
87                }
88
89                Err(RootSearchFail::QuantumExceeded) => {
90                    if !should_continue() {
91                        return AnswerResult::QuantumExceeded;
92                    }
93                }
94
95                Err(RootSearchFail::NegativeCycle) => {
96                    panic!("negative cycle was detected");
102                }
103            }
104        }
105    }
106
107    fn next_answer(&mut self, should_continue: impl Fn() -> bool) -> AnswerResult<I> {
108        let answer = self.peek_answer(should_continue);
109        self.answer.increment();
110        answer
111    }
112
113    fn any_future_answer(&self, test: impl Fn(&Substitution<I>) -> bool) -> bool {
114        self.forest.any_future_answer(self.table, self.answer, test)
115    }
116}