use core::marker;
#[allow(unused_imports)]
use super::pervasive::*;
#[allow(unused_imports)]
use super::prelude::*;
verus! {
#[verifier::external_body]
#[verifier::ext_equal]
#[verifier::accept_recursive_types(A)]
pub struct Seq<A> {
dummy: marker::PhantomData<A>,
}
impl<A> Seq<A> {
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::empty"]
pub uninterp spec fn empty() -> Seq<A>;
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::new"]
pub uninterp spec fn new(len: nat, f: impl Fn(int) -> A) -> Seq<A>;
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::len"]
pub uninterp spec fn len(self) -> nat;
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::index"]
pub uninterp spec fn index(self, i: int) -> A
recommends
0 <= i < self.len(),
;
#[verifier::inline]
pub open spec fn spec_index(self, i: int) -> A
recommends
0 <= i < self.len(),
{
self.index(i)
}
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::push"]
pub uninterp spec fn push(self, a: A) -> Seq<A>;
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::update"]
pub uninterp spec fn update(self, i: int, a: A) -> Seq<A>
recommends
0 <= i < self.len(),
;
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::subrange"]
pub uninterp spec fn subrange(self, start_inclusive: int, end_exclusive: int) -> Seq<A>
recommends
0 <= start_inclusive <= end_exclusive <= self.len(),
;
#[verifier::inline]
pub open spec fn take(self, n: int) -> Seq<A> {
self.subrange(0, n)
}
#[verifier::inline]
pub open spec fn skip(self, n: int) -> Seq<A> {
self.subrange(n, self.len() as int)
}
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::add"]
pub uninterp spec fn add(self, rhs: Seq<A>) -> Seq<A>;
#[verifier::inline]
pub open spec fn spec_add(self, rhs: Seq<A>) -> Seq<A> {
self.add(rhs)
}
#[rustc_diagnostic_item = "verus::vstd::seq::Seq::last"]
pub open spec fn last(self) -> A
recommends
0 < self.len(),
{
self[self.len() as int - 1]
}
#[rustc_diagnostic_item = "vstd::seq::Seq::first"]
pub open spec fn first(self) -> A
recommends
0 < self.len(),
{
self[0]
}
}
pub broadcast proof fn axiom_seq_index_decreases<A>(s: Seq<A>, i: int)
requires
0 <= i < s.len(),
ensures
#[trigger] (decreases_to!(s => s[i])),
{
admit();
}
pub proof fn axiom_seq_len_decreases<A>(s1: Seq<A>, s2: Seq<A>)
requires
s2.len() < s1.len(),
forall|i2: int|
0 <= i2 < s2.len() && #[trigger] trigger(s2[i2]) ==> exists|i1: int|
0 <= i1 < s1.len() && s1[i1] == s2[i2],
ensures
decreases_to!(s1 => s2),
{
admit();
}
pub broadcast proof fn axiom_seq_subrange_decreases<A>(s: Seq<A>, i: int, j: int)
requires
0 <= i <= j <= s.len(),
s.subrange(i, j).len() < s.len(),
ensures
#[trigger] (decreases_to!(s => s.subrange(i, j))),
{
broadcast use axiom_seq_subrange_len, axiom_seq_subrange_index;
let s2 = s.subrange(i, j);
assert forall|i2: int| 0 <= i2 < s2.len() && #[trigger] trigger(s2[i2]) implies exists|i1: int|
0 <= i1 < s.len() && s[i1] == s2[i2] by {
assert(s[i + i2] == s2[i2]);
}
axiom_seq_len_decreases(s, s2);
}
pub broadcast proof fn axiom_seq_empty<A>()
ensures
#[trigger] Seq::<A>::empty().len() == 0,
{
admit();
}
pub broadcast proof fn axiom_seq_new_len<A>(len: nat, f: spec_fn(int) -> A)
ensures
#[trigger] Seq::new(len, f).len() == len,
{
admit();
}
pub broadcast proof fn axiom_seq_new_index<A>(len: nat, f: spec_fn(int) -> A, i: int)
requires
0 <= i < len,
ensures
#[trigger] Seq::new(len, f)[i] == f(i),
{
admit();
}
pub broadcast proof fn axiom_seq_push_len<A>(s: Seq<A>, a: A)
ensures
#[trigger] s.push(a).len() == s.len() + 1,
{
admit();
}
pub broadcast proof fn axiom_seq_push_index_same<A>(s: Seq<A>, a: A, i: int)
requires
i == s.len(),
ensures
#[trigger] s.push(a)[i] == a,
{
admit();
}
pub broadcast proof fn axiom_seq_push_index_different<A>(s: Seq<A>, a: A, i: int)
requires
0 <= i < s.len(),
ensures
#[trigger] s.push(a)[i] == s[i],
{
admit();
}
pub broadcast proof fn axiom_seq_update_len<A>(s: Seq<A>, i: int, a: A)
requires
0 <= i < s.len(),
ensures
#[trigger] s.update(i, a).len() == s.len(),
{
admit();
}
pub broadcast proof fn axiom_seq_update_same<A>(s: Seq<A>, i: int, a: A)
requires
0 <= i < s.len(),
ensures
#[trigger] s.update(i, a)[i] == a,
{
admit();
}
pub broadcast proof fn axiom_seq_update_different<A>(s: Seq<A>, i1: int, i2: int, a: A)
requires
0 <= i1 < s.len(),
0 <= i2 < s.len(),
i1 != i2,
ensures
#[trigger] s.update(i2, a)[i1] == s[i1],
{
admit();
}
pub broadcast proof fn axiom_seq_ext_equal<A>(s1: Seq<A>, s2: Seq<A>)
ensures
#[trigger] (s1 =~= s2) <==> {
&&& s1.len() == s2.len()
&&& forall|i: int| 0 <= i < s1.len() ==> s1[i] == s2[i]
},
{
admit();
}
pub broadcast proof fn axiom_seq_ext_equal_deep<A>(s1: Seq<A>, s2: Seq<A>)
ensures
#[trigger] (s1 =~~= s2) <==> {
&&& s1.len() == s2.len()
&&& forall|i: int| 0 <= i < s1.len() ==> s1[i] =~~= s2[i]
},
{
admit();
}
pub broadcast proof fn axiom_seq_subrange_len<A>(s: Seq<A>, j: int, k: int)
requires
0 <= j <= k <= s.len(),
ensures
#[trigger] s.subrange(j, k).len() == k - j,
{
admit();
}
pub broadcast proof fn axiom_seq_subrange_index<A>(s: Seq<A>, j: int, k: int, i: int)
requires
0 <= j <= k <= s.len(),
0 <= i < k - j,
ensures
#[trigger] s.subrange(j, k)[i] == s[i + j],
{
admit();
}
pub broadcast proof fn axiom_seq_add_len<A>(s1: Seq<A>, s2: Seq<A>)
ensures
#[trigger] s1.add(s2).len() == s1.len() + s2.len(),
{
admit();
}
pub broadcast proof fn axiom_seq_add_index1<A>(s1: Seq<A>, s2: Seq<A>, i: int)
requires
0 <= i < s1.len(),
ensures
#[trigger] s1.add(s2)[i] == s1[i],
{
admit();
}
pub broadcast proof fn axiom_seq_add_index2<A>(s1: Seq<A>, s2: Seq<A>, i: int)
requires
s1.len() <= i < s1.len() + s2.len(),
ensures
#[trigger] s1.add(s2)[i] == s2[i - s1.len()],
{
admit();
}
pub broadcast group group_seq_axioms {
axiom_seq_index_decreases,
axiom_seq_subrange_decreases,
axiom_seq_empty,
axiom_seq_new_len,
axiom_seq_new_index,
axiom_seq_push_len,
axiom_seq_push_index_same,
axiom_seq_push_index_different,
axiom_seq_update_len,
axiom_seq_update_same,
axiom_seq_update_different,
axiom_seq_ext_equal,
axiom_seq_ext_equal_deep,
axiom_seq_subrange_len,
axiom_seq_subrange_index,
axiom_seq_add_len,
axiom_seq_add_index1,
axiom_seq_add_index2,
}
#[doc(hidden)]
#[macro_export]
macro_rules! seq_internal {
[] => {
$crate::vstd::seq::Seq::empty()
};
[$elem:expr] => {
$crate::vstd::seq::Seq::empty()
.push($elem)
};
[$($elem:expr),* $(,)?] => {
<_ as $crate::vstd::view::View>::view(&[$($elem),*])
};
[$elem:expr; $n:expr] => {
$crate::vstd::seq::Seq::new(
$n,
$crate::vstd::prelude::closure_to_fn_spec(
|_x: _| $elem
),
)
};
}
#[macro_export]
macro_rules! seq {
[$($tail:tt)*] => {
::builtin_macros::verus_proof_macro_exprs!($crate::vstd::seq::seq_internal!($($tail)*))
};
}
#[doc(hidden)]
pub use seq_internal;
pub use seq;
}