Eager and Fast FeedbackTuple Implementations (#144)
* Introduce eager and fast feedback_or! implementations (issue #135) * rename FeedbackTuple to CombinedFeedback (as it is a struct not tuple) and add fast/eager AND
This commit is contained in:
parent
42997dbde9
commit
156ed08905
@ -108,26 +108,54 @@ where
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compose [`Feedback`]`s` with an `AND` operation
|
pub struct CombinedFeedback<A, B, I, S, FL>
|
||||||
pub struct AndFeedback<A, B, I, S>
|
|
||||||
where
|
where
|
||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
|
FL: FeedbackLogic<A, B, I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// The first [`Feedback`] to `AND`.
|
|
||||||
pub first: A,
|
pub first: A,
|
||||||
/// The second [`Feedback`] to `AND`.
|
|
||||||
pub second: B,
|
pub second: B,
|
||||||
/// The name
|
|
||||||
name: String,
|
name: String,
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S, FL)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, I, S> Feedback<I, S> for AndFeedback<A, B, I, S>
|
impl<A, B, I, S, FL> Named for CombinedFeedback<A, B, I, S, FL>
|
||||||
where
|
where
|
||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
|
FL: FeedbackLogic<A, B, I, S>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
self.name.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, B, I, S, FL> CombinedFeedback<A, B, I, S, FL>
|
||||||
|
where
|
||||||
|
A: Feedback<I, S>,
|
||||||
|
B: Feedback<I, S>,
|
||||||
|
FL: FeedbackLogic<A, B, I, S>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub fn new(first: A, second: B) -> Self {
|
||||||
|
let name = format!("{} ({},{})", FL::name(), first.name(), second.name());
|
||||||
|
Self {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
name,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, B, I, S, FL> Feedback<I, S> for CombinedFeedback<A, B, I, S, FL>
|
||||||
|
where
|
||||||
|
A: Feedback<I, S>,
|
||||||
|
B: Feedback<I, S>,
|
||||||
|
FL: FeedbackLogic<A, B, I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
@ -142,14 +170,15 @@ where
|
|||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let a = self
|
FL::is_pair_interesting(
|
||||||
.first
|
&mut self.first,
|
||||||
.is_interesting(state, manager, input, observers, exit_kind)?;
|
&mut self.second,
|
||||||
let b = a
|
state,
|
||||||
&& self
|
manager,
|
||||||
.second
|
input,
|
||||||
.is_interesting(state, manager, input, observers, exit_kind)?;
|
observers,
|
||||||
Ok(b)
|
exit_kind,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
@ -167,27 +196,17 @@ where
|
|||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
FL::is_pair_interesting_with_perf(
|
||||||
let a = self.first.is_interesting_with_perf(
|
&mut self.first,
|
||||||
|
&mut self.second,
|
||||||
state,
|
state,
|
||||||
manager,
|
manager,
|
||||||
input,
|
input,
|
||||||
observers,
|
observers,
|
||||||
&exit_kind,
|
exit_kind,
|
||||||
feedback_stats,
|
feedback_stats,
|
||||||
feedback_index,
|
feedback_index,
|
||||||
)?;
|
)
|
||||||
let b = a
|
|
||||||
&& self.second.is_interesting_with_perf(
|
|
||||||
state,
|
|
||||||
manager,
|
|
||||||
input,
|
|
||||||
observers,
|
|
||||||
&exit_kind,
|
|
||||||
feedback_stats,
|
|
||||||
feedback_index + 1,
|
|
||||||
)?;
|
|
||||||
Ok(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -203,60 +222,62 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, I, S> Named for AndFeedback<A, B, I, S>
|
pub trait FeedbackLogic<A, B, I, S>: 'static
|
||||||
where
|
where
|
||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
#[inline]
|
fn name() -> &'static str;
|
||||||
fn name(&self) -> &str {
|
|
||||||
&self.name
|
fn is_pair_interesting<EM, OT>(
|
||||||
}
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple;
|
||||||
|
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
fn is_pair_interesting_with_perf<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
feedback_stats: &mut [u64; NUM_FEEDBACKS],
|
||||||
|
feedback_index: usize,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, I, S> AndFeedback<A, B, I, S>
|
pub struct LogicEagerOr {}
|
||||||
where
|
pub struct LogicFastOr {}
|
||||||
A: Feedback<I, S>,
|
pub struct LogicEagerAnd {}
|
||||||
B: Feedback<I, S>,
|
pub struct LogicFastAnd {}
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
/// Creates a new [`AndFeedback`], resulting in the `AND` of two feedbacks.
|
|
||||||
pub fn new(first: A, second: B) -> Self {
|
|
||||||
let name = format!("And({}, {})", first.name(), second.name());
|
|
||||||
Self {
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
name,
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compose feedbacks with an OR operation
|
impl<A, B, I, S> FeedbackLogic<A, B, I, S> for LogicEagerOr
|
||||||
pub struct OrFeedback<A, B, I, S>
|
|
||||||
where
|
where
|
||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// The first [`Feedback`]
|
fn name() -> &'static str {
|
||||||
pub first: A,
|
"Eager OR"
|
||||||
/// The second [`Feedback`], `OR`ed with the first.
|
}
|
||||||
pub second: B,
|
|
||||||
/// The name
|
|
||||||
name: String,
|
|
||||||
phantom: PhantomData<(I, S)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A, B, I, S> Feedback<I, S> for OrFeedback<A, B, I, S>
|
fn is_pair_interesting<EM, OT>(
|
||||||
where
|
first: &mut A,
|
||||||
A: Feedback<I, S>,
|
second: &mut B,
|
||||||
B: Feedback<I, S>,
|
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
fn is_interesting<EM, OT>(
|
|
||||||
&mut self,
|
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
@ -267,19 +288,15 @@ where
|
|||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let a = self
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
.first
|
let b = second.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
.is_interesting(state, manager, input, observers, exit_kind)?;
|
Ok(a || b)
|
||||||
let b = a
|
|
||||||
|| self
|
|
||||||
.second
|
|
||||||
.is_interesting(state, manager, input, observers, exit_kind)?;
|
|
||||||
Ok(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
fn is_interesting_with_perf<EM, OT>(
|
fn is_pair_interesting_with_perf<EM, OT>(
|
||||||
&mut self,
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
@ -293,7 +310,7 @@ where
|
|||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = self.first.is_interesting_with_perf(
|
let a = first.is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
manager,
|
manager,
|
||||||
input,
|
input,
|
||||||
@ -302,8 +319,8 @@ where
|
|||||||
feedback_stats,
|
feedback_stats,
|
||||||
feedback_index,
|
feedback_index,
|
||||||
)?;
|
)?;
|
||||||
let b = a
|
|
||||||
|| self.second.is_interesting_with_perf(
|
let b = second.is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
manager,
|
manager,
|
||||||
input,
|
input,
|
||||||
@ -312,52 +329,244 @@ where
|
|||||||
feedback_stats,
|
feedback_stats,
|
||||||
feedback_index + 1,
|
feedback_index + 1,
|
||||||
)?;
|
)?;
|
||||||
Ok(b)
|
Ok(a || b)
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_metadata(&mut self, state: &mut S, testcase: &mut Testcase<I>) -> Result<(), Error> {
|
|
||||||
self.first.append_metadata(state, testcase)?;
|
|
||||||
self.second.append_metadata(state, testcase)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
|
||||||
self.first.discard_metadata(state, input)?;
|
|
||||||
self.second.discard_metadata(state, input)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, I, S> Named for OrFeedback<A, B, I, S>
|
impl<A, B, I, S> FeedbackLogic<A, B, I, S> for LogicFastOr
|
||||||
where
|
where
|
||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
#[inline]
|
fn name() -> &'static str {
|
||||||
fn name(&self) -> &str {
|
"Fast OR"
|
||||||
&self.name
|
}
|
||||||
|
|
||||||
|
fn is_pair_interesting<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
|
if a {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
second.is_interesting(state, manager, input, observers, exit_kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
fn is_pair_interesting_with_perf<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
feedback_stats: &mut [u64; NUM_FEEDBACKS],
|
||||||
|
feedback_index: usize,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
// Execute this feedback
|
||||||
|
let a = first.is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
feedback_stats,
|
||||||
|
feedback_index,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if a {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
second.is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
feedback_stats,
|
||||||
|
feedback_index + 1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, I, S> OrFeedback<A, B, I, S>
|
impl<A, B, I, S> FeedbackLogic<A, B, I, S> for LogicEagerAnd
|
||||||
where
|
where
|
||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Creates a new [`OrFeedback`] for two feedbacks.
|
fn name() -> &'static str {
|
||||||
pub fn new(first: A, second: B) -> Self {
|
"Eager AND"
|
||||||
let name = format!("Or({}, {})", first.name(), second.name());
|
|
||||||
Self {
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
name,
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_pair_interesting<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
|
let b = second.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
|
Ok(a && b)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
fn is_pair_interesting_with_perf<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
feedback_stats: &mut [u64; NUM_FEEDBACKS],
|
||||||
|
feedback_index: usize,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
// Execute this feedback
|
||||||
|
let a = first.is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
feedback_stats,
|
||||||
|
feedback_index,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let b = second.is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
feedback_stats,
|
||||||
|
feedback_index + 1,
|
||||||
|
)?;
|
||||||
|
Ok(a && b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A, B, I, S> FeedbackLogic<A, B, I, S> for LogicFastAnd
|
||||||
|
where
|
||||||
|
A: Feedback<I, S>,
|
||||||
|
B: Feedback<I, S>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"Fast AND"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_pair_interesting<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
|
if a == false {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
second.is_interesting(state, manager, input, observers, exit_kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
fn is_pair_interesting_with_perf<EM, OT>(
|
||||||
|
first: &mut A,
|
||||||
|
second: &mut B,
|
||||||
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
feedback_stats: &mut [u64; NUM_FEEDBACKS],
|
||||||
|
feedback_index: usize,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
// Execute this feedback
|
||||||
|
let a = first.is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
feedback_stats,
|
||||||
|
feedback_index,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if a == false {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
second.is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
feedback_stats,
|
||||||
|
feedback_index + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Combine two feedbacks with an eager AND operation,
|
||||||
|
/// will call all feedbacks functions even if not necessery to conclude the result
|
||||||
|
pub type EagerAndFeedback<A, B, I, S> = CombinedFeedback<A, B, I, S, LogicEagerAnd>;
|
||||||
|
|
||||||
|
/// Combine two feedbacks with an fast AND operation,
|
||||||
|
/// might skip calling feedbacks functions if not necessery to conclude the result
|
||||||
|
pub type FastAndFeedback<A, B, I, S> = CombinedFeedback<A, B, I, S, LogicFastAnd>;
|
||||||
|
|
||||||
|
/// Combine two feedbacks with an eager OR operation,
|
||||||
|
/// will call all feedbacks functions even if not necessery to conclude the result
|
||||||
|
pub type EagerOrFeedback<A, B, I, S> = CombinedFeedback<A, B, I, S, LogicEagerOr>;
|
||||||
|
|
||||||
|
/// Combine two feedbacks with an fast OR operation,
|
||||||
|
/// might skip calling feedbacks functions if not necessery to conclude the result
|
||||||
|
/// This means any feedback that is not first might be skipped, use caution when using with
|
||||||
|
/// `TimeFeedback`
|
||||||
|
pub type FastOrFeedback<A, B, I, S> = CombinedFeedback<A, B, I, S, LogicFastOr>;
|
||||||
|
|
||||||
/// Compose feedbacks with an OR operation
|
/// Compose feedbacks with an OR operation
|
||||||
pub struct NotFeedback<A, I, S>
|
pub struct NotFeedback<A, I, S>
|
||||||
where
|
where
|
||||||
@ -438,7 +647,18 @@ macro_rules! feedback_and {
|
|||||||
|
|
||||||
( $head:expr, $($tail:expr), +) => {
|
( $head:expr, $($tail:expr), +) => {
|
||||||
// recursive call
|
// recursive call
|
||||||
$crate::feedbacks::AndFeedback::new($head , feedback_and!($($tail),+))
|
$crate::feedbacks::EagerAndFeedback::new($head , feedback_and!($($tail),+))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
///
|
||||||
|
/// Variadic macro to create a chain of (fast) AndFeedback
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! feedback_and_fast {
|
||||||
|
( $last:expr ) => { $last };
|
||||||
|
|
||||||
|
( $head:expr, $($tail:expr), +) => {
|
||||||
|
// recursive call
|
||||||
|
$crate::feedbacks::FastAndFeedback::new($head , feedback_and_fast!($($tail),+))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +669,17 @@ macro_rules! feedback_or {
|
|||||||
|
|
||||||
( $head:expr, $($tail:expr), +) => {
|
( $head:expr, $($tail:expr), +) => {
|
||||||
// recursive call
|
// recursive call
|
||||||
$crate::feedbacks::OrFeedback::new($head , feedback_or!($($tail),+))
|
$crate::feedbacks::EagerOrFeedback::new($head , feedback_or!($($tail),+))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! feedback_or_fast {
|
||||||
|
( $last:expr ) => { $last };
|
||||||
|
|
||||||
|
( $head:expr, $($tail:expr), +) => {
|
||||||
|
// recursive call
|
||||||
|
$crate::feedbacks::FastOrFeedback::new($head , feedback_or_fast!($($tail),+))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user