coremem_types: enumerated: allow folding the enum into the first element
This commit is contained in:
@@ -1,13 +1,25 @@
|
||||
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano, PeanoNonZero, PNext};
|
||||
use crate::compound::list::{Indexable, IntoList, List};
|
||||
use crate::compound::list::{self, Indexable, IntoList, List};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
// anything which can encode a discriminant up to *and including* P
|
||||
pub trait DiscriminantCodable<P: Peano> {
|
||||
fn discr(&self) -> Discr<P>;
|
||||
}
|
||||
|
||||
// discriminant which encodes up to *and including* P.
|
||||
pub struct Discr<P: Peano>(u32, PhantomData<P>);
|
||||
#[derive(Copy, Clone, Default, PartialEq)]
|
||||
pub struct Discr<P: Peano>(u32, P::Unit);
|
||||
|
||||
impl<P: Peano> DiscriminantCodable<P> for Discr<P> {
|
||||
fn discr(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Peano> Discr<P> {
|
||||
fn new_unchecked(u: u32) -> Self {
|
||||
Self(u, PhantomData)
|
||||
Self(u, Default::default())
|
||||
}
|
||||
fn dispatch<H: DiscrHandler<P>>(&self, h: H) -> H::Output {
|
||||
match self.0 {
|
||||
@@ -33,59 +45,88 @@ pub trait VariantHandler<N: Peano> {
|
||||
}
|
||||
|
||||
/// helper used to call F with some (yet-to-be-determined) variant of E
|
||||
struct EnumDispatch<'a, E, F> {
|
||||
enum_: &'a E,
|
||||
struct DispatchIndexable<'a, I, F> {
|
||||
indexable: &'a I,
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<'a, E, F> EnumDispatch<'a, E, F> {
|
||||
fn new(enum_: &'a E, f: F) -> Self {
|
||||
Self { enum_, f }
|
||||
impl<'a, I, F> DispatchIndexable<'a, I, F> {
|
||||
fn new(indexable: &'a I, f: F) -> Self {
|
||||
Self { indexable, f }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, L, F> DiscrHandler<P0> for EnumDispatch<'a, Enum<L>, F>
|
||||
impl<'a, I, F> DiscrHandler<P0> for DispatchIndexable<'a, I, F>
|
||||
where
|
||||
L: Indexable<P0>,
|
||||
L::Element: Copy,
|
||||
F: VariantHandler<P0, Args=L::Element>,
|
||||
I: Indexable<P0>,
|
||||
I::Element: Copy,
|
||||
F: VariantHandler<P0, Args=I::Element>,
|
||||
{
|
||||
type Output = F::Output;
|
||||
type PrevOrPanic = Self;
|
||||
fn call(self) -> Self::Output {
|
||||
self.f.call(self.enum_.0.get())
|
||||
self.f.call(self.indexable.get())
|
||||
}
|
||||
fn prev(self) -> Self::PrevOrPanic {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, L, F, P: Peano> DiscrHandler<PNext<P>> for EnumDispatch<'a, Enum<L>, F>
|
||||
impl<'a, I, F, P: Peano> DiscrHandler<PNext<P>> for DispatchIndexable<'a, I, F>
|
||||
where
|
||||
L: Indexable<PNext<P>>,
|
||||
L::Element: Copy,
|
||||
F: VariantHandler<PNext<P>, Args=L::Element, Output=<Self as DiscrHandler<P>>::Output>,
|
||||
I: Indexable<PNext<P>>,
|
||||
I::Element: Copy,
|
||||
F: VariantHandler<PNext<P>, Args=I::Element, Output=<Self as DiscrHandler<P>>::Output>,
|
||||
Self: DiscrHandler<P>,
|
||||
{
|
||||
type Output = F::Output;
|
||||
type PrevOrPanic = Self;
|
||||
fn call(self) -> Self::Output {
|
||||
self.f.call(self.enum_.0.get())
|
||||
self.f.call(self.indexable.get())
|
||||
}
|
||||
fn prev(self) -> Self::PrevOrPanic {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Enum<L>(L);
|
||||
struct Enum<D, L>(D, L);
|
||||
|
||||
trait DiscriminantedEnum<P: Peano>: Sized {
|
||||
fn discr(&self) -> Discr<P>;
|
||||
fn dispatch<'a, F>(&'a self, f: F) -> <EnumDispatch<'a, Self, F> as DiscrHandler<P>>::Output
|
||||
trait EnumRequirements {
|
||||
type MaxDiscr: Peano;
|
||||
fn discr(&self) -> Discr<Self::MaxDiscr>;
|
||||
}
|
||||
|
||||
impl<D, L> EnumRequirements for Enum<(D,), L>
|
||||
where
|
||||
EnumDispatch<'a, Self, F>: DiscrHandler<P>
|
||||
D: DiscriminantCodable<<<L as list::Meta>::Length as PeanoNonZero>::Prev>,
|
||||
L: list::Meta,
|
||||
{
|
||||
self.discr().dispatch(EnumDispatch::new(self, f))
|
||||
type MaxDiscr = <<L as list::Meta>::Length as PeanoNonZero>::Prev;
|
||||
fn discr(&self) -> Discr<Self::MaxDiscr> {
|
||||
self.0.0.discr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> EnumRequirements for Enum<(), L>
|
||||
where
|
||||
L: list::Meta + Indexable<P0>,
|
||||
list::ElementAt<P0, L>: Copy + DiscriminantCodable<<<L as list::Meta>::Length as PeanoNonZero>::Prev>,
|
||||
{
|
||||
type MaxDiscr = <<L as list::Meta>::Length as PeanoNonZero>::Prev;
|
||||
fn discr(&self) -> Discr<Self::MaxDiscr> {
|
||||
self.1.get().discr()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<D, L> Enum<D, L>
|
||||
where Self: EnumRequirements
|
||||
{
|
||||
fn dispatch<'a, F>(&'a self, f: F) -> <DispatchIndexable<'a, L, F> as DiscrHandler<<Self as EnumRequirements>::MaxDiscr>>::Output
|
||||
where
|
||||
DispatchIndexable<'a, L, F>: DiscrHandler<<Self as EnumRequirements>::MaxDiscr>
|
||||
{
|
||||
self.discr().dispatch(DispatchIndexable::new(&self.1, f))
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano};
|
||||
use crate::compound::peano::{LessThan, P0, P1, P2, P3, Peano, PeanoNonZero, PNext};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Serialize, Deserialize};
|
||||
@@ -96,3 +96,16 @@ impl<E0, E1, E2, E3> IntoList for (E0, E1, E2, E3) {
|
||||
Node::new(self.0, (self.1, self.2, self.3).into_list())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Meta {
|
||||
type Length: PeanoNonZero;
|
||||
}
|
||||
|
||||
impl<H> Meta for Node<H, Null> {
|
||||
type Length = P1;
|
||||
}
|
||||
impl<H, T: Meta> Meta for Node<H, T> {
|
||||
type Length = PNext<T::Length>;
|
||||
}
|
||||
|
||||
pub type ElementAt<P, L> = <L as Indexable<P>>::Element;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#[derive(Default)]
|
||||
#[derive(Copy, Clone, Default, PartialEq)]
|
||||
pub struct PNext<P>(P);
|
||||
#[derive(Default)]
|
||||
#[derive(Copy, Clone, Default, PartialEq)]
|
||||
pub struct P0;
|
||||
|
||||
pub type P1 = PNext<P0>;
|
||||
@@ -11,9 +11,12 @@ pub type P5 = PNext<P4>;
|
||||
pub type P6 = PNext<P5>;
|
||||
pub type P7 = PNext<P6>;
|
||||
|
||||
pub trait Peano: Default {
|
||||
pub trait Peano: Copy + Clone + Default + PartialEq {
|
||||
type Next: PeanoNonZero;
|
||||
type PrevOrZero: Peano;
|
||||
/// always set to ()
|
||||
/// this exists to allow Peano numbers to be used as struct parameters without PhantomData
|
||||
type Unit: Copy + Clone + Default + PartialEq;
|
||||
const VALUE: u32;
|
||||
}
|
||||
|
||||
@@ -24,11 +27,13 @@ pub trait PeanoNonZero: Peano {
|
||||
impl Peano for P0 {
|
||||
type Next = P1;
|
||||
type PrevOrZero = P0;
|
||||
type Unit = ();
|
||||
const VALUE: u32 = 0;
|
||||
}
|
||||
impl<P: Peano> Peano for PNext<P> {
|
||||
type Next = PNext<PNext<P>>;
|
||||
type PrevOrZero = P;
|
||||
type Unit = ();
|
||||
const VALUE: u32 = 1 + P::VALUE;
|
||||
}
|
||||
impl<P: Peano> PeanoNonZero for PNext<P> {
|
||||
|
Reference in New Issue
Block a user