use crate::{logic::Mapping, std::ops::*, *};
use ::std::iter::Filter;
pub trait FilterExt<I, F> {
#[logic]
fn iter(self) -> I;
#[logic]
fn func(self) -> F;
}
impl<I, F> FilterExt<I, F> for Filter<I, F> {
#[trusted]
#[logic]
#[ensures(inv(self) ==> inv(result))]
fn iter(self) -> I {
dead
}
#[trusted]
#[logic]
#[ensures(inv(self) ==> inv(result))]
fn func(self) -> F {
dead
}
}
impl<I: Iterator, F: FnMut(&I::Item) -> bool> Invariant for Filter<I, F> {
#[predicate(prophetic)]
#[open(self)]
fn invariant(self) -> bool {
pearlite! {
forall<f : F, i : &I::Item> f.precondition((i,)) &&
(forall<f : F, g : F> f.unnest(g) ==> f == g) &&
(forall<f1 : F, f2 : F, i : _> !(f1.postcondition_mut((i,), f2, true) && f1.postcondition_mut((i,), f2, false)))
}
}
}
#[open]
#[predicate(prophetic)]
pub fn no_precondition<A, F: FnMut(A) -> bool>(_: F) -> bool {
pearlite! { forall<f : F, i : A> f.precondition((i,)) }
}
#[open]
#[predicate(prophetic)]
pub fn immutable<A, F: FnMut(A) -> bool>(_: F) -> bool {
pearlite! { forall<f : F, g : F> f.unnest(g) ==> f == g }
}
#[open]
#[predicate(prophetic)]
pub fn precise<A, F: FnMut(A) -> bool>(_: F) -> bool {
pearlite! { forall<f1 : F, f2 : F, i : _> !(f1.postcondition_mut((i,), f2, true) && f1.postcondition_mut((i,), f2, false)) }
}
impl<I, F> Iterator for Filter<I, F>
where
I: Iterator,
F: FnMut(&I::Item) -> bool,
{
#[open]
#[predicate(prophetic)]
fn completed(&mut self) -> bool {
pearlite! {
(exists<s: Seq<_>, e : &mut I > self.iter().produces(s, *e) && e.completed() &&
forall<i : _> 0 <= i && i < s.len() ==> (*self).func().postcondition_mut((&s[i],), (^self).func(), false))
&& (*self).func() == (^self).func()
}
}
#[open]
#[predicate(prophetic)]
fn produces(self, visited: Seq<Self::Item>, succ: Self) -> bool {
pearlite! {
self.invariant() ==>
self.func().unnest(succ.func()) &&
exists<s : Seq<Self::Item>, f : Mapping<Int, Int>> self.iter().produces(s, succ.iter()) &&
(forall<i : _, j :_ > 0 <= i && i <= j && j < visited.len() ==> 0 <= f.get(i) && f.get(i) <= f.get(j) && f.get(j) < s.len()) &&
(forall<i : _, > 0 <= i && i < visited.len() ==> visited[i] == s[f.get(i)]) &&
(forall<i : _> 0 <= i && i < s.len() ==>
(exists<j : _> 0 <= j && j < visited.len() && f.get(j) == i) == self.func().postcondition_mut((&s[i],), self.func(), true)
)
}
}
#[law]
#[open(self)]
#[ensures(self.produces(Seq::EMPTY, self))]
fn produces_refl(self) {}
#[law]
#[open(self)]
#[requires(a.produces(ab, b))]
#[requires(b.produces(bc, c))]
#[ensures(a.produces(ab.concat(bc), c))]
fn produces_trans(a: Self, ab: Seq<Self::Item>, b: Self, bc: Seq<Self::Item>, c: Self) {}
}