use super::root::{
AffixualFormativeRoot, NormalFormativeRoot, NumericFormativeRoot, ReferentialFormativeRoot,
ShortcutCheckedFormativeRoot,
};
use crate::{
affix::AffixList,
category::{Stem, Version},
specificity::{AsGeneral, TryAsSpecific},
};
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct FormativeCore<RootType, StemType> {
pub root: RootType,
pub stem: StemType,
pub version: Version,
pub slot_vii_affixes: AffixList,
}
pub type NormalFormativeCore = FormativeCore<NormalFormativeRoot, Stem>;
pub type NumericFormativeCore = FormativeCore<NumericFormativeRoot, Stem>;
pub type ReferentialFormativeCore = FormativeCore<ReferentialFormativeRoot, ()>;
pub type AffixualFormativeCore = FormativeCore<AffixualFormativeRoot, ()>;
pub type ShortcutCheckedFormativeCore = FormativeCore<ShortcutCheckedFormativeRoot, Stem>;
macro_rules! as_general_impl {
($specific:ident, $variant:ident, $stem:ident, $stem_pat:pat, $stem_expr:expr, $stem_value:expr) => {
impl AsGeneral<ShortcutCheckedFormativeCore> for $specific {
fn as_general(self) -> ShortcutCheckedFormativeCore {
#[allow(unused_variables)]
let Self {
root,
$stem,
version,
slot_vii_affixes,
} = self;
ShortcutCheckedFormativeCore {
root: root.as_general(),
$stem: $stem_expr,
version,
slot_vii_affixes,
}
}
}
impl From<$specific> for ShortcutCheckedFormativeCore {
fn from(value: $specific) -> Self {
value.as_general()
}
}
impl TryAsSpecific<$specific> for ShortcutCheckedFormativeCore {
fn try_as_specific(self) -> Option<$specific> {
match self {
Self {
root: ShortcutCheckedFormativeRoot::$variant(root),
$stem: $stem_pat,
version,
slot_vii_affixes,
} => Some($specific {
root,
$stem: $stem_value,
version,
slot_vii_affixes,
}),
_ => None,
}
}
}
};
}
as_general_impl!(NormalFormativeCore, Normal, stem, stem, stem, stem);
as_general_impl!(NumericFormativeCore, Numeric, stem, stem, stem, stem);
as_general_impl!(
ReferentialFormativeCore,
Referential,
stem,
Stem::S1,
(Stem::S1),
()
);
as_general_impl!(
AffixualFormativeCore,
Affixual,
stem,
Stem::S1,
(Stem::S1),
()
);