1 use crate::context
::Context
;
2 use crate::index_struct
;
3 use crate::strand
::Strand
;
4 use crate::tables
::Tables
;
5 use crate::{Minimums, TableIndex, TimeStamp}
;
7 use std
::ops
::{Index, IndexMut, Range}
;
9 use chalk_ir
::interner
::Interner
;
13 pub(crate) struct Stack
<I
: Interner
, C
: Context
<I
>> {
14 /// Stack: as described above, stores the in-progress goals.
15 stack
: Vec
<StackEntry
<I
, C
>>,
18 impl<I
: Interner
, C
: Context
<I
>> Stack
<I
, C
> {
19 // This isn't actually used, but it can be helpful when debugging stack issues
21 pub(crate) fn debug_with
<'a
>(&'a
self, tables
: &'a Tables
<I
>) -> StackDebug
<'_
, I
, C
> {
29 pub(crate) struct StackDebug
<'a
, I
: Interner
, C
: Context
<I
>> {
30 stack
: &'a Stack
<I
, C
>,
31 tables
: &'a Tables
<I
>,
34 impl<I
: Interner
, C
: Context
<I
>> fmt
::Debug
for StackDebug
<'_
, I
, C
> {
35 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
36 writeln
!(f
, "---- Stack ----")?
;
37 for entry
in self.stack
.stack
.iter() {
38 writeln
!(f
, " --- StackEntry ---")?
;
41 " Table {:?} with goal {:?}",
42 entry
.table
, self.tables
[entry
.table
].table_goal
44 writeln
!(f
, " Active strand: {:#?}", entry
.active_strand
)?
;
47 " Additional strands: {:#?}",
48 self.tables
[entry
.table
].strands().collect
::<Vec
<_
>>()
51 write
!(f
, "---- End Stack ----")?
;
56 impl<I
: Interner
, C
: Context
<I
>> Default
for Stack
<I
, C
> {
57 fn default() -> Self {
58 Stack { stack: vec![] }
63 /// The StackIndex identifies the position of a table's goal in the
64 /// stack of goals that are actively being processed. Note that once a
65 /// table is completely evaluated, it may be popped from the stack,
66 /// and hence no longer have a stack index.
67 pub(crate) struct StackIndex
{
73 pub(crate) struct StackEntry
<I
: Interner
, C
: Context
<I
>> {
74 /// The goal G from the stack entry `A :- G` represented here.
75 pub(super) table
: TableIndex
,
77 /// The clock TimeStamp of this stack entry.
78 pub(super) clock
: TimeStamp
,
80 pub(super) cyclic_minimums
: Minimums
,
82 // FIXME: should store this as an index.
83 // This would mean that if we unwind,
84 // we don't need to worry about losing a strand
85 pub(super) active_strand
: Option
<Strand
<I
, C
>>,
88 impl<I
: Interner
, C
: Context
<I
>> Stack
<I
, C
> {
89 pub(super) fn is_empty(&self) -> bool
{
93 /// Searches the stack to see if `table` is active. If so, returns
95 pub(super) fn is_active(&self, table
: TableIndex
) -> Option
<StackIndex
> {
99 .filter_map(|(index
, stack_entry
)| {
100 if stack_entry
.table
== table
{
101 Some(StackIndex
::from(index
))
109 pub(super) fn top_of_stack_from(&self, depth
: StackIndex
) -> Range
<StackIndex
> {
110 depth
..StackIndex
::from(self.stack
.len())
116 cyclic_minimums
: Minimums
,
119 let old_len
= self.stack
.len();
120 self.stack
.push(StackEntry
{
126 StackIndex
::from(old_len
)
129 /// Pops the top-most entry from the stack:
130 /// * If the stack is now empty, returns false.
131 /// * Otherwise, returns true.
132 fn pop_and_adjust_depth(&mut self) -> bool
{
134 !self.stack
.is_empty()
137 /// Pops the top-most entry from the stack, which should have the depth `*depth`:
138 /// * If the stack is now empty, returns None.
139 /// * Otherwise, `take`s the active strand from the new top and returns it.
140 pub(super) fn pop_and_take_caller_strand(&mut self) -> Option
<Strand
<I
, C
>> {
141 if self.pop_and_adjust_depth() {
142 Some(self.top().active_strand
.take().unwrap())
148 /// Pops the top-most entry from the stack, which should have the depth `*depth`:
149 /// * If the stack is now empty, returns None.
150 /// * Otherwise, borrows the active strand (mutably) from the new top and returns it.
151 pub(super) fn pop_and_borrow_caller_strand(&mut self) -> Option
<&mut Strand
<I
, C
>> {
152 if self.pop_and_adjust_depth() {
153 Some(self.top().active_strand
.as_mut().unwrap())
159 pub(super) fn top(&mut self) -> &mut StackEntry
<I
, C
> {
160 self.stack
.last_mut().unwrap()
164 impl<I
: Interner
, C
: Context
<I
>> Index
<StackIndex
> for Stack
<I
, C
> {
165 type Output
= StackEntry
<I
, C
>;
167 fn index(&self, index
: StackIndex
) -> &StackEntry
<I
, C
> {
168 &self.stack
[index
.value
]
172 impl<I
: Interner
, C
: Context
<I
>> IndexMut
<StackIndex
> for Stack
<I
, C
> {
173 fn index_mut(&mut self, index
: StackIndex
) -> &mut StackEntry
<I
, C
> {
174 &mut self.stack
[index
.value
]