coremem_types: implement a list type wherein we can hope to implement enum-like types on gpu

This commit is contained in:
2022-07-20 01:37:33 -07:00
parent 7954d341fc
commit 225d1d7f3a
2 changed files with 142 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
#[derive(Copy, Clone, Default, PartialEq)]
struct Null;
#[derive(Copy, Clone, Default, PartialEq)]
struct LLNode<E, N> {
e: E,
// Null or LLNode
next: N,
}
impl<E> LLNode<E, Null> {
fn new(e: E) -> Self {
Self {
e,
next: Null,
}
}
}
impl<E, N> LLNode<E, N> {
fn prepend<P>(self, e: P) -> LLNode<P, Self> {
LLNode {
e,
next: self
}
}
}
trait ListOp<F, L> {
fn apply(&self, f: F);
}
trait ElemCallable<T> {
fn call(&self, el: &T);
}
impl<F: ElemCallable<E>, E, N: ListOp<F, N>> ListOp<F, LLNode<E, N>> for LLNode<E, N> {
fn apply(&self, f: F) {
f.call(&self.e);
self.next.apply(f)
}
}
impl<F> ListOp<F, Null> for Null {
fn apply(&self, _f: F) { }
}
#[cfg(test)]
mod test {
use super::*;
use core::cell::Cell;
#[derive(Default)]
struct ApplyAccumulator<T> {
delayed0: Cell<T>,
delayed1: Cell<T>,
delayed2: Cell<T>,
}
impl ElemCallable<u32> for &ApplyAccumulator<u32> {
fn call(&self, el: &u32) {
self.delayed2.set(
self.delayed1.replace(
self.delayed0.replace(*el)
)
)
}
}
#[test]
fn test_apply_single() {
let list = LLNode::new(5u32);
let acc = ApplyAccumulator::default();
list.apply(&acc);
assert_eq!(acc.delayed1.into_inner(), 0);
assert_eq!(acc.delayed0.into_inner(), 5);
}
#[derive(Copy, Clone, Default, Debug, PartialEq)]
struct V0(u32);
#[derive(Copy, Clone, Default, Debug, PartialEq)]
struct V1(f32);
#[derive(Copy, Clone, Default, Debug, PartialEq)]
struct Flat {
v0: V0,
v1: V1,
}
trait Variant {
fn to_flat(&self) -> Flat;
}
impl Variant for V0 {
fn to_flat(&self) -> Flat {
Flat { v0: *self, ..Default::default() }
}
}
impl Variant for V1 {
fn to_flat(&self) -> Flat {
Flat { v1: *self, ..Default::default() }
}
}
impl<T: Variant> ElemCallable<T> for &ApplyAccumulator<Flat> {
fn call(&self, el: &T) {
self.delayed2.set(
self.delayed1.replace(
self.delayed0.replace(el.to_flat())
)
)
}
}
#[test]
fn test_apply_2() {
let list = LLNode::new(V0(5u32))
.prepend(V1(4f32));
let acc = ApplyAccumulator::default();
list.apply(&acc);
assert_eq!(acc.delayed2.into_inner(), Flat::default());
assert_eq!(acc.delayed1.into_inner(), V1(4f32).to_flat());
assert_eq!(acc.delayed0.into_inner(), V0(5u32).to_flat());
}
#[test]
fn test_apply_3() {
let list = LLNode::new(V0(5u32))
.prepend(V1(4f32))
.prepend(V0(2u32));
let acc = ApplyAccumulator::default();
list.apply(&acc);
assert_eq!(acc.delayed2.into_inner(), V0(2u32).to_flat());
assert_eq!(acc.delayed1.into_inner(), V1(4f32).to_flat());
assert_eq!(acc.delayed0.into_inner(), V0(5u32).to_flat());
}
}

View File

@@ -1,6 +1,7 @@
#![no_std] #![no_std]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
mod compound;
pub mod mat; pub mod mat;
pub mod real; pub mod real;
pub mod vec; pub mod vec;