narust_158/language/base/
property.rs

1//! 实现 / 属性(内建)
2//! * 🎯非OpenNARS所定义之「属性」「方法」
3//!   * 📌至少并非OpenNARS原先所定义的
4
5use super::structs::*;
6use crate::symbols::*;
7use crate::util::ToDisplayAndBrief;
8
9/// 内建属性
10impl Term {
11    /// 只读的「标识符」属性
12    #[inline]
13    pub fn identifier(&self) -> &str {
14        &self.identifier
15    }
16
17    /// 只读的「组分」属性
18    #[inline]
19    pub fn components(&self) -> &TermComponents {
20        &self.components
21    }
22
23    /// language内部可写的「组分」属性
24    #[inline]
25    pub(in crate::language) fn components_mut(&mut self) -> &mut TermComponents {
26        &mut self.components
27    }
28
29    /// 判断其是否为「占位符」
30    /// * 🎯【2024-04-21 01:04:17】在「词法折叠」中首次使用
31    pub fn is_placeholder(&self) -> bool {
32        self.identifier == PLACEHOLDER
33    }
34
35    /// 快捷获取「标识符-组分」二元组
36    /// * 🎯用于很多地方的「类型匹配」
37    pub fn id_comp(&self) -> (&str, &TermComponents) {
38        (&self.identifier, &self.components)
39    }
40
41    /// 快捷获取「标识符-组分」二元组,并提供可变机会
42    /// * 🚩【2024-04-21 00:59:20】现在正常返回其两重可变引用
43    /// * 📝【2024-04-21 00:58:58】当「标识符」为「静态字串」时,不能对其内部的`&str`属性进行修改
44    ///   * 📌使用`&mut &str`会遇到生命周期问题
45    ///   * 📌实际上「修改类型」本身亦不常用
46    /// * 🚩【2024-09-08 16:51:57】目前仅在「语言」模块的测试代码中使用
47    #[cfg(test)]
48    pub(in crate::language) fn id_comp_mut(&mut self) -> (&mut String, &mut TermComponents) {
49        (&mut self.identifier, &mut self.components)
50    }
51
52    /// 解包「标识符-组分」二元组,丢弃其它字段
53    /// * 📌【2024-09-08 16:54:28】目前没有其它字段
54    pub fn unwrap_id_comp(self) -> (String, TermComponents) {
55        (self.identifier, self.components)
56    }
57
58    /// 判断「是否包含指定类型的词项」
59    /// * 🎯支持「词项」中的方法,递归判断「是否含有变量」
60    pub fn contain_type(&self, identifier: &str) -> bool {
61        self.identifier == identifier || self.components.contain_type(identifier)
62    }
63
64    /// 遍历其中所有原子词项
65    /// * 🎯找到其中所有的变量
66    /// * ⚠️外延像/内涵像 中的占位符
67    /// * ⚠️需要传入闭包的可变引用,而非闭包本身
68    ///   * 📌中间「递归深入」需要重复调用(传入)闭包
69    /// * 📄词语、变量
70    /// * 📄占位符
71    pub fn for_each_atom(&self, f: &mut impl FnMut(&Term)) {
72        use TermComponents::*;
73        match self.components() {
74            // 无组分⇒遍历自身
75            Empty | Word(..) | Variable(..) => f(self),
76            // 内含词项⇒递归深入
77            Compound(terms) => {
78                for term in terms.iter() {
79                    term.for_each_atom(f);
80                }
81            }
82        }
83    }
84
85    /// 遍历其中所有原子词项(可变版本)
86    /// * [`Self::for_each_atom`]的可变版本
87    /// * 📌仅在整个库内部使用
88    pub(crate) fn for_each_atom_mut(&mut self, f: &mut impl FnMut(&Term)) {
89        use TermComponents::*;
90        match self.components_mut() {
91            // 无组分⇒遍历自身
92            Empty | Word(..) | Variable(..) => f(self),
93            // 内含词项⇒递归深入
94            Compound(terms) => {
95                for term in terms.iter_mut() {
96                    term.for_each_atom_mut(f);
97                }
98            }
99        }
100    }
101}
102
103/// 实现[`Display`]
104/// * 🎯调试时便于展现内部结构
105/// * ⚡性能友好
106/// * ⚠️并非CommonNarsese语法
107impl std::fmt::Display for Term {
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        f.write_str(&self.format_name())
110    }
111}
112
113/// 自动实现[`ToDisplayAndBrief`]
114/// * 🚩【2024-05-08 23:30:59】「简略显示」与「完全显示」相同
115/// * 🚩【2024-05-08 23:31:32】目前使用ASCII格式化器去做,性能可能会低
116impl ToDisplayAndBrief for Term {
117    #[inline]
118    fn to_display(&self) -> String {
119        self.format_ascii()
120    }
121}
122
123/// 内建属性
124impl TermComponents {
125    /// 获取「组分」的大小
126    /// * ⚠️对于「带索引序列」不包括「索引」
127    ///   * 📄对「像」不包括「像占位符」
128    pub fn len(&self) -> usize {
129        use TermComponents::*;
130        match self {
131            // 无组分
132            Empty | Word(..) | Variable(..) => 0,
133            // 不定数目
134            Compound(terms) => terms.len(),
135        }
136    }
137
138    /// 获取「组分是否为空」
139    /// * 🎯自clippy提示而设
140    pub fn is_empty(&self) -> bool {
141        use TermComponents::*;
142        match self {
143            // 一定空
144            Empty | Word(..) | Variable(..) => true,
145            // 可能空
146            Compound(terms) => terms.is_empty(),
147        }
148    }
149
150    /// 获取指定位置的组分(不一定有)
151    /// * ⚠️对于「带索引序列」不受「索引」影响
152    ///   * 📄对「像」不受「像占位符」影响
153    pub fn get(&self, index: usize) -> Option<&Term> {
154        use TermComponents::*;
155        match self {
156            // 无组分
157            Empty | Word(..) | Variable(..) => None,
158            // 有组分
159            Compound(terms) => terms.get(index),
160        }
161    }
162
163    /// 获取指定位置的组分(不检查,直接返回元素)
164    /// * ⚠️对于「带索引序列」不受「索引」影响
165    ///   * 📄对「像」不受「像占位符」影响
166    ///
167    /// # Safety
168    ///
169    /// ⚠️只有在「确保索引不会越界」才不会引发panic和未定义行为(UB)
170    pub unsafe fn get_unchecked(&self, index: usize) -> &Term {
171        use TermComponents::*;
172        match self {
173            // 有组分
174            Compound(terms) => terms.get_unchecked(index),
175            // 其它情况⇒panic
176            _ => panic!("尝试在非法位置 {index} 获取词项:{self:?}"),
177        }
178    }
179
180    /// 获取其中「所有元素」的迭代器
181    /// * 🚩返回一个迭代器,迭代其中所有「元素」
182    /// * ⚠️并非「深迭代」:仅迭代自身的下一级词项,不会递归深入
183    pub fn iter(&self) -> impl Iterator<Item = &Term> {
184        use TermComponents::*;
185        // * 📝必须添加类型注释,以便统一不同类型的`Box`,进而统一「迭代器」类型
186        let b: Box<dyn Iterator<Item = &Term>> = match self {
187            // 一定空
188            Empty | Word(..) | Variable(..) => Box::new(None.into_iter()),
189            // 可能空
190            Compound(terms) => Box::new(terms.iter()),
191        };
192        b
193    }
194
195    /// (作为无序不重复集合)排序内部词项并去重
196    /// * 🎯表征「可交换词项(无序不重复词项)」的「构造时整理」与「修改后整理」
197    /// * 🎯提供统一的方法,整理内部词项而不依赖外界
198    /// * 🎯用作「集合中替换元素后,重新排序(并去重)」
199    ///   * ⚠️不会在「固定数目词项」中去重
200    ///   * 📄NAL-6「变量替换」
201    /// * ⚠️暂且封闭:不让外界随意调用 破坏其内部结构
202    /// * ⚠️只会排序内部的一层词项
203    pub(crate) fn sort_dedup(self) -> Self {
204        use TermComponents::*;
205        match self {
206            // 无组分 ⇒ 不排序
207            Empty | Word(..) | Variable(..) => self,
208            // 不定数目⇒直接对数组重排并去重
209            Compound(terms) => Self::Compound(Self::sort_dedup_terms(terms)),
210        }
211    }
212
213    /// 在不可变长数组中对数组进行排序并去重
214    pub fn sort_dedup_terms(terms: Box<[Term]>) -> Box<[Term]> {
215        // 转换成变长数组
216        let mut new_terms = Vec::from(terms);
217        // * 重排+去重
218        Self::sort_dedup_term_vec(&mut new_terms);
219        // 转换回定长数组
220        new_terms.into_boxed_slice()
221    }
222
223    /// 对「词项数组」重排并去重
224    pub fn sort_dedup_term_vec(terms: &mut Vec<Term>) {
225        // 重排 | ✅保证去重不改变顺序
226        terms.sort();
227        // 去重 | ⚠️危险:会改变词项长度
228        terms.dedup();
229    }
230
231    /// 获取内部所有词项,拷贝成变长数组
232    /// * 🎯用于复合词项增删相关
233    pub fn clone_to_vec(&self) -> Vec<Term> {
234        use TermComponents::*;
235        match self {
236            // * 🚩原子词项⇒空数组
237            Empty | Word(..) | Variable(..) => vec![],
238            // * 🚩复合词项⇒使用`to_vec`拷贝数组
239            Compound(terms) => terms.to_vec(),
240        }
241    }
242
243    /// 判断「是否包含指定类型的词项」
244    /// * 🎯支持「词项」中的方法,递归判断「是否含有变量」
245    /// * 🚩【2024-04-21 20:35:23】目前直接基于迭代器
246    ///   * 📌牺牲一定性能,加快开发速度
247    pub fn contain_type(&self, identifier: &str) -> bool {
248        self.iter().any(|term| term.contain_type(identifier))
249    }
250
251    /// 判断「结构模式上是否匹配」
252    /// * 🚩判断二者在「结构大小」与(可能有的)「结构索引」是否符合
253    /// * ⚠️非递归:不会递归比较「组分是否对应匹配」
254    /// * 🎯变量替换中的「相同结构之模式替换」
255    /// * 📄`variable::find_substitute`
256    pub fn structural_match(&self, other: &Self) -> bool {
257        use TermComponents::*;
258        match (self, other) {
259            // 同类型 / 空 | 同类型 / 具名 | 同类型 / 变量
260            (Empty, Empty) | (Word(..), Word(..)) | (Variable(..), Variable(..)) => true,
261            // 同类型 / 多元
262            (Compound(terms1), Compound(terms2)) => terms1.len() == terms2.len(),
263            // 其它情形(类型相异)
264            _ => false,
265        }
266    }
267}
268
269/// 单元测试
270#[cfg(test)]
271mod tests {
272    use super::*;
273    use crate::test_term as term;
274    use crate::{ok, util::AResult};
275    use nar_dev_utils::asserts;
276
277    /// 测试 / [`Term`]
278    mod term {
279        use super::*;
280        use nar_dev_utils::macro_once;
281
282        #[test]
283        fn eq() -> AResult {
284            macro_once! {
285                // * 🚩模式:左边词项 运算符 右边字符串
286                macro eq($( $left:literal $op:tt $right:expr )*) {
287                    asserts! {$(
288                        term!($left) $op term!($right),
289                    )*}
290                }
291                // 二次构造
292                "A" == "A"
293                "<A --> B>" == "<A-->B>"
294                "[A]" == "[A]"
295                // 可交换性
296                "<A <-> B>" == "<B <-> A>"
297                "(&, C, A, B)" == "(&, B, C, A)"
298                "{C, A, B}" == "{B, C, A}"
299                // 自动转换
300                r"(/, _, A, B)" == "(*, A, B)"
301                r"(\, _, A, B)" == "(*, A, B)"
302                // 不等 / 标识符
303                "$A" != "A"
304                "$A" != "#A"
305                r"(\, A, _, B)" != r"(/, A, _, B)"
306                "<A <-> B>" != "<A <=> B>"
307                // 不等 / 元素
308                "A" != "a"
309                "(*, A, B, C)" != "(*, A, B)"
310                "(*, A, B, C)" != "(*, A, B, c)"
311                "(/, A, B, _)" != "(/, A, _, B)"
312                "{C, A, B}" != "{B, C}"
313            }
314            ok!()
315        }
316
317        /// 测试 / 散列
318        /// * 🚩【2024-04-25 09:24:58】仅测试其「可散列化」
319        #[test]
320        fn hash() -> AResult {
321            use std::collections::{HashMap, HashSet};
322            use std::hash::RandomState;
323            // 创建
324            let mut map = HashMap::from([(term!("A"), term!("B")), (term!("C"), term!("D"))]);
325            let mut set: HashSet<Term, RandomState> = HashSet::from_iter(map.keys().cloned());
326            asserts! {
327                map.get(&term!("A")) => Some(&term!("B")),
328                map.get(&term!("C")) => Some(&term!("D")),
329                map.get(&term!("E")) => None,
330                set.contains(&term!("A"))
331                set.contains(&term!("C"))
332            }
333            // 修改
334            map.insert(term!("D"), term!("C"));
335            for v in map.values() {
336                set.insert(v.clone());
337            }
338            asserts! {
339                map.get(&term!("D")) => Some(&term!("C")),
340                set.contains(&term!("B"))
341                set.contains(&term!("D"))
342            }
343            // 结束
344            dbg!(&map, &set);
345            ok!()
346        }
347
348        #[test]
349        fn identifier() -> AResult {
350            macro_once! {
351                // * 🚩模式:词项字符串 ⇒ 预期
352                macro identifier($( $s:literal => $expected:expr )*) {
353                    asserts! {$(
354                        term!($s).identifier() => $expected,
355                    )*}
356                }
357                // 占位符
358                "_" => PLACEHOLDER
359                // 原子词项
360                "A" => WORD
361                "$A" => VAR_INDEPENDENT
362                "#A" => VAR_DEPENDENT
363                "?A" => VAR_QUERY
364                // 复合词项
365                "{A}" => SET_EXT_OPERATOR
366                "[A]" => SET_INT_OPERATOR
367                "(&, A, B)" => INTERSECTION_EXT_OPERATOR // ! 📌【2024-09-07 13:10:43】现在需要保证词项有效,不能再用单个词项了
368                "(|, A, B)" => INTERSECTION_INT_OPERATOR // ! 📌【2024-09-07 13:10:43】现在需要保证词项有效,不能再用单个词项了
369                "(-, A, B)" => DIFFERENCE_EXT_OPERATOR
370                "(~, A, B)" => DIFFERENCE_INT_OPERATOR
371                "(*, A)" => PRODUCT_OPERATOR
372                r"(/, R, _)" => IMAGE_EXT_OPERATOR
373                r"(\, R, _)" => IMAGE_INT_OPERATOR
374                r"(&&, A, B)" => CONJUNCTION_OPERATOR // ! 📌【2024-09-07 13:10:43】现在需要保证词项有效,不能再用单个词项了
375                r"(||, A, B)" => DISJUNCTION_OPERATOR // ! 📌【2024-09-07 13:10:43】现在需要保证词项有效,不能再用单个词项了
376                r"(--, A)" => NEGATION_OPERATOR
377                // 陈述
378                "<A --> B>" => INHERITANCE_RELATION
379                "<A <-> B>" => SIMILARITY_RELATION
380                "<A ==> B>" => IMPLICATION_RELATION
381                "<A <=> B>" => EQUIVALENCE_RELATION
382            }
383            ok!()
384        }
385
386        #[test]
387        fn components() -> AResult {
388            use TermComponents::*;
389            macro_once! {
390                // * 🚩模式:词项字符串 ⇒ 预期模式
391                macro components($( $s:literal => $expected:pat )*) {
392                    asserts! {$(
393                        term!($s).components() => @$expected,
394                    )*}
395                }
396                // 空(一般不会在外部出现)
397                "_" => Empty
398                // 具名
399                "A" => Word(..)
400                // 变量
401                "$A" => Variable(..)
402                "#A" => Variable(..)
403                "?A" => Variable(..)
404                // 一元
405                "(--, A)" => Compound(..)
406                // 二元
407                "(-, A, B)" => Compound(..)
408                "(~, A, B)" => Compound(..)
409                "<A --> B>" => Compound(..)
410                "<A <-> B>" => Compound(..)
411                "<A ==> B>" => Compound(..)
412                "<A <=> B>" => Compound(..)
413                // 多元
414                "{A}" => Compound(..)
415                "[A]" => Compound(..)
416                "(&, A, B)" => Compound(..)
417                "(|, A, B)" => Compound(..)
418                "(*, A)" => Compound(..)
419                r"(&&, A, B)" => Compound(..)
420                r"(||, A, B)" => Compound(..)
421                // 多元索引
422                r"(/, R, _)" => Compound(..)
423                r"(\, R, _)" => Compound(..)
424            }
425            ok!()
426        }
427
428        #[test]
429        fn is_placeholder() -> AResult {
430            macro_once! {
431                // * 🚩模式:词项字符串 ⇒ 预期
432                macro is_placeholder($( $s:literal => $expected:expr )*) {
433                    asserts! {$(
434                        term!($s).is_placeholder() => $expected,
435                    )*}
436                }
437                // 占位符
438                "_" => true
439                // 原子词项
440                "A" => false
441                "$A" => false
442                "#A" => false
443                "?A" => false
444                // 复合词项
445                "{A}" => false
446                "[A]" => false
447                "(&, A, B)" => false // ! 【2024-09-07 12:55:51】现在"(&, A)" 会被自动简化
448                "(|, A, B)" => false // ! 【2024-09-07 12:55:51】现在"(|, A)" 会被自动简化
449                "(-, A, B)" => false
450                "(~, A, B)" => false
451                "(*, A)" => false
452                r"(/, R, _)" => false
453                r"(\, R, _)" => false
454                r"(&&, A)" => false
455                r"(||, A)" => false
456                r"(--, A)" => false
457                // 陈述
458                "<A --> B>" => false
459                "<A <-> B>" => false
460                "<A ==> B>" => false
461                "<A <=> B>" => false
462            }
463            ok!()
464        }
465
466        /// 🎯仅测试其返回值为二元组
467        #[test]
468        fn id_comp() -> AResult {
469            macro_once! {
470                // * 🚩模式:词项字符串
471                macro id_comp($($s:literal)*) {
472                    asserts! {$(
473                        term!($s).id_comp() => @(&_, &_),
474                    )*}
475                }
476                // 占位符
477                "_"
478                // 原子词项
479                "A"
480                "$A"
481                "#A"
482                "?A"
483                // 复合词项
484                "{A}"
485                "[A]"
486                "(&, A)"
487                "(|, A)"
488                "(-, A, B)"
489                "(~, A, B)"
490                "(*, A)"
491                r"(/, R, _)"
492                r"(\, R, _)"
493                r"(&&, A)"
494                r"(||, A)"
495                r"(--, A)"
496                // 陈述
497                "<A --> B>"
498                "<A <-> B>"
499                "<A ==> B>"
500                "<A <=> B>"
501            }
502            ok!()
503        }
504
505        /// 🎯仅测试其返回值为二元组
506        #[test]
507        fn id_comp_mut() -> AResult {
508            macro_once! {
509                // * 🚩模式:词项字符串
510                macro id_comp_mut($($s:literal)*) {
511                    asserts! {$(
512                        term!($s).id_comp_mut() => @(&mut _, &mut _),
513                    )*}
514                }
515                // 占位符
516                "_"
517                // 原子词项
518                "A"
519                "$A"
520                "#A"
521                "?A"
522                // 复合词项
523                "{A}"
524                "[A]"
525                "(&, A)"
526                "(|, A)"
527                "(-, A, B)"
528                "(~, A, B)"
529                "(*, A)"
530                r"(/, R, _)"
531                r"(\, R, _)"
532                r"(&&, A)"
533                r"(||, A)"
534                r"(--, A)"
535                // 陈述
536                "<A --> B>"
537                "<A <-> B>"
538                "<A ==> B>"
539                "<A <=> B>"
540            }
541            ok!()
542        }
543
544        #[test]
545        fn contain_type() -> AResult {
546            macro_once! {
547                // * 🚩模式:含有的类型 in 词项字符串
548                macro contain_type($($expected:ident in $s:literal)*) {
549                    asserts! {$(
550                        term!($s).contain_type($expected)
551                    )*}
552                }
553                // 复合词项
554                WORD in "{A}"
555                WORD in "[A]"
556                WORD in "(&, A, B)" // ! 【2024-09-07 12:55:51】现在"(&, A)" 会被自动简化
557                WORD in "(|, A, B)" // ! 【2024-09-07 12:55:51】现在"(|, A)" 会被自动简化
558                WORD in "(-, A, B)"
559                WORD in "(~, A, B)"
560                WORD in "(*, A)"
561                WORD in r"(/, R, _)"
562                WORD in r"(\, R, _)"
563                WORD in r"(&&, A, B)" // ! 【2024-09-07 12:55:51】现在"(&&, A)" 会被自动简化
564                WORD in r"(||, A, B)" // ! 【2024-09-07 12:55:51】现在"(||, A)" 会被自动简化
565                WORD in r"(--, A)"
566
567                VAR_INDEPENDENT in "{$A}"
568                VAR_INDEPENDENT in "[$A]"
569                VAR_INDEPENDENT in "(&, $A)"
570                VAR_INDEPENDENT in "(|, $A)"
571                VAR_INDEPENDENT in "(-, $A, B)"
572                VAR_INDEPENDENT in "(~, $A, B)"
573                VAR_INDEPENDENT in "(*, $A)"
574                VAR_INDEPENDENT in r"(/, $R, _)"
575                VAR_INDEPENDENT in r"(\, $R, _)"
576                VAR_INDEPENDENT in r"(&&, $A, #B)" // ! 【2024-09-07 12:55:51】现在"(&&, A)" 会被自动简化
577                VAR_INDEPENDENT in r"(||, $A, #B)" // ! 【2024-09-07 12:55:51】现在"(||, A)" 会被自动简化
578                VAR_DEPENDENT   in r"(&&, $A, #B)" // ! 【2024-09-07 12:55:51】现在"(&&, A)" 会被自动简化
579                VAR_DEPENDENT   in r"(||, $A, #B)" // ! 【2024-09-07 12:55:51】现在"(||, A)" 会被自动简化
580                VAR_INDEPENDENT in r"(--, $A)"
581
582                PRODUCT_OPERATOR in "{(*, A)}"
583                PRODUCT_OPERATOR in "[(*, A)]"
584                PRODUCT_OPERATOR in "(&, (*, A), B)" // ! 【2024-09-07 12:55:51】现在"(&, X)" 会被自动简化
585                PRODUCT_OPERATOR in "(|, (*, A), B)" // ! 【2024-09-07 12:55:51】现在"(|, X)" 会被自动简化
586                PRODUCT_OPERATOR in "(-, (*, A), B)"
587                PRODUCT_OPERATOR in "(~, (*, A), B)"
588                PRODUCT_OPERATOR in "(*, (*, A))"
589                PRODUCT_OPERATOR in r"(/, (*, R), _)"
590                PRODUCT_OPERATOR in r"(\, (*, R), _)"
591                PRODUCT_OPERATOR in r"(&&, (*, A), B)" // ! 【2024-09-07 12:55:51】现在"(&&, X)" 会被自动简化
592                PRODUCT_OPERATOR in r"(||, (*, A), B)" // ! 【2024-09-07 12:55:51】现在"(||, X)" 会被自动简化
593                PRODUCT_OPERATOR in r"(--, (*, A))"
594
595                // 陈述
596                WORD in "<A --> B>"
597                WORD in "<A <-> B>"
598                WORD in "<A ==> B>"
599                WORD in "<A <=> B>"
600
601                INHERITANCE_RELATION in "<<A --> B> --> <C ==> D>>" // ! ⚠️【2024-09-07 13:13:05】现在需要通过`make`的检验
602                SIMILARITY_RELATION  in "<<A <-> B> <-> <C <=> D>>" // ! ⚠️【2024-09-07 13:13:05】现在需要通过`make`的检验
603                IMPLICATION_RELATION in "<<A --> B> ==> <C ==> D>>" // ! ⚠️【2024-09-07 13:13:05】现在需要通过`make`的检验
604                EQUIVALENCE_RELATION in "<<A <-> B> <=> <C <=> D>>" // ! ⚠️【2024-09-07 13:13:05】现在需要通过`make`的检验
605            }
606            ok!()
607        }
608
609        /// 🎯类型相等,组分相配
610        #[test]
611        fn structural_match() -> AResult {
612            macro_once! {
613                // * 🚩模式:被匹配的 ⇒ 用于匹配的
614                macro assert_structural_match($($term1:literal => $term2:literal)*) {
615                    asserts! {$(
616                        term!($term1).structural_match(&term!($term2))
617                    )*}
618                }
619                // 常规 //
620                // 占位符
621                "_" => "__"
622                // 原子词项
623                "A" => "a"
624                "$A" => "$a"
625                "#A" => "#a"
626                "?A" => "?a"
627                // 复合词项
628                "{A}" => "{a}"
629                "[A]" => "[a]"
630                "(&, A, B)" => "(&, a, b)"
631                "(|, A, B)" => "(|, a, b)"
632                "(-, A, B)" => "(-, a, b)"
633                "(~, A, B)" => "(~, a, b)"
634                "(*, A)" => "(*, a)"
635                r"(/, R, _)" => r"(/, r, _)"
636                r"(\, R, _)" => r"(\, r, _)"
637                r"(&&, A, B)" => r"(&&, a, b)"
638                r"(||, A, B)" => r"(||, a, b)"
639                r"(--, A)" => r"(--, a)"
640                // 陈述
641                "<A --> B>" => "<a --> b>"
642                "<A <-> B>" => "<a <-> b>"
643                "<A ==> B>" => "<a ==> b>"
644                "<A <=> B>" => "<a <=> b>"
645                // 可交换(⚠️只判断一层) //
646                "{A, B, C}" => "{0, 1, 2}"
647                "{A, B, [C]}" => "{0, 1, [2]}"
648                "{A, {B, C, D}, [E]}" => "{{0, 1, 2}, 1, [2]}"
649            }
650            ok!()
651        }
652
653        #[test]
654        fn fmt() -> AResult {
655            macro_once! {
656                // * 🚩模式:词项字符串 ⇒ 预期
657                macro fmt($($term:literal => $expected:expr)*) {
658                    asserts! {$(
659                        format!("{}", term!($term)) => $expected
660                    )*}
661                }
662                // 占位符
663                "_" => "_"
664                // 原子词项
665                "A" => "A"
666                "$A" => "$1" // ! 🚩【2024-06-13 23:53:31】现在「变量词项」会被重新命名
667                "#A" => "#1" // ! 🚩【2024-06-13 23:53:31】现在「变量词项」会被重新命名
668                "?A" => "?1" // ! 🚩【2024-06-13 23:53:31】现在「变量词项」会被重新命名
669                // 复合词项
670                "{A, B}" => "{}(A B)"
671                "[A, B]" => "[](A B)"
672                "(&, A, B)" => "&(A B)"
673                "(|, A, B)" => "|(A B)"
674                "(-, A, B)" => "(A - B)"
675                "(~, A, B)" => "(A ~ B)"
676                "(*, A, B)" => "*(A B)"
677                r"(/, R, _)" => r"/(R _)"
678                r"(\, R, _)" => r"\(R _)"
679                r"(/, R, _, A)" => r"/(R _ A)"
680                r"(\, R, _, A)" => r"\(R _ A)"
681                r"(&&, A, B)" => r"&&(A B)"
682                r"(||, A, B)" => r"||(A B)"
683                r"(--, A)" => r"(-- A)"
684                // 陈述
685                "<A --> B>" => "(A --> B)"
686                "<A <-> B>" => "(A <-> B)"
687                "<A ==> B>" => "(A ==> B)"
688                "<A <=> B>" => "(A <=> B)"
689            }
690            ok!()
691        }
692
693        #[test]
694        fn for_each_atom() -> AResult {
695            fn test(term: Term, expected: &[Term]) {
696                // 构造列表
697                let mut v = vec![];
698                // 遍历,复制,添加
699                term.for_each_atom(&mut |t| v.push(t.clone()));
700                // 断言
701                assert_eq!(v, expected);
702            }
703            macro_once! {
704                // * 🚩模式:词项字符串 ⇒ 预期词项字符串序列
705                macro for_each_atom($($term:literal => [ $($expected:expr),* ] )*) {
706                    $( test(term!($term), &term!([ $($expected),* ])); )*
707                }
708                // 简单情况(一层) //
709                // 占位符
710                "_" => ["_"]
711                // 原子词项
712                "A" => ["A"]
713                "$A" => ["$A"]
714                "#A" => ["#A"]
715                "?A" => ["?A"]
716                // 复合词项
717                "{A, B}" => ["A", "B"]
718                "[A, B]" => ["A", "B"]
719                "(&, A, B)" => ["A", "B"]
720                "(|, A, B)" => ["A", "B"]
721                "(-, A, B)" => ["A", "B"]
722                "(~, A, B)" => ["A", "B"]
723                "(*, A, B)" => ["A", "B"]
724                r"(/, R, _)" => ["R", "_"] // ! ⚠️【2024-06-13 17:47:14】现在会包含占位符了
725                r"(\, R, _)" => ["R", "_"]
726                r"(/, R, _, A)" => ["R", "_", "A"]
727                r"(\, R, _, A)" => ["R", "_", "A"]
728                r"(&&, A, B)" => ["A", "B"]
729                r"(||, A, B)" => ["A", "B"]
730                r"(--, A)" => ["A"]
731                // 陈述
732                "<A --> B>" => ["A", "B"]
733                "<A <-> B>" => ["A", "B"]
734                "<A ==> B>" => ["A", "B"]
735                "<A <=> B>" => ["A", "B"]
736                // 复杂情况 //
737                // 复合词项后置,同时递归深入
738                "(&&, A, B, [C, D])" => ["A", "B", "C", "D"]
739                "<(--, (--, (--, (--, (--, (--, (--, (--, A)))))))) ==> <(-, B, C) --> (*, (*, (*, (*, (*, D)))))>>" => ["A", "B", "C", "D"]
740                "<<A --> B> ==> <C --> D>>" => ["A", "B", "C", "D"]
741            }
742            ok!()
743        }
744
745        // TODO: 【2024-06-16 12:40:20】增加「判等⇔排序」的测试
746    }
747
748    /// 测试 / [`TermComponents`]
749    mod term_components {
750        use super::*;
751        use nar_dev_utils::macro_once;
752
753        /// 测试/长度
754        #[test]
755        fn len() -> AResult {
756            macro_once! {
757                // * 🚩模式:词项字符串 ⇒ 预期结果
758                macro asserts_len($( $term:literal => $s:expr )*) {
759                    asserts! { $( term!($term).components.len() => $s )* }
760                }
761                // 平常情况
762                "B" => 0
763                "?quine" => 0
764                "<A --> B>" => 2
765                "(*, {SELF}, x, y)" => 3
766                "(--, [good])" => 1
767                // 像:占位符现已计入
768                "(/, A, _, B)" => 3
769                // 集合:缩并
770                "[2, 1, 0, 0, 1, 2]" => 3
771            }
772            ok!()
773        }
774
775        /// 测试/判空
776        #[test]
777        fn is_empty() -> AResult {
778            macro_once! {
779                // * 🚩模式:词项字符串 ⇒ 预期结果
780                macro is_empty($($term:literal => $expected:expr)*) {
781                    asserts! { $( term!($term).components.is_empty() => $expected )* }
782                }
783                "B" => true
784                "?quine" => true
785                "<A --> B>" => false
786                "(*, {SELF}, x, y)" => false
787                "(--, [good])" => false
788                "(/, A, _, B)" => false
789                "[2, 1, 0, 0, 1, 2]" => false
790            }
791            ok!()
792        }
793
794        /// 测试/获取
795        #[test]
796        fn get() -> AResult {
797            macro_once! {
798                // * 🚩模式:词项字符串.索引 ⇒ 预期结果
799                macro get($($s:literal . $i:expr => $expected:expr)*) {
800                    asserts! { $(
801                        term!($s).components.get($i) => $expected
802                    )* }
803                }
804                // 平常情况
805                "B".0 => None
806                "?quine".0 => None
807                "<A --> B>".0 => Some(&term!("A"))
808                "<A --> B>".1 => Some(&term!("B"))
809                "<A --> B>".2 => None
810                "{SELF}".0 => Some(&term!("SELF"))
811                "{SELF}".1 => None
812                "(*, {SELF}, x, y)".0 => Some(&term!("{SELF}"))
813                "(*, {SELF}, x, y)".1 => Some(&term!("x"))
814                "(*, {SELF}, x, y)".2 => Some(&term!("y"))
815                "(*, {SELF}, x, y)".3 => None
816                "(--, [good])".0 => Some(&term!("[good]"))
817                "(--, [good])".1 => None
818                // 像:【2024-06-13 17:50:45】占位符现已计入
819                "(/, A, _, B)".0 => Some(&term!("A"))
820                "(/, A, _, B)".1 => Some(&term!("_")) // ! 【2024-06-13 17:51:45】构造占位符目前是被允许的
821                "(/, A, _, B)".2 => Some(&term!("B"))
822                "(/, A, _, B)".3 => None
823                // 集合:排序 & 缩并
824                "[2, 1, 0, 0, 1, 2]".0 => Some(&term!("0"))
825                "[2, 1, 0, 0, 1, 2]".1 => Some(&term!("1"))
826                "[2, 1, 0, 0, 1, 2]".2 => Some(&term!("2"))
827                "[2, 1, 0, 0, 1, 2]".3 => None
828            }
829            ok!()
830        }
831
832        /// 测试/获取
833        #[test]
834        fn get_unchecked() -> AResult {
835            macro_once! {
836                // * 🚩模式:词项字符串.索引 ⇒ 预期结果
837                macro get_unchecked($($s:literal . $i:expr => $expected:expr)*) {
838                    unsafe { asserts! { $(
839                        term!($s).components.get_unchecked($i) => $expected
840                    )* } }
841                }
842                // 平常情况
843                "<A --> B>".0 => &term!("A")
844                "<A --> B>".1 => &term!("B")
845                "{SELF}".0 => &term!("SELF")
846                "(*, {SELF}, x, y)".0 => &term!("{SELF}")
847                "(*, {SELF}, x, y)".1 => &term!("x")
848                "(*, {SELF}, x, y)".2 => &term!("y")
849                "(--, [good])".0 => &term!("[good]")
850                // 像:【2024-06-13 17:50:45】占位符现已计入
851                "(/, A, _, B)".0 => &term!("A")
852                "(/, A, _, B)".1 => &term!("_")
853                "(/, A, _, B)".2 => &term!("B")
854                // 集合:排序 & 缩并
855                "[2, 1, 0, 0, 1, 2]".0 => &term!("0")
856                "[2, 1, 0, 0, 1, 2]".1 => &term!("1")
857                "[2, 1, 0, 0, 1, 2]".2 => &term!("2")
858            }
859            ok!()
860        }
861
862        /// 测试/迭代器
863        /// * 🚩转换为数组,然后跟数组比对
864        #[test]
865        fn iter() -> AResult {
866            macro_once! {
867                // * 🚩模式:词项字符串 ⇒ 预期结果
868                macro iter($($s:literal => $expected:expr)*) {
869                    asserts! { $(
870                        term!($s).components.iter().collect::<Vec<_>>() => $expected
871                    )* }
872                }
873                // 平常情况
874                "<A --> B>" => term!(["A", "B"]&)
875                "{SELF}" => term!(["SELF"]&)
876                "(*, {SELF}, x, y)" => term!(["{SELF}", "x", "y"]&)
877                "(--, [good])" => term!(["[good]"]&)
878                // 像:【2024-06-13 17:50:45】占位符现已计入
879                "(/, A, _, B)" => term!(["A", "_", "B"]&)
880                // 集合:排序 & 缩并
881                "[2, 1, 0, 0, 1, 2]" => term!(["0", "1", "2"]&)
882            }
883            ok!()
884        }
885
886        #[test]
887        fn sort_dedup() -> AResult {
888            macro_once! {
889                // * 🚩模式:词项字符串 ⇒ 预期结果
890                macro sort_dedup($($s:literal => $expected:literal)*) {
891                    $(
892                        // 构造词项
893                        let mut term = term!($s);
894                        print!("{term}");
895                        // 重排词项
896                        term.components = term.components.sort_dedup();
897                        // 验证结果
898                        let expected = term!($expected);
899                        println!(" => {term}");
900                        assert_eq!(term, expected);
901                    )*
902                }
903                // 重排
904                "(*, B, C, A)" => "(*, A, B, C)"
905                "(*, 2, 1, 3)" => "(*, 1, 2, 3)"
906                "(/, R, T, _, S)" => "(/, R, S, T, _)" // ! ⚠️【2024-06-13 17:53:13】占位符现已被计入
907                "{[C], $B, A}" => "{A, $B, [C]}"
908                "(*, あ, え, い, お, う)" => "(*, あ, い, う, え, お)"
909                "(*, ア, エ, イ, オ, ウ)" => "(*, ア, イ, ウ, エ, オ)"
910                "(*, 一, 丄, 七, 丁, 丂)" => "(*, 一, 丁, 丂, 七, 丄)"
911                // 去重
912                "(*, F, A, D, E, D)" => "(*, A, D, E, F)"
913                "(*, 1, 1, 4, 5, 1, 4)" => "(*, 1, 4, 5)"
914            }
915            ok!()
916        }
917
918        // ! 以下函数已在 `Term` 中测试
919        // * contain_type
920        // * structural_match
921    }
922}