#![feature(ptr_sub_ptr)]
#![feature(slice_split_at_unchecked)]
#![feature(slice_swap_unchecked)]
#![feature(slice_pattern)]
#![warn(missing_docs)]
pub mod name {
use core::marker::PhantomData;
#[derive(Copy, Clone)]
pub struct Name<'name>(PhantomData<&'name ()>);
pub const fn name<'name>() -> Name<'name> {
Name(PhantomData)
}
}
pub mod only {
use super::name::{name, Name};
pub unsafe trait Only<'name> {
fn name(&self) -> Name<'name> {
name::<'name>()
}
}
}
pub mod call {
use super::link::Link;
use super::name::name;
use super::only::Only;
use core::ops::Deref;
pub struct Call<'name, T> {
link: Link<'name, T>,
}
unsafe impl<'name, T> Only<'name> for Call<'name, T> {}
impl<'name, T> Call<'name, T> {
pub fn into_owned(self) -> T {
self.link.body
}
pub unsafe fn as_mut(&mut self) -> &mut T {
&mut self.link.body
}
}
impl<'name, T> Deref for Call<'name, T> {
type Target = T;
fn deref(&self) -> &T {
&self.link.body
}
}
pub const unsafe fn forge<'name, T>(
body: T,
) -> Call<'name, T> {
Call {
link: Link {
body,
name: name::<'name>(),
},
}
}
}
pub mod called {
use super::call::{forge, Call};
pub trait Called {
fn called<Out, Body>(self: Self, body: Body) -> Out
where
Body: for<'call> FnOnce(Call<'call, Self>) -> Out,
Self: Sized;
}
impl<T> Called for T
where
T: Sized,
{
fn called<'here, Out, Body>(
self: Self,
body: Body,
) -> Out
where
Body: for<'call> FnOnce(Call<'call, Self>) -> Out,
Self: Sized,
{
body(unsafe { forge(self) })
}
}
}
pub mod link {
use super::name::{name, Name};
#[derive(Copy, Clone)]
pub struct Link<'name, T> {
pub body: T,
pub name: Name<'name>,
}
pub const fn link<'name, T>(body: T) -> Link<'name, T> {
Link {
body,
name: name::<'name>(),
}
}
}
pub mod prop {
use super::name::Name;
pub struct Sorted<'name>(Name<'name>);
}
pub mod vec {
use super::call::{forge, Call};
use super::key::Key;
use super::link::{link, Link};
use super::name::name;
use super::only::Only;
use super::proof::{assume, Eqv, Prf, Sub};
use super::prop;
use core::cmp::Ordering;
use core::ops::Range;
use core::slice;
use core::slice::SlicePattern;
use std::vec;
pub struct Vec<'name, T> {
own: Call<'name, vec::Vec<T>>,
}
pub struct Slice<'name, 'vec, T> {
#[allow(missing_docs)]
pub own: Link<'name, &'vec [T]>,
}
impl<'name, 'vec, T> From<Link<'name, &'vec [T]>>
for Slice<'name, 'vec, T>
{
fn from(own: Link<'name, &'vec [T]>) -> Self {
Slice { own }
}
}
pub struct MutSlice<'name, 'vec, T> {
#[allow(missing_docs)]
pub own: Link<'name, &'vec mut [T]>,
}
impl<'name, 'vec, T> From<Link<'name, &'vec mut [T]>>
for MutSlice<'name, 'vec, T>
{
fn from(own: Link<'name, &'vec mut [T]>) -> Self {
MutSlice { own }
}
}
pub struct ConstPtr<'name, T> {
#[allow(missing_docs)]
pub own: Link<'name, *const T>,
}
impl<'name, T> From<Link<'name, *const T>>
for ConstPtr<'name, T>
{
fn from(own: Link<'name, *const T>) -> Self {
ConstPtr { own }
}
}
pub struct MutPtr<'name, T> {
#[allow(missing_docs)]
pub own: Link<'name, *mut T>,
}
impl<'name, T> From<Link<'name, *mut T>> for MutPtr<'name, T> {
fn from(own: Link<'name, *mut T>) -> Self {
MutPtr { own }
}
}
impl<'name, T> From<Call<'name, vec::Vec<T>>>
for Vec<'name, T>
{
fn from(own: Call<'name, vec::Vec<T>>) -> Self {
Vec { own }
}
}
impl<'name, T> Vec<'name, T> {
pub fn new() -> Vec<'name, T> {
unsafe { Vec::from(forge(vec::Vec::new())) }
}
pub fn with_capacity(capacity: usize) -> Vec<'name, T> {
unsafe {
Vec::from(forge(vec::Vec::with_capacity(
capacity,
)))
}
}
pub unsafe fn from_raw_parts(
ptr: *mut T,
length: usize,
capacity: usize,
) -> Vec<'name, T> {
unsafe {
Vec::from(forge(vec::Vec::from_raw_parts(
ptr, length, capacity,
)))
}
}
pub fn capacity(&self) -> usize {
self.own.capacity()
}
pub fn reserve(&mut self, additional: usize) -> () {
unsafe { self.own.as_mut().reserve(additional) }
}
pub fn reserve_exact(
&mut self,
additional: usize,
) -> () {
unsafe {
self.own.as_mut().reserve_exact(additional)
}
}
pub fn try_reserve_exact(
&mut self,
additional: usize,
) -> Result<(), std::collections::TryReserveError>
{
unsafe {
self.own.as_mut().try_reserve_exact(additional)
}
}
}
impl<'before_truncate, T> Vec<'before_truncate, T> {
pub fn truncate<'after_truncate>(
self,
len: usize,
) -> (
Vec<'after_truncate, T>,
Prf<Sub<'after_truncate, 'before_truncate>>,
impl Fn(
Key<'before_truncate, usize>,
)
-> Option<Key<'after_truncate, usize>>,
) {
let mut old = self.own.into_owned();
old.truncate(len);
(
unsafe { Vec::from(forge(old)) },
unsafe {
assume::<
Sub<'after_truncate, 'before_truncate>,
>()
},
move |key| {
if key.index() < len {
Some(unsafe {
Key::new(
key.index(),
name::<'after_truncate>(),
)
})
} else {
None
}
},
)
}
}
impl<'name, T> Vec<'name, T> {
pub fn as_slice<'vec>(
&'vec self,
) -> Slice<'name, 'vec, T>
where
'vec: 'name,
{
Slice::from(link(self.own.as_slice()))
}
pub fn as_mut_slice<'vec>(
&'vec mut self,
) -> MutSlice<'name, 'vec, T>
where
'vec: 'name,
{
MutSlice::from(link(unsafe {
self.own.as_mut().as_mut_slice()
}))
}
pub unsafe fn as_ptr(&self) -> ConstPtr<'name, T> {
ConstPtr::from(link(self.own.as_ptr()))
}
pub unsafe fn as_mut_ptr(
&mut self,
) -> MutPtr<'name, T> {
MutPtr::from(link(self.own.as_mut().as_mut_ptr()))
}
pub unsafe fn as_ptr_range(
&self,
) -> Range<ConstPtr<'name, T>> {
let Range { start, end } = self.own.as_ptr_range();
ConstPtr::from(link(start))
..ConstPtr::from(link(end))
}
pub unsafe fn as_mut_ptr_range(
&mut self,
) -> Range<MutPtr<'name, T>> {
let Range { start, end } =
self.own.as_mut().as_mut_ptr_range();
MutPtr::from(link(start))..MutPtr::from(link(end))
}
pub fn swap(
&mut self,
a: Key<'name, usize>,
b: Key<'name, usize>,
) {
debug_assert!(
a.index() < self.len()
&& b.index() < self.len()
);
unsafe {
self.own
.as_mut()
.swap_unchecked(a.index(), b.index())
}
}
pub fn push<'changed>(
self,
value: T,
) -> (
Vec<'changed, T>,
Key<'changed, usize>,
impl Fn(Key<'name, usize>) -> Key<'changed, usize>,
) {
let mut old = self.own.into_owned();
let index = old.len();
old.push(value);
(
unsafe { Vec::from(forge(old)) },
unsafe { Key::new(index, name::<'changed>()) },
|k| unsafe {
Key::new(k.index(), name::<'changed>())
},
)
}
pub fn len(&self) -> usize {
self.own.len()
}
pub fn swap_unchecked(
&mut self,
a: Key<'name, usize>,
b: Key<'name, usize>,
) {
self.swap(a, b)
}
}
impl<'before_reverse, T> Vec<'before_reverse, T> {
pub fn reverse<'after_reverse>(
self,
) -> (
Vec<'after_reverse, T>,
Prf<Eqv<'before_reverse, 'after_reverse>>,
impl Fn(
Key<'before_reverse, usize>,
) -> Key<'after_reverse, usize>,
) {
let mut old = self.own.into_owned();
old.reverse();
let len = old.len();
(
unsafe { Vec::from(forge(old)) },
unsafe {
assume::<Eqv<'before_reverse, 'after_reverse>>(
)
},
move |key| unsafe {
Key::new(
len - key.index() - 1,
name::<'after_reverse>(),
)
},
)
}
}
impl<'name, T> Vec<'name, T> {
pub fn reverse_mut(&mut self) {
unsafe { self.own.as_mut().reverse() }
}
pub fn iter(&self) -> slice::Iter<'_, T> {
self.own.iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
unsafe { self.own.as_mut().iter_mut() }
}
pub fn split_at<'vec>(
&'vec self,
mid: Key<'name, usize>,
) -> (Slice<'name, 'vec, T>, Slice<'name, 'vec, T>)
where
'vec: 'name,
{
debug_assert!(mid.index() <= self.len());
unsafe {
let (left, right) =
self.own.split_at_unchecked(mid.index());
(
Slice::from(link(left)),
Slice::from(link(right)),
)
}
}
pub fn split_at_mut<'vec>(
&'vec mut self,
mid: Key<'name, usize>,
) -> (MutSlice<'name, 'vec, T>, MutSlice<'name, 'vec, T>)
where
'vec: 'name,
{
debug_assert!(mid.index() <= self.len());
unsafe {
let (left, right) = self
.own
.as_mut()
.split_at_mut_unchecked(mid.index());
(
MutSlice::from(link(left)),
MutSlice::from(link(right)),
)
}
}
pub fn split_at_unchecked<'vec>(
&'vec self,
mid: Key<'name, usize>,
) -> (Slice<'name, 'vec, T>, Slice<'name, 'vec, T>)
where
'vec: 'name,
{
self.split_at(mid)
}
pub fn split_at_mut_unchecked<'vec>(
&'vec mut self,
mid: Key<'name, usize>,
) -> (MutSlice<'name, 'vec, T>, MutSlice<'name, 'vec, T>)
where
'vec: 'name,
{
self.split_at_mut(mid)
}
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq<T>,
{
self.own.contains(x)
}
pub fn starts_with(&self, needle: &[T]) -> bool
where
T: PartialEq<T>,
{
self.own.starts_with(needle)
}
pub fn ends_with(&self, needle: &[T]) -> bool
where
T: PartialEq<T>,
{
self.own.ends_with(needle)
}
pub fn strip_prefix<'vec, P>(
&'vec self,
prefix: &P,
) -> Option<Slice<'name, 'vec, T>>
where
P: SlicePattern<Item = T> + ?Sized,
T: PartialEq<T>,
'vec: 'name,
{
self.own
.strip_prefix(prefix)
.map(|slice| Slice::from(link(slice)))
}
pub fn strip_suffix<'vec, P>(
&'vec self,
suffix: &P,
) -> Option<Slice<'name, 'vec, T>>
where
P: SlicePattern<Item = T> + ?Sized,
T: PartialEq<T>,
'vec: 'name,
{
self.own
.strip_suffix(suffix)
.map(|slice| Slice::from(link(slice)))
}
pub fn binary_search(
&self,
x: &T,
) -> Result<Key<'name, usize>, usize>
where
T: Ord,
{
self.own.binary_search(x).map(|index| unsafe {
Key::new(index, name::<'name>())
})
}
pub fn binary_search_by<F>(
&self,
f: F,
) -> Result<Key<'name, usize>, usize>
where
F: FnMut(&T) -> Ordering,
{
self.own.binary_search_by(f).map(|index| unsafe {
Key::new(index, name::<'name>())
})
}
pub fn binary_search_by_key<B, F>(
&self,
b: &B,
f: F,
) -> Result<Key<'name, usize>, usize>
where
F: FnMut(&T) -> B,
B: Ord,
{
self.own.binary_search_by_key(b, f).map(
|index| unsafe {
Key::new(index, name::<'name>())
},
)
}
pub fn sort_unstable<'changed>(
self,
) -> (Vec<'changed, T>, Prf<prop::Sorted<'changed>>)
where
T: Ord,
{
let mut old = self.own.into_owned();
old.sort_unstable();
(unsafe { Vec::from(forge(old)) }, unsafe {
assume::<prop::Sorted<'changed>>()
})
}
pub fn contains_key(
&self,
index: usize,
) -> Option<Key<'name, usize>> {
self.own.get(index).map(|_val| unsafe {
Key::new(index, name::<'name>())
})
}
pub fn get(&self, key: Key<'name, usize>) -> &T {
unsafe { self.own.get_unchecked(key.index()) }
}
}
impl<'name, 'vec, T> Slice<'name, 'vec, T> {
pub fn index(
&self,
vec: &'vec Vec<'name, T>,
) -> Key<'name, usize> {
unsafe {
debug_assert!(vec
.own
.as_ptr_range()
.contains(&self.own.body.as_ptr()));
Key::new(
self.own
.body
.as_ptr()
.sub_ptr(vec.own.as_ptr()),
vec.own.name(),
)
}
}
}
impl<'name, 'vec, T> MutSlice<'name, 'vec, T> {
pub fn index(
&mut self,
vec: &'vec mut Vec<'name, T>,
) -> Key<'name, usize> {
unsafe {
debug_assert!(vec
.own
.as_ptr_range()
.contains(&self.own.body.as_ptr()));
Key::new(
self.own
.body
.as_mut_ptr()
.sub_ptr(vec.own.as_mut().as_mut_ptr()),
vec.own.name(),
)
}
}
} }
pub mod vec_deque {
use super::call::Call;
use std::collections::vec_deque;
pub type VecDeque<'name, T> =
Call<'name, vec_deque::VecDeque<T>>;
}
pub mod linked_list {
use super::call::Call;
use std::collections::linked_list;
pub type LinkedList<'name, T> =
Call<'name, linked_list::LinkedList<T>>;
}
pub mod hash_map {
use super::call::Call;
use std::collections::hash_map;
pub type HashMap<'name, K, V, S = hash_map::RandomState> =
Call<'name, hash_map::HashMap<K, V, S>>;
}
pub mod btree_map {
use super::call::Call;
use std::collections::btree_map;
pub type BTreeMap<'name, K, V> =
Call<'name, btree_map::BTreeMap<K, V>>;
}
pub mod binary_heap {
use super::call::Call;
use std::collections::binary_heap;
pub type BinaryHeap<'name, T> =
Call<'name, binary_heap::BinaryHeap<T>>;
}
pub mod key {
use super::link::Link;
use super::name::Name;
#[derive(Copy, Clone)]
pub struct Key<'name, Index> {
own: Link<'name, Index>,
}
impl<'name, Index> Key<'name, Index> {
pub unsafe fn new(
body: Index,
name: Name<'name>,
) -> Self {
Key {
own: Link { body, name },
}
}
pub fn index(&self) -> Index
where
Index: Copy,
{
self.own.body
}
}
}
pub mod proof {
use super::name::Name;
use core::marker::PhantomData;
pub struct Prf<A>(PhantomData<A>);
pub enum False {}
pub enum True {}
pub struct Not<A>(PhantomData<A>);
pub struct And<A, B>(PhantomData<(A, B)>);
pub struct Or<A, B>(PhantomData<(A, B)>);
pub struct Imp<A, B>(PhantomData<(A, B)>);
pub struct Sub<'s, 't>(Name<'s>, Name<'t>);
pub struct Iff<A, B>(PhantomData<(A, B)>);
pub struct Eqv<'s, 't>(Name<'s>, Name<'t>);
pub unsafe fn assume<A>() -> Prf<A> {
axiom()
}
fn axiom<A>() -> Prf<A> {
Prf(PhantomData)
}
pub fn lam<A, B>(_s: impl Fn(A) -> B) -> Prf<Imp<A, B>> {
axiom()
}
pub fn app<A, B>(
_a_to_b: &Prf<Imp<A, B>>,
_a: &Prf<A>,
) -> Prf<B> {
axiom()
}
pub fn and<A, B>(_a: Prf<A>, _b: Prf<B>) -> Prf<And<A, B>> {
axiom()
}
pub fn fst<A, B>(_a_and_b: Prf<And<A, B>>) -> Prf<A> {
axiom()
}
pub fn snd<A, B>(_a_and_b: Prf<And<A, B>>) -> Prf<B> {
axiom()
}
pub fn or<A, B, C>(
_a_or_b: &Prf<Or<A, B>>,
_a_to_c: &Prf<Imp<A, C>>,
_b_to_c: &Prf<Imp<B, C>>,
) -> Prf<C> {
axiom()
}
pub fn left<A, B>(_a: &Prf<A>) -> Prf<Or<A, B>> {
axiom()
}
pub fn right<A, B>(_b: &Prf<B>) -> Prf<Or<A, B>> {
axiom()
}
pub fn not<A>(_a_to_f: &Prf<Imp<A, False>>) -> Prf<Not<A>> {
axiom()
}
pub fn contradiction<A>(
_a: &Prf<A>,
_not_a: &Prf<Not<A>>,
) -> Prf<False> {
axiom()
}
pub fn trivial<A>() -> Prf<True> {
axiom()
}
pub fn impossible<A>(_f: &Prf<False>) -> Prf<A> {
axiom()
}
pub fn iff_refl<A>() -> Prf<Iff<A, A>> {
axiom()
}
pub fn imp_refl<A>() -> Prf<Imp<A, A>> {
axiom()
}
pub fn iff_symm<A, B>(
_a_iff_b: &Prf<Iff<A, B>>,
) -> Prf<Iff<B, A>> {
axiom()
}
pub fn iff_trans<A, B, C>(
_a_iff_b: &Prf<Iff<A, B>>,
_b_iff_c: &Prf<Iff<B, C>>,
) -> Prf<Iff<A, C>> {
axiom()
}
pub fn imp_trans<A, B, C>(
_a_imp_b: &Prf<Imp<A, B>>,
_b_imp_c: &Prf<Imp<B, C>>,
) -> Prf<Imp<A, C>> {
axiom()
}
pub fn imp_antisymm<A, B>(
_a_imp_b: &Prf<Imp<A, B>>,
_b_imp_a: &Prf<Imp<B, A>>,
) -> Prf<Iff<A, B>> {
axiom()
}
}
#[cfg(test)]
mod tests {
use super::called::Called;
use super::key::Key;
use super::vec::Vec;
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
#[test]
fn named_vec() {
std::vec::Vec::new().called(|filenames| {
let filenames = Vec::from(filenames);
let (filenames, _, _) =
filenames.push(String::from("taxes.txt"));
let (filenames, _, _) =
filenames.push(String::from("passwords.txt"));
let passwords = filenames.contains_key(1).unwrap();
assert_eq!(
filenames.get(passwords),
&"passwords.txt"
);
let (filenames, poems, upcast) =
filenames.push(String::from("poems.txt"));
{
fn assert_type<'passwords, 'poems>(
_: &Key<'passwords, usize>,
_: &Key<'poems, usize>,
_: &impl Fn(
Key<'passwords, usize>,
)
-> Key<'poems, usize>,
) {
}
assert_type(&passwords, &poems, &upcast);
}
assert_eq!(filenames.get(poems), &"poems.txt");
assert_eq!(
filenames.get(upcast(passwords)),
&"passwords.txt"
);
});
}
}