driver: allow preserving the Stimuli as a concrete List
This commit is contained in:
@@ -7,6 +7,7 @@ use crate::render::{self, MultiRenderer, Renderer};
|
|||||||
use crate::sim::AbstractSim;
|
use crate::sim::AbstractSim;
|
||||||
use crate::sim::units::{Frame, Time};
|
use crate::sim::units::{Frame, Time};
|
||||||
use crate::stim::AbstractStimulus;
|
use crate::stim::AbstractStimulus;
|
||||||
|
use coremem_cross::compound::list;
|
||||||
|
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -33,8 +34,8 @@ pub struct Driver<S, Stim=DynStimuli> {
|
|||||||
/// generic stimuli collection which monomorphizes everything by boxing it.
|
/// generic stimuli collection which monomorphizes everything by boxing it.
|
||||||
pub type DynStimuli = Vec<Box<dyn AbstractStimulus>>;
|
pub type DynStimuli = Vec<Box<dyn AbstractStimulus>>;
|
||||||
|
|
||||||
impl<S: AbstractSim, Stim: Default> Driver<S, Stim> {
|
impl<S: AbstractSim, Stim> Driver<S, Stim> {
|
||||||
pub fn new(mut state: S) -> Self {
|
pub fn new_with_stim(mut state: S, stimuli: Stim) -> Self {
|
||||||
let diag = SyncDiagnostics::new();
|
let diag = SyncDiagnostics::new();
|
||||||
state.use_diagnostics(diag.clone());
|
state.use_diagnostics(diag.clone());
|
||||||
Self {
|
Self {
|
||||||
@@ -48,7 +49,7 @@ impl<S: AbstractSim, Stim: Default> Driver<S, Stim> {
|
|||||||
Arc::new(meas::Energy::world()),
|
Arc::new(meas::Energy::world()),
|
||||||
Arc::new(meas::Power::world()),
|
Arc::new(meas::Power::world()),
|
||||||
],
|
],
|
||||||
stimuli: Default::default(),
|
stimuli,
|
||||||
sim_end_time: None,
|
sim_end_time: None,
|
||||||
diag,
|
diag,
|
||||||
last_diag_time: Instant::now(),
|
last_diag_time: Instant::now(),
|
||||||
@@ -60,12 +61,39 @@ impl<S: AbstractSim, Stim: Default> Driver<S, Stim> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Driver<S, DynStimuli> {
|
impl<S: AbstractSim> Driver<S, DynStimuli> {
|
||||||
|
pub fn new(state: S) -> Self {
|
||||||
|
Self::new_with_stim(state, DynStimuli::default())
|
||||||
|
}
|
||||||
pub fn add_stimulus<Stim: AbstractStimulus + 'static>(&mut self, s: Stim) {
|
pub fn add_stimulus<Stim: AbstractStimulus + 'static>(&mut self, s: Stim) {
|
||||||
self.stimuli.push(Box::new(s))
|
self.stimuli.push(Box::new(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S: AbstractSim> Driver<S, list::Empty> {
|
||||||
|
pub fn new_unboxed_stim(state: S) -> Self {
|
||||||
|
Self::new_with_stim(state, list::Empty::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: AbstractSim, Stim> Driver<S, Stim> {
|
||||||
|
pub fn with_stimulus<E>(self, s: E) -> Driver<S, Stim::Result>
|
||||||
|
where Stim: list::Prependable<E>
|
||||||
|
{
|
||||||
|
Driver {
|
||||||
|
state: self.state,
|
||||||
|
renderer: self.renderer,
|
||||||
|
render_pool: self.render_pool,
|
||||||
|
render_channel: self.render_channel,
|
||||||
|
measurements: self.measurements,
|
||||||
|
stimuli: self.stimuli.prepend(s),
|
||||||
|
sim_end_time: self.sim_end_time,
|
||||||
|
diag: self.diag,
|
||||||
|
last_diag_time: self.last_diag_time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: AbstractSim, Stim> Driver<S, Stim> {
|
impl<S: AbstractSim, Stim> Driver<S, Stim> {
|
||||||
pub fn fill_region<Reg: Region, M: Into<S::Material> + Clone>(&mut self, region: &Reg, mat: M) {
|
pub fn fill_region<Reg: Region, M: Into<S::Material> + Clone>(&mut self, region: &Reg, mat: M) {
|
||||||
self.state.fill_region(region, mat);
|
self.state.fill_region(region, mat);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
use crate::compound::list::{Indexable, Meta};
|
use crate::compound::list::{Indexable, MaybeMeta, Meta};
|
||||||
use crate::compound::peano::{P0, P1, P2, P3, Peano, PNext};
|
use crate::compound::peano::{P0, P1, P2, P3, Peano, PNext};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@@ -94,10 +94,22 @@ impl<E0, E1, E2, E3, T> Indexable<P3> for Node<E0, Node<E1, Node<E2, Node<E3, T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E0> IntoList for (E0,) {
|
pub trait IntoList {
|
||||||
type List = Node<E0, Null>;
|
type List;
|
||||||
|
fn into_list(self) -> Self::List;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoList for () {
|
||||||
|
type List = Null;
|
||||||
fn into_list(self) -> Self::List {
|
fn into_list(self) -> Self::List {
|
||||||
Node::new(self.0, Null)
|
Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E0> IntoList for (E0,) {
|
||||||
|
type List = Node<E0, <() as IntoList>::List>;
|
||||||
|
fn into_list(self) -> Self::List {
|
||||||
|
Node::new(self.0, ().into_list())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,9 +134,27 @@ impl<E0, E1, E2, E3> IntoList for (E0, E1, E2, E3) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoList {
|
pub trait Prependable<E> {
|
||||||
type List;
|
type Result;
|
||||||
fn into_list(self) -> Self::List;
|
fn prepend(self, e: E) -> Self::Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> Prependable<E> for Null {
|
||||||
|
type Result = Node<E, Null>;
|
||||||
|
fn prepend(self, e: E) -> Self::Result {
|
||||||
|
Node::new(e, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E, H, T> Prependable<E> for Node<H, T> {
|
||||||
|
type Result = Node<E, Node<H, T>>;
|
||||||
|
fn prepend(self, e: E) -> Self::Result {
|
||||||
|
Node::new(e, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaybeMeta for Null {
|
||||||
|
type Length = P0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H> Meta for Node<H, Null> {
|
impl<H> Meta for Node<H, Null> {
|
||||||
|
@@ -5,9 +5,11 @@ mod flat;
|
|||||||
// mod tuple_consumer;
|
// mod tuple_consumer;
|
||||||
// pub use tuple_consumer::*;
|
// pub use tuple_consumer::*;
|
||||||
// pub use linked::*;
|
// pub use linked::*;
|
||||||
pub use flat::IntoList;
|
pub use flat::{IntoList, Prependable};
|
||||||
pub use flat::exports::*;
|
pub use flat::exports::*;
|
||||||
|
|
||||||
|
pub type Empty = flat::Null;
|
||||||
|
|
||||||
/// something which can be indexed at `P`.
|
/// something which can be indexed at `P`.
|
||||||
/// a List of length N is expected to implement `Indexable<P>` for all `P < N`.
|
/// a List of length N is expected to implement `Indexable<P>` for all `P < N`.
|
||||||
pub trait Indexable<P: Peano> {
|
pub trait Indexable<P: Peano> {
|
||||||
@@ -26,6 +28,15 @@ pub trait Meta {
|
|||||||
type Length: PeanoNonZero;
|
type Length: PeanoNonZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// implemented by any List, or Null (empty list)
|
||||||
|
pub trait MaybeMeta {
|
||||||
|
type Length: Peano;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: Meta> MaybeMeta for M {
|
||||||
|
type Length = M::Length;
|
||||||
|
}
|
||||||
|
|
||||||
/// implement on your own type for all `N` of a given list if you want to be able to walk the list.
|
/// implement on your own type for all `N` of a given list if you want to be able to walk the list.
|
||||||
pub trait Visitor<N: Peano, Arg> {
|
pub trait Visitor<N: Peano, Arg> {
|
||||||
fn visit(&mut self, a: &Arg);
|
fn visit(&mut self, a: &Arg);
|
||||||
@@ -45,25 +56,21 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// used internally to simplify trait bounds.
|
/// used internally to simplify trait bounds.
|
||||||
/// visits every element in the list at index `P` and less.
|
/// visits every element in the list at index less than `P`.
|
||||||
pub trait PartialListVisitor<L, P> {
|
pub trait PartialListVisitor<L, P> {
|
||||||
fn visit_partial(&mut self, l: &L);
|
fn visit_partial(&mut self, l: &L);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, V> PartialListVisitor<L, P0> for V
|
impl<L, V> PartialListVisitor<L, P0> for V
|
||||||
where
|
|
||||||
L: Indexable<P0>,
|
|
||||||
V: Visitor<P0, L::Element>,
|
|
||||||
{
|
{
|
||||||
fn visit_partial(&mut self, l: &L) {
|
fn visit_partial(&mut self, _unused_basecase: &L) {
|
||||||
self.visit(l.get_ref())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, V, P: Peano> PartialListVisitor<L, PNext<P>> for V
|
impl<L, V, P: Peano> PartialListVisitor<L, PNext<P>> for V
|
||||||
where
|
where
|
||||||
L: Indexable<PNext<P>>,
|
L: Indexable<P>,
|
||||||
V: PartialListVisitor<L, P> + Visitor<PNext<P>, L::Element>,
|
V: PartialListVisitor<L, P> + Visitor<P, L::Element>,
|
||||||
{
|
{
|
||||||
fn visit_partial(&mut self, l: &L) {
|
fn visit_partial(&mut self, l: &L) {
|
||||||
PartialListVisitor::<L, P>::visit_partial(self, l);
|
PartialListVisitor::<L, P>::visit_partial(self, l);
|
||||||
@@ -72,12 +79,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// marker trait for a type which can visit every element in the list `L`.
|
/// marker trait for a type which can visit every element in the list `L`.
|
||||||
pub trait ListVisitor<L: Meta>: PartialListVisitor<L, <<L as Meta>::Length as PeanoNonZero>::Prev> {}
|
pub trait ListVisitor<L: MaybeMeta>: PartialListVisitor<L, <L as MaybeMeta>::Length> {}
|
||||||
|
|
||||||
/// user-facing API to visit a list
|
/// user-facing API to visit a list
|
||||||
pub fn visit<L, V>(l: &L, v: &mut V)
|
pub fn visit<L, V>(l: &L, v: &mut V)
|
||||||
where
|
where
|
||||||
L: Meta,
|
L: MaybeMeta,
|
||||||
V: ListVisitor<L>,
|
V: ListVisitor<L>,
|
||||||
{
|
{
|
||||||
v.visit_partial(l)
|
v.visit_partial(l)
|
||||||
|
Reference in New Issue
Block a user