use crate::types::TypedVariables;
use crate::types::{EffectCondition, Effects, GoalDefinition, PrimitiveEffect};
#[doc(alias("c-effect"))]
#[derive(Debug, Clone, PartialEq)]
pub enum ConditionalEffect {
Effect(PrimitiveEffect),
Forall(ForallConditionalEffect),
When(WhenConditionalEffect),
}
#[doc(alias("c-effect"))]
#[derive(Debug, Clone, PartialEq)]
pub struct ForallConditionalEffect {
pub variables: TypedVariables,
pub effects: Effects,
}
impl ForallConditionalEffect {
pub const fn new(variables: TypedVariables, effects: Effects) -> Self {
ForallConditionalEffect { variables, effects }
}
}
#[doc(alias("c-effect"))]
#[derive(Debug, Clone, PartialEq)]
pub struct WhenConditionalEffect {
pub condition: GoalDefinition,
pub effect: EffectCondition,
}
impl WhenConditionalEffect {
pub const fn new(condition: GoalDefinition, effect: EffectCondition) -> Self {
WhenConditionalEffect { condition, effect }
}
}
impl ConditionalEffect {
pub const fn new_primitive_effect(effect: PrimitiveEffect) -> Self {
Self::Effect(effect)
}
#[deprecated(since = "0.2.0", note = "Use `new_primitive_effect` instead")]
pub const fn new_p_effect(effect: PrimitiveEffect) -> Self {
Self::new_primitive_effect(effect)
}
pub const fn primitive_effect(effect: PrimitiveEffect) -> Self {
Self::Effect(effect)
}
pub const fn forall(variables: TypedVariables, effect: Effects) -> Self {
Self::Forall(ForallConditionalEffect::new(variables, effect))
}
#[deprecated(since = "0.2.0", note = "Use `forall` instead")]
pub const fn new_forall(variables: TypedVariables, effect: Effects) -> Self {
Self::forall(variables, effect)
}
pub const fn when(condition: GoalDefinition, effect: EffectCondition) -> Self {
Self::When(WhenConditionalEffect::new(condition, effect))
}
#[deprecated(since = "0.2.0", note = "Use `when` instead")]
pub const fn new_when(condition: GoalDefinition, effect: EffectCondition) -> Self {
Self::when(condition, effect)
}
}
impl From<PrimitiveEffect> for ConditionalEffect {
fn from(value: PrimitiveEffect) -> Self {
ConditionalEffect::new_primitive_effect(value)
}
}
impl From<ForallConditionalEffect> for ConditionalEffect {
fn from(value: ForallConditionalEffect) -> Self {
ConditionalEffect::Forall(value)
}
}
impl From<WhenConditionalEffect> for ConditionalEffect {
fn from(value: WhenConditionalEffect) -> Self {
ConditionalEffect::When(value)
}
}
impl From<(TypedVariables, Effects)> for ForallConditionalEffect {
fn from(value: (TypedVariables, Effects)) -> Self {
ForallConditionalEffect::new(value.0, value.1)
}
}
impl From<(GoalDefinition, EffectCondition)> for WhenConditionalEffect {
fn from(value: (GoalDefinition, EffectCondition)) -> Self {
WhenConditionalEffect::new(value.0, value.1)
}
}
impl TryInto<PrimitiveEffect> for ConditionalEffect {
type Error = ();
fn try_into(self) -> Result<PrimitiveEffect, Self::Error> {
match self {
ConditionalEffect::Effect(x) => Ok(x),
ConditionalEffect::Forall(_) => Err(()),
ConditionalEffect::When(_) => Err(()),
}
}
}
impl TryInto<WhenConditionalEffect> for ConditionalEffect {
type Error = ();
fn try_into(self) -> Result<WhenConditionalEffect, Self::Error> {
match self {
ConditionalEffect::Effect(_) => Err(()),
ConditionalEffect::Forall(_) => Err(()),
ConditionalEffect::When(x) => Ok(x),
}
}
}
impl TryInto<ForallConditionalEffect> for ConditionalEffect {
type Error = ();
fn try_into(self) -> Result<ForallConditionalEffect, Self::Error> {
match self {
ConditionalEffect::Effect(_) => Err(()),
ConditionalEffect::Forall(x) => Ok(x),
ConditionalEffect::When(_) => Err(()),
}
}
}
#[deprecated(since = "0.2.0", note = "Use `ConditionalEffect` instead")]
pub type CEffect = ConditionalEffect;
#[deprecated(since = "0.2.0", note = "Use `ForallConditionalEffect` instead")]
pub type ForallCEffect = ForallConditionalEffect;
#[deprecated(since = "0.2.0", note = "Use `WhenConditionalEffect` instead")]
pub type WhenCEffect = WhenConditionalEffect;
#[cfg(test)]
mod tests {
use super::*;
use crate::types::{AtomicFormula, Term};
#[test]
fn conditional_effect_try_into_primitive_effect() {
let pe = PrimitiveEffect::new(AtomicFormula::equality(
Term::Name("x".into()),
Term::Name("y".into()),
));
let ce: ConditionalEffect = pe.clone().into();
let result: Result<PrimitiveEffect, ()> = ce.try_into();
assert!(result.is_ok());
}
#[test]
fn conditional_effect_try_into_primitive_effect_fails() {
let vars = TypedVariables::default();
let ce = ConditionalEffect::forall(vars, Effects::default());
let result: Result<PrimitiveEffect, ()> = ce.try_into();
assert!(result.is_err());
}
#[test]
fn conditional_effect_try_into_when() {
let cond = GoalDefinition::and(Vec::new());
let effect = EffectCondition::all(Vec::new());
let ce = ConditionalEffect::when(cond, effect);
let result: Result<WhenConditionalEffect, ()> = ce.try_into();
assert!(result.is_ok());
}
#[test]
fn conditional_effect_try_into_when_fails() {
let ce = ConditionalEffect::new_primitive_effect(PrimitiveEffect::new(
AtomicFormula::equality(Term::Name("x".into()), Term::Name("y".into())),
));
let result: Result<WhenConditionalEffect, ()> = ce.try_into();
assert!(result.is_err());
}
#[test]
fn conditional_effect_try_into_forall() {
let vars = TypedVariables::default();
let effects = Effects::default();
let ce = ConditionalEffect::forall(vars, effects);
let result: Result<ForallConditionalEffect, ()> = ce.try_into();
assert!(result.is_ok());
}
#[test]
fn conditional_effect_from_tuples() {
let effects = Effects::default();
let forall: ForallConditionalEffect = (TypedVariables::default(), effects).into();
assert!(forall.effects.is_empty());
let cond = GoalDefinition::and(Vec::new());
let effect = EffectCondition::all(Vec::new());
let when: WhenConditionalEffect = (cond, effect).into();
assert!(matches!(when.condition, GoalDefinition::And(_)));
}
#[test]
#[allow(deprecated)]
fn deprecated_aliases_exist() {
fn _assert_alias_ce(_: CEffect) {}
fn _assert_alias_fc(_: ForallCEffect) {}
fn _assert_alias_wc(_: WhenCEffect) {}
}
}