coremem_types: list: allow Peano-based index operation

This commit is contained in:
colin 2022-07-20 03:49:39 -07:00
parent 159fa1b9a1
commit 3a235fe47e
2 changed files with 57 additions and 3 deletions

View File

@ -1,3 +1,5 @@
use crate::compound::peano::{P0, Peano, PNext};
#[derive(Copy, Clone, Default, PartialEq)]
struct Null;
@ -77,6 +79,13 @@ trait ElementOp<T> {
fn call(&self, el: &T) -> Self::Output;
}
impl<T, R, F: Fn(&T) -> R> ElementOp<T> for F {
type Output = R;
fn call(&self, el: &T) -> Self::Output {
(self)(el)
}
}
impl<Output, F, E, N> ListOp<F, LLNode<E, N>, Output> for LLNode<E, N>
where
F: ElementOp<E, Output=Output>,
@ -101,15 +110,42 @@ impl<Output, F> ListOp<F, Null, Output> for Null {
fn apply_all(&self, _f: F) {
// the tail element simply terminates recursion
}
fn apply_at_rel(&self, i: u32, cur: u32, _f: F) -> Output {
fn apply_at_rel(&self, _i: u32, _cur: u32, _f: F) -> Output {
// it's expected that the element was found by now
unreachable!();
}
}
/// implemented on a list AND index, allowing potentially non-generic code to fetch a
/// compile-time-constant element.
trait IndexOp<List, Index, Elem> {
fn get(&self, idx: Index) -> &Elem;
}
/// zero-index into Self
impl<E, N> IndexOp<LLNode<E, N>, P0, E> for LLNode<E, N>
{
fn get(&self, _idx: P0) -> &E {
&self.e
}
}
/// index N+1 into Self given that we know how to index N into Self::next
impl<E, N, P, ElemAtP> IndexOp<LLNode<E, N>, PNext<P>, ElemAtP> for LLNode<E, N>
where
P: Peano,
N: IndexOp<N, P, ElemAtP>
{
fn get(&self, _idx: PNext<P>) -> &ElemAtP {
self.next.get(P::default())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::compound::peano::{P1, P2};
use core::cell::Cell;
#[derive(Default)]
@ -242,6 +278,16 @@ mod test {
assert_eq!(list.apply_at(2, ApplyAtRetOp), V0(5u32).to_flat());
}
#[test]
fn get() {
let list = LLNode::new(3f32)
.prepend(4i32)
.prepend(5u32);
assert_eq!(list.get(P0), &5u32);
assert_eq!(list.get(P1::default()), &4i32);
assert_eq!(list.get(P2::default()), &3f32);
}
#[test]
fn test_list_builder() {
let type_level = List::<(i32, f32, u32)>::default();

View File

@ -1,12 +1,20 @@
#[derive(Default)]
pub struct PNext<P>(P);
#[derive(Default)]
pub struct P0;
pub type P1 = PNext<P0>;
pub type P2 = PNext<P1>;
pub type P3 = PNext<P2>;
pub type P4 = PNext<P3>;
pub type P5 = PNext<P4>;
pub type P6 = PNext<P5>;
pub type P7 = PNext<P6>;
pub trait Peano {
pub trait Peano: Default {
type Next: PeanoNonZero;
}
pub trait PeanoNonZero {
pub trait PeanoNonZero: Peano {
type Prev: Peano;
}