use crate::{
category::{
ArbitraryMoodOrCaseScope, Case, CaseScope, DatalessRelation, IllocutionOrValidation, Mood,
MoodOrCaseScope, NominalMode, NonDefaultCaseScope, NonDefaultMood,
},
specificity::{AsGeneral, TryAsSpecific},
};
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Relation<CaseScopeType, MoodType> {
Nominal {
mode: NominalMode,
case_scope: CaseScopeType,
case: Case,
},
Verbal {
mood: MoodType,
ivl: IllocutionOrValidation,
},
}
impl<CaseScopeType, MoodType> Relation<CaseScopeType, MoodType> {
pub fn without_data(self) -> DatalessRelation {
match self {
Relation::Nominal { mode, .. } => mode.as_general(),
Relation::Verbal { .. } => DatalessRelation::VRB,
}
}
}
impl<CaseScopeType, MoodType> Relation<CaseScopeType, MoodType>
where
CaseScopeType: Into<CaseScope>,
MoodType: Into<Mood>,
{
pub fn split_as_dataless_cn_vc(self) -> (DatalessRelation, ArbitraryMoodOrCaseScope, Case) {
match self {
Relation::Nominal {
mode,
case_scope,
case,
} => (
mode.as_general(),
<CaseScopeType as Into<CaseScope>>::into(case_scope).as_general(),
case,
),
Relation::Verbal { mood, ivl } => (
DatalessRelation::VRB,
<MoodType as Into<Mood>>::into(mood).as_general(),
ivl.as_vc(),
),
}
}
}
impl<CaseScopeType, MoodType> Default for Relation<CaseScopeType, MoodType>
where
CaseScopeType: Default,
{
fn default() -> Self {
Self::Nominal {
mode: NominalMode::NOM,
case_scope: CaseScopeType::default(),
case: Case::THM,
}
}
}
pub type NormalRelation = Relation<CaseScope, Mood>;
pub type NonDefaultRelation = Relation<NonDefaultCaseScope, NonDefaultMood>;
impl AsGeneral<NormalRelation> for NonDefaultRelation {
fn as_general(self) -> NormalRelation {
match self {
Self::Nominal {
mode,
case_scope,
case,
} => NormalRelation::Nominal {
mode,
case_scope: case_scope.as_general(),
case,
},
Self::Verbal { mood, ivl } => NormalRelation::Verbal {
mood: mood.as_general(),
ivl,
},
}
}
}
impl From<NonDefaultRelation> for NormalRelation {
fn from(value: NonDefaultRelation) -> Self {
value.as_general()
}
}
impl TryAsSpecific<NonDefaultRelation> for NormalRelation {
fn try_as_specific(self) -> Option<NonDefaultRelation> {
Some(match self {
Self::Nominal {
mode,
case_scope,
case,
} => NonDefaultRelation::Nominal {
mode,
case_scope: match case_scope.try_as_specific() {
Some(value) => value,
None => return None,
},
case,
},
Self::Verbal { mood, ivl } => NonDefaultRelation::Verbal {
mood: match mood.try_as_specific() {
Some(value) => value,
None => return None,
},
ivl,
},
})
}
}
impl NormalRelation {
pub fn mood_or_case_scope(&self) -> MoodOrCaseScope {
match self {
Self::Nominal { case_scope, .. } => case_scope.as_general(),
Self::Verbal { mood, .. } => mood.as_general(),
}
}
}
impl NonDefaultRelation {
pub fn mood_or_case_scope(&self) -> MoodOrCaseScope {
self.as_general().mood_or_case_scope()
}
}