use std::rc::Rc;
use std::marker::PhantomData;
use crate::simulation;
use crate::simulation::Run;
use crate::simulation::Point;
use crate::simulation::error::*;
use crate::simulation::simulation::*;
use crate::simulation::event::Event;
use crate::simulation::process::*;
use crate::simulation::observable::disposable::*;
use crate::simulation::composite::*;
use dvcompute_utils::grc::Grc;
pub mod random;
pub mod ops;
#[inline]
pub fn return_parameter<T>(val: T) -> Return<T> {
Return { val: val }
}
#[inline]
pub fn panic_parameter<T>(msg: String) -> Panic<T> {
Panic { msg: msg, _phantom: PhantomData }
}
#[inline]
pub fn delay_parameter<F, M>(f: F) -> Delay<F, M>
where F: FnOnce() -> M,
M: Parameter
{
Delay { f: f, _phantom: PhantomData }
}
#[inline]
pub fn cons_parameter<F, T>(f: F) -> Cons<F, T>
where F: FnOnce(&Run) -> simulation::Result<T>
{
Cons { f: f, _phantom: PhantomData }
}
#[inline]
pub fn parameter_sequence<I, M>(comps: I) -> Sequence<I::IntoIter, M>
where I: IntoIterator<Item = M>,
M: Parameter
{
Sequence { comps: comps.into_iter(), _phantom: PhantomData }
}
#[inline]
pub fn parameter_sequence_<I, M>(comps: I) -> Sequence_<I::IntoIter, M>
where I: IntoIterator<Item = M>,
M: Parameter
{
Sequence_ { comps: comps.into_iter(), _phantom: PhantomData }
}
#[inline]
pub fn simulation_index() -> SimulationIndex {
SimulationIndex {}
}
pub trait Parameter {
type Item;
#[doc(hidden)]
fn call_parameter(self, r: &Run) -> simulation::Result<Self::Item>;
#[inline]
fn into_simulation(self) -> ParameterIntoSimulation<Self>
where Self: Sized
{
ParameterIntoSimulation { comp: self }
}
#[inline]
fn into_event(self) -> ParameterIntoEvent<Self>
where Self: Sized
{
ParameterIntoEvent { comp: self }
}
#[inline]
fn into_process(self) -> ParameterIntoProcess<Self>
where Self: Sized
{
ParameterIntoProcess { comp: self }
}
#[inline]
fn into_composite(self) -> ParameterIntoComposite<Self>
where Self: Sized
{
ParameterIntoComposite { comp: self }
}
#[inline]
fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
where Self: Sized,
U: Parameter,
F: FnOnce(Self::Item) -> U,
{
AndThen { comp: self, f: f, _phantom: PhantomData }
}
#[inline]
fn map<B, F>(self, f: F) -> Map<Self, B, F>
where Self: Sized,
F: FnOnce(Self::Item) -> B,
{
Map { comp: self, f: f, _phantom: PhantomData }
}
#[inline]
fn zip<U>(self, other: U) -> Zip<Self, U>
where Self: Sized,
U: Parameter
{
Zip { comp: self, other: other }
}
#[inline]
fn ap<U, B>(self, other: U) -> Ap<Self, U, B>
where Self: Sized,
Self::Item: FnOnce(U::Item) -> B,
U: Parameter
{
Ap { comp: self, other: other, _phantom: PhantomData }
}
#[inline]
fn into_boxed(self) -> ParameterBox<Self::Item>
where Self: Sized + 'static
{
ParameterBox::new(move |r: &Run| { self.call_parameter(r) })
}
}
pub trait IntoParameter {
type Parameter: Parameter<Item = Self::Item>;
type Item;
fn into_parameter(self) -> Self::Parameter;
}
impl<M: Parameter> IntoParameter for M {
type Parameter = M;
type Item = M::Item;
#[inline]
fn into_parameter(self) -> Self::Parameter {
self
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct ParameterBox<T> {
f: Box<dyn ParameterFnBox<T>>
}
impl<T> ParameterBox<T> {
#[doc(hidden)]
#[inline]
fn new<F>(f: F) -> Self
where F: FnOnce(&Run) -> simulation::Result<T> + 'static
{
ParameterBox {
f: Box::new(f)
}
}
#[doc(hidden)]
#[inline]
pub fn call_box(self, arg: (&Run,)) -> simulation::Result<T> {
let ParameterBox { f } = self;
f.call_box(arg)
}
}
impl<T> Parameter for ParameterBox<T> {
type Item = T;
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<Self::Item> {
self.call_box((r,))
}
#[inline]
fn into_boxed(self) -> ParameterBox<Self::Item>
where Self: Sized + 'static
{
self
}
}
trait ParameterFnBox<T> {
fn call_box(self: Box<Self>, args: (&Run,)) -> simulation::Result<T>;
}
impl<T, F> ParameterFnBox<T> for F
where F: for<'a> FnOnce(&'a Run) -> simulation::Result<T>
{
fn call_box(self: Box<Self>, args: (&Run,)) -> simulation::Result<T> {
let this: Self = *self;
this(args.0)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Return<T> {
val: T
}
impl<T> Parameter for Return<T> {
type Item = T;
#[doc(hidden)]
#[inline]
fn call_parameter(self, _: &Run) -> simulation::Result<T> {
let Return { val } = self;
Result::Ok(val)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Delay<F, M> {
f: F,
_phantom: PhantomData<M>
}
impl<F, M> Parameter for Delay<F, M>
where F: FnOnce() -> M,
M: Parameter
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<M::Item> {
let Delay { f, _phantom } = self;
f().call_parameter(r)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Cons<F, T> {
f: F,
_phantom: PhantomData<T>
}
impl<F, T> Parameter for Cons<F, T>
where F: FnOnce(&Run) -> simulation::Result<T>
{
type Item = T;
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<T> {
let Cons { f, _phantom } = self;
f(r)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct ParameterIntoSimulation<M> {
comp: M
}
impl<M> Simulation for ParameterIntoSimulation<M>
where M: Parameter
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_simulation(self, r: &Run) -> simulation::Result<M::Item> {
let ParameterIntoSimulation { comp } = self;
comp.call_parameter(r)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct ParameterIntoEvent<M> {
comp: M
}
impl<M> Event for ParameterIntoEvent<M>
where M: Parameter
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_event(self, p: &Point) -> simulation::Result<M::Item> {
let ParameterIntoEvent { comp } = self;
comp.call_parameter(p.run)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct ParameterIntoComposite<M> {
comp: M
}
impl<M> Composite for ParameterIntoComposite<M>
where M: Parameter
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(M::Item, DisposableBox)> {
let ParameterIntoComposite { comp } = self;
let a = comp.call_parameter(p.run)?;
Result::Ok((a, disposable))
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct AndThen<M, U, F> {
comp: M,
f: F,
_phantom: PhantomData<U>
}
impl<M, U, F> Parameter for AndThen<M, U, F>
where M: Parameter,
U: Parameter,
F: FnOnce(M::Item) -> U
{
type Item = U::Item;
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<U::Item> {
let AndThen { comp, f, _phantom } = self;
match comp.call_parameter(r) {
Result::Ok(a) => {
let m = f(a);
m.call_parameter(r)
},
Result::Err(e) => {
Result::Err(e)
}
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Map<M, B, F> {
comp: M,
f: F,
_phantom: PhantomData<B>
}
impl<M, B, F> Parameter for Map<M, B, F>
where M: Parameter,
F: FnOnce(M::Item) -> B
{
type Item = B;
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<B> {
let Map { comp, f, _phantom } = self;
match comp.call_parameter(r) {
Result::Ok(a) => Result::Ok(f(a)),
Result::Err(e) => Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Zip<M, U> {
comp: M,
other: U,
}
impl<M, U> Parameter for Zip<M, U>
where M: Parameter,
U: Parameter
{
type Item = (M::Item, U::Item);
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<(M::Item, U::Item)> {
let Zip { comp, other } = self;
comp.and_then(move |a| {
other.map(move |b| (a, b))
}).call_parameter(r)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Ap<M, U, B> {
comp: M,
other: U,
_phantom: PhantomData<B>
}
impl<M, U, B> Parameter for Ap<M, U, B>
where M: Parameter,
U: Parameter,
M::Item: FnOnce(U::Item) -> B
{
type Item = B;
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<B> {
let Ap { comp, other, _phantom } = self;
comp.and_then(move |f| {
other.map(move |a| { f(a) })
}).call_parameter(r)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct ParameterIntoProcess<M> {
comp: M
}
impl<M> Process for ParameterIntoProcess<M>
where M: Parameter
{
type Item = M::Item;
#[doc(hidden)]
#[inline]
fn call_process<C>(self, cont: C, pid: Grc<ProcessId>, p: &Point) -> simulation::Result<()>
where C: FnOnce(simulation::Result<Self::Item>, Grc<ProcessId>, &Point) -> simulation::Result<()> + 'static
{
if is_process_cancelled(&pid, p) {
revoke_process(cont, pid, p)
} else {
let ParameterIntoProcess { comp } = self;
let t = comp.call_parameter(p.run);
cont(t, pid, p)
}
}
#[doc(hidden)]
#[inline]
fn call_process_boxed(self, cont: ProcessBoxCont<Self::Item>, pid: Grc<ProcessId>, p: &Point) -> simulation::Result<()> {
if is_process_cancelled(&pid, p) {
revoke_process_boxed(cont, pid, p)
} else {
let ParameterIntoProcess { comp } = self;
let t = comp.call_parameter(p.run);
cont.call_box((t, pid, p))
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Sequence<I, M> {
comps: I,
_phantom: PhantomData<M>
}
impl<I, M> Parameter for Sequence<I, M>
where I: Iterator<Item = M>,
M: Parameter
{
type Item = Vec<M::Item>;
#[doc(hidden)]
fn call_parameter(self, r: &Run) -> simulation::Result<Self::Item> {
let Sequence { comps, _phantom } = self;
let mut v = {
match comps.size_hint() {
(_, Some(n)) => Vec::with_capacity(n),
(_, None) => Vec::new()
}
};
for m in comps {
match m.call_parameter(r) {
Result::Ok(a) => {
v.push(a)
},
Result::Err(e) => {
return Result::Err(e)
}
}
}
Result::Ok(v)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Sequence_<I, M> {
comps: I,
_phantom: PhantomData<M>
}
impl<I, M> Parameter for Sequence_<I, M>
where I: Iterator<Item = M>,
M: Parameter
{
type Item = ();
#[doc(hidden)]
fn call_parameter(self, r: &Run) -> simulation::Result<Self::Item> {
let Sequence_ { comps, _phantom } = self;
for m in comps {
match m.call_parameter(r) {
Result::Ok(_) => (),
Result::Err(e) => return Result::Err(e)
}
}
Result::Ok(())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct SimulationIndex {}
impl Parameter for SimulationIndex {
type Item = usize;
#[doc(hidden)]
#[inline]
fn call_parameter(self, r: &Run) -> simulation::Result<Self::Item> {
Result::Ok(r.run_index)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Panic<T> {
msg: String,
_phantom: PhantomData<T>
}
impl<T> Parameter for Panic<T> {
type Item = T;
#[doc(hidden)]
#[inline]
fn call_parameter(self, _r: &Run) -> simulation::Result<Self::Item> {
let Panic { msg, _phantom } = self;
let err = Rc::new(OtherError::Panic(msg));
let err = Error::Other(err);
Result::Err(err)
}
}