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