tnil/word/formative/
core.rs

1//! Defines formative core types.
2
3use super::root::{
4    AffixualFormativeRoot, NormalFormativeRoot, NumericFormativeRoot, ReferentialFormativeRoot,
5    ShortcutCheckedFormativeRoot,
6};
7use crate::{
8    affix::AffixList,
9    category::{Stem, Version},
10    specificity::{AsGeneral, TryAsSpecific},
11};
12
13/// The core of a formative.
14#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
15pub struct FormativeCore<RootType, StemType> {
16    /// The root of this formative.
17    pub root: RootType,
18
19    /// The stem of this formative.
20    pub stem: StemType,
21
22    /// The version of this formative.
23    pub version: Version,
24
25    /// The slot VII affixes of this formative.
26    pub slot_vii_affixes: AffixList,
27}
28
29/// The core of a normal formative.
30pub type NormalFormativeCore = FormativeCore<NormalFormativeRoot, Stem>;
31
32/// The core of a numeric formative.
33pub type NumericFormativeCore = FormativeCore<NumericFormativeRoot, Stem>;
34
35/// The core of a referential formative.
36pub type ReferentialFormativeCore = FormativeCore<ReferentialFormativeRoot, ()>;
37
38/// The core of an affixual formative.
39pub type AffixualFormativeCore = FormativeCore<AffixualFormativeRoot, ()>;
40
41/// The core of a general formative.
42pub type ShortcutCheckedFormativeCore = FormativeCore<ShortcutCheckedFormativeRoot, Stem>;
43
44macro_rules! as_general_impl {
45    ($specific:ident, $variant:ident, $stem:ident, $stem_pat:pat, $stem_expr:expr, $stem_value:expr) => {
46        impl AsGeneral<ShortcutCheckedFormativeCore> for $specific {
47            fn as_general(self) -> ShortcutCheckedFormativeCore {
48                #[allow(unused_variables)]
49                let Self {
50                    root,
51                    $stem,
52                    version,
53                    slot_vii_affixes,
54                } = self;
55
56                ShortcutCheckedFormativeCore {
57                    root: root.as_general(),
58                    $stem: $stem_expr,
59                    version,
60                    slot_vii_affixes,
61                }
62            }
63        }
64
65        impl From<$specific> for ShortcutCheckedFormativeCore {
66            fn from(value: $specific) -> Self {
67                value.as_general()
68            }
69        }
70
71        impl TryAsSpecific<$specific> for ShortcutCheckedFormativeCore {
72            fn try_as_specific(self) -> Option<$specific> {
73                match self {
74                    Self {
75                        root: ShortcutCheckedFormativeRoot::$variant(root),
76                        $stem: $stem_pat,
77                        version,
78                        slot_vii_affixes,
79                    } => Some($specific {
80                        root,
81                        $stem: $stem_value,
82                        version,
83                        slot_vii_affixes,
84                    }),
85                    _ => None,
86                }
87            }
88        }
89    };
90}
91
92as_general_impl!(NormalFormativeCore, Normal, stem, stem, stem, stem);
93
94as_general_impl!(NumericFormativeCore, Numeric, stem, stem, stem, stem);
95
96as_general_impl!(
97    ReferentialFormativeCore,
98    Referential,
99    stem,
100    Stem::S1,
101    (Stem::S1),
102    ()
103);
104
105as_general_impl!(
106    AffixualFormativeCore,
107    Affixual,
108    stem,
109    Stem::S1,
110    (Stem::S1),
111    ()
112);