From 3a235fe47e3dfbde9bfa1a28ea3fa392b1ce51f0 Mon Sep 17 00:00:00 2001 From: colin Date: Wed, 20 Jul 2022 03:49:39 -0700 Subject: [PATCH] coremem_types: list: allow Peano-based index operation --- crates/types/src/compound/list.rs | 48 +++++++++++++++++++++++++++++- crates/types/src/compound/peano.rs | 12 ++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/crates/types/src/compound/list.rs b/crates/types/src/compound/list.rs index 9b73115..13d26f6 100644 --- a/crates/types/src/compound/list.rs +++ b/crates/types/src/compound/list.rs @@ -1,3 +1,5 @@ +use crate::compound::peano::{P0, Peano, PNext}; + #[derive(Copy, Clone, Default, PartialEq)] struct Null; @@ -77,6 +79,13 @@ trait ElementOp { fn call(&self, el: &T) -> Self::Output; } +impl R> ElementOp for F { + type Output = R; + fn call(&self, el: &T) -> Self::Output { + (self)(el) + } +} + impl ListOp, Output> for LLNode where F: ElementOp, @@ -101,15 +110,42 @@ impl ListOp 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 { + fn get(&self, idx: Index) -> &Elem; +} + +/// zero-index into Self +impl IndexOp, P0, E> for LLNode +{ + 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 IndexOp, PNext

, ElemAtP> for LLNode +where + P: Peano, + N: IndexOp +{ + fn get(&self, _idx: PNext

) -> &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(); diff --git a/crates/types/src/compound/peano.rs b/crates/types/src/compound/peano.rs index d3825e4..79683e8 100644 --- a/crates/types/src/compound/peano.rs +++ b/crates/types/src/compound/peano.rs @@ -1,12 +1,20 @@ +#[derive(Default)] pub struct PNext

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