From 858e787c19a905e17c68c60589aeb03da533be48 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 12 Aug 2022 18:03:10 -0700 Subject: [PATCH] driver: allow preserving the Stimuli as a concrete List --- crates/coremem/src/driver.rs | 36 ++++++++++++++++++--- crates/cross/src/compound/list/flat.rs | 44 ++++++++++++++++++++++---- crates/cross/src/compound/list/mod.rs | 29 ++++++++++------- 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/crates/coremem/src/driver.rs b/crates/coremem/src/driver.rs index cec771d..eda61ed 100644 --- a/crates/coremem/src/driver.rs +++ b/crates/coremem/src/driver.rs @@ -7,6 +7,7 @@ use crate::render::{self, MultiRenderer, Renderer}; use crate::sim::AbstractSim; use crate::sim::units::{Frame, Time}; use crate::stim::AbstractStimulus; +use coremem_cross::compound::list; use log::{info, trace}; use serde::{Deserialize, Serialize}; @@ -33,8 +34,8 @@ pub struct Driver { /// generic stimuli collection which monomorphizes everything by boxing it. pub type DynStimuli = Vec>; -impl Driver { - pub fn new(mut state: S) -> Self { +impl Driver { + pub fn new_with_stim(mut state: S, stimuli: Stim) -> Self { let diag = SyncDiagnostics::new(); state.use_diagnostics(diag.clone()); Self { @@ -48,7 +49,7 @@ impl Driver { Arc::new(meas::Energy::world()), Arc::new(meas::Power::world()), ], - stimuli: Default::default(), + stimuli, sim_end_time: None, diag, last_diag_time: Instant::now(), @@ -60,12 +61,39 @@ impl Driver { } } -impl Driver { +impl Driver { + pub fn new(state: S) -> Self { + Self::new_with_stim(state, DynStimuli::default()) + } pub fn add_stimulus(&mut self, s: Stim) { self.stimuli.push(Box::new(s)) } } +impl Driver { + pub fn new_unboxed_stim(state: S) -> Self { + Self::new_with_stim(state, list::Empty::default()) + } +} + +impl Driver { + pub fn with_stimulus(self, s: E) -> Driver + where Stim: list::Prependable + { + 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 Driver { pub fn fill_region + Clone>(&mut self, region: &Reg, mat: M) { self.state.fill_region(region, mat); diff --git a/crates/cross/src/compound/list/flat.rs b/crates/cross/src/compound/list/flat.rs index 3b5d7a9..f7a1cea 100644 --- a/crates/cross/src/compound/list/flat.rs +++ b/crates/cross/src/compound/list/flat.rs @@ -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}; #[cfg(feature = "serde")] @@ -94,10 +94,22 @@ impl Indexable for Node } } -impl IntoList for (E0,) { - type List = Node; +pub trait IntoList { + type List; + fn into_list(self) -> Self::List; +} + +impl IntoList for () { + type List = Null; fn into_list(self) -> Self::List { - Node::new(self.0, Null) + Null + } +} + +impl IntoList for (E0,) { + type List = Node::List>; + fn into_list(self) -> Self::List { + Node::new(self.0, ().into_list()) } } @@ -122,9 +134,27 @@ impl IntoList for (E0, E1, E2, E3) { } } -pub trait IntoList { - type List; - fn into_list(self) -> Self::List; +pub trait Prependable { + type Result; + fn prepend(self, e: E) -> Self::Result; +} + +impl Prependable for Null { + type Result = Node; + fn prepend(self, e: E) -> Self::Result { + Node::new(e, self) + } +} + +impl Prependable for Node { + type Result = Node>; + fn prepend(self, e: E) -> Self::Result { + Node::new(e, self) + } +} + +impl MaybeMeta for Null { + type Length = P0; } impl Meta for Node { diff --git a/crates/cross/src/compound/list/mod.rs b/crates/cross/src/compound/list/mod.rs index 3cee261..347e1ef 100644 --- a/crates/cross/src/compound/list/mod.rs +++ b/crates/cross/src/compound/list/mod.rs @@ -5,9 +5,11 @@ mod flat; // mod tuple_consumer; // pub use tuple_consumer::*; // pub use linked::*; -pub use flat::IntoList; +pub use flat::{IntoList, Prependable}; pub use flat::exports::*; +pub type Empty = flat::Null; + /// something which can be indexed at `P`. /// a List of length N is expected to implement `Indexable

` for all `P < N`. pub trait Indexable { @@ -26,6 +28,15 @@ pub trait Meta { type Length: PeanoNonZero; } +/// implemented by any List, or Null (empty list) +pub trait MaybeMeta { + type Length: Peano; +} + +impl 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. pub trait Visitor { fn visit(&mut self, a: &Arg); @@ -45,25 +56,21 @@ where } /// 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 { fn visit_partial(&mut self, l: &L); } impl PartialListVisitor for V -where - L: Indexable, - V: Visitor, { - fn visit_partial(&mut self, l: &L) { - self.visit(l.get_ref()) + fn visit_partial(&mut self, _unused_basecase: &L) { } } impl PartialListVisitor> for V where - L: Indexable>, - V: PartialListVisitor + Visitor, L::Element>, + L: Indexable

, + V: PartialListVisitor + Visitor, { fn visit_partial(&mut self, l: &L) { PartialListVisitor::::visit_partial(self, l); @@ -72,12 +79,12 @@ where } /// marker trait for a type which can visit every element in the list `L`. -pub trait ListVisitor: PartialListVisitor::Length as PeanoNonZero>::Prev> {} +pub trait ListVisitor: PartialListVisitor::Length> {} /// user-facing API to visit a list pub fn visit(l: &L, v: &mut V) where - L: Meta, + L: MaybeMeta, V: ListVisitor, { v.visit_partial(l)