1use crate::language::*;
34use crate::symbols::*;
35use nar_dev_utils::matches_or;
36use narsese::api::{GetCapacity, TermCapacity};
37use std::{
38 fmt::{Display, Formatter},
39 ops::{Deref, DerefMut},
40};
41
42pub(in crate::language) mod vec_utils {
45 use crate::language::Term;
46
47 pub fn remove(vec: &mut Vec<Term>, term: &Term) -> bool {
49 let position = vec.iter().position(|t| t == term);
68 match position {
69 Some(i) => {
70 vec.remove(i);
71 true
72 }
73 None => false,
74 }
75 }
76
77 pub fn remove_all(vec: &mut Vec<Term>, terms: &[Term]) -> bool {
79 let mut removed = false;
82 for term in terms {
83 if remove(vec, term) {
85 removed = true;
86 }
87 }
88 removed
89 }
90
91 pub fn retain_all(vec: &mut Vec<Term>, terms: &[Term]) {
94 vec.retain(|t| terms.contains(t));
95 }
96}
97
98impl Term {
100 pub fn instanceof_compound_pure(&self) -> bool {
103 matches!(
104 self.identifier(),
105 SET_EXT_OPERATOR
106 | SET_INT_OPERATOR
107 | INTERSECTION_EXT_OPERATOR
108 | INTERSECTION_INT_OPERATOR
109 | DIFFERENCE_EXT_OPERATOR
110 | DIFFERENCE_INT_OPERATOR
111 | PRODUCT_OPERATOR
112 | IMAGE_EXT_OPERATOR
113 | IMAGE_INT_OPERATOR
114 | CONJUNCTION_OPERATOR
115 | DISJUNCTION_OPERATOR
116 | NEGATION_OPERATOR
117 )
118 }
119
120 #[must_use]
125 pub fn as_compound_type(&self, compound_class: impl AsRef<str>) -> Option<CompoundTermRef> {
126 matches_or! {
127 ?self.as_compound(),
128 Some(compound)
129 if compound_class.as_ref() == self.identifier()
131 => compound
133 }
134 }
135
136 #[must_use]
141 pub fn unwrap_compound_id_components(self) -> Option<(String, Box<[Term]>)> {
142 matches_or! {
143 ?self.unwrap_id_comp(),
144 (
146 identifier,
148 TermComponents::Compound(terms)
150 )
151 => (identifier, terms)
153 }
154 }
155
156 #[must_use]
161 pub fn unwrap_compound_components(self) -> Option<Box<[Term]>> {
162 matches_or! {
163 ?self.unwrap_id_comp(),
164 (
166 _,
167 TermComponents::Compound(terms)
169 )
170 => terms
172 }
173 }
174
175 #[must_use]
180 pub fn unwrap_compound_type_components(
181 self,
182 compound_class: impl AsRef<str>,
183 ) -> Option<Box<[Term]>> {
184 matches_or! {
185 ?self.unwrap_id_comp(),
186 (
188 identifier,
189 TermComponents::Compound(terms)
191 )
192 if identifier.as_str() == compound_class.as_ref()
194 => terms
196 }
197 }
198
199 #[inline(always)]
203 pub fn instanceof_compound(&self) -> bool {
204 self.instanceof_compound_pure() || self.instanceof_statement()
205 }
206
207 #[inline(always)]
211 pub fn instanceof_set_ext(&self) -> bool {
212 self.identifier() == SET_EXT_OPERATOR
213 }
214
215 #[inline(always)]
219 pub fn instanceof_set_int(&self) -> bool {
220 self.identifier() == SET_INT_OPERATOR
221 }
222
223 #[inline(always)]
226 pub fn instanceof_set(&self) -> bool {
227 self.instanceof_set_ext() || self.instanceof_set_int()
228 }
229
230 #[inline(always)]
234 pub fn instanceof_intersection_ext(&self) -> bool {
235 self.identifier() == INTERSECTION_EXT_OPERATOR
236 }
237
238 #[inline(always)]
242 pub fn instanceof_intersection_int(&self) -> bool {
243 self.identifier() == INTERSECTION_INT_OPERATOR
244 }
245
246 #[inline(always)]
250 pub fn instanceof_intersection(&self) -> bool {
251 self.instanceof_intersection_ext() || self.instanceof_intersection_int()
252 }
253
254 #[inline(always)]
258 pub fn instanceof_difference_ext(&self) -> bool {
259 self.identifier() == DIFFERENCE_EXT_OPERATOR
260 }
261
262 #[inline(always)]
266 pub fn instanceof_difference_int(&self) -> bool {
267 self.identifier() == DIFFERENCE_INT_OPERATOR
268 }
269
270 #[inline(always)]
273 pub fn instanceof_difference(&self) -> bool {
274 self.instanceof_difference_ext() || self.instanceof_difference_int()
275 }
276
277 #[inline(always)]
281 pub fn instanceof_product(&self) -> bool {
282 self.identifier() == PRODUCT_OPERATOR
283 }
284
285 #[inline(always)]
289 pub fn instanceof_image_ext(&self) -> bool {
290 self.identifier() == IMAGE_EXT_OPERATOR
291 }
292
293 #[inline(always)]
297 pub fn instanceof_image_int(&self) -> bool {
298 self.identifier() == IMAGE_INT_OPERATOR
299 }
300
301 #[inline(always)]
304 pub fn instanceof_image(&self) -> bool {
305 self.instanceof_image_ext() || self.instanceof_image_int()
306 }
307
308 #[inline(always)]
312 pub fn instanceof_conjunction(&self) -> bool {
313 self.identifier() == CONJUNCTION_OPERATOR
314 }
315
316 #[inline(always)]
320 pub fn instanceof_disjunction(&self) -> bool {
321 self.identifier() == DISJUNCTION_OPERATOR
322 }
323 #[inline(always)]
326 pub fn instanceof_junction(&self) -> bool {
327 self.instanceof_conjunction() || self.instanceof_disjunction()
328 }
329
330 #[inline(always)]
334 pub fn instanceof_negation(&self) -> bool {
335 self.identifier() == NEGATION_OPERATOR
336 }
337
338 #[doc(alias = "is_symmetric")]
351 pub fn is_commutative(&self) -> bool {
352 matches!(
353 self.identifier(),
354 SET_EXT_OPERATOR
356 | SET_INT_OPERATOR
357 | INTERSECTION_EXT_OPERATOR
358 | INTERSECTION_INT_OPERATOR
359 | SIMILARITY_RELATION
361 | EQUIVALENCE_RELATION
362 | DISJUNCTION_OPERATOR
364 | CONJUNCTION_OPERATOR
365 )
366 }
367
368 #[inline(always)]
373 pub fn structural_match(&self, other: &Self) -> bool {
374 self.is_same_type(other)
375 && self
377 .components()
378 .structural_match(other.components())
379 }
380
381 pub fn is_compound(&self) -> bool {
386 matches!(self.components(), TermComponents::Compound(..))
387 }
388
389 #[must_use]
393 pub fn as_compound(&self) -> Option<CompoundTermRef> {
394 matches_or!(
395 ?self.components(),
396 TermComponents::Compound(ref c) => CompoundTermRef {
397 inner: self,
398 components: c
399 }
400 )
401 }
402
403 #[must_use]
407 pub fn as_compound_and(
408 &self,
409 predicate: impl FnOnce(&CompoundTermRef) -> bool,
410 ) -> Option<CompoundTermRef> {
411 match self.as_compound() {
412 Some(compound) if predicate(&compound) => Some(compound),
413 _ => None,
414 }
415 }
416
417 #[must_use]
425 pub unsafe fn as_compound_unchecked(&self) -> CompoundTermRef {
426 debug_assert!(self.is_compound(), "转换前必须假定其为复合词项");
428 match self.components() {
430 TermComponents::Compound(ref c) => CompoundTermRef {
431 inner: self,
432 components: c,
433 },
434 _ => unsafe { core::hint::unreachable_unchecked() },
436 }
437 }
438
439 #[must_use]
442 pub fn as_compound_mut(&mut self) -> Option<CompoundTermRefMut> {
443 matches_or! {
444 ?self.components_mut(),
447 TermComponents::Compound(components) => CompoundTermRefMut {
448 components: &mut **components as *mut [Term],
451 inner :self,
452 }
453 }
454 }
455
456 #[must_use]
464 pub unsafe fn as_compound_mut_unchecked(&mut self) -> CompoundTermRefMut {
465 debug_assert!(self.is_compound(), "转换前必须假定其为复合词项");
467 match self.components_mut() {
469 TermComponents::Compound(components) => CompoundTermRefMut {
470 components: &mut **components as *mut [Term],
473 inner: self,
474 },
475 _ => unsafe { core::hint::unreachable_unchecked() },
477 }
478 }
479}
480
481impl GetCapacity for Term {
483 fn get_capacity(&self) -> TermCapacity {
484 use TermCapacity::*;
485 match self.identifier() {
486 WORD | PLACEHOLDER | VAR_INDEPENDENT | VAR_DEPENDENT | VAR_QUERY => Atom,
488 NEGATION_OPERATOR => Unary,
490 DIFFERENCE_EXT_OPERATOR
492 | DIFFERENCE_INT_OPERATOR
493 | INHERITANCE_RELATION
494 | IMPLICATION_RELATION => BinaryVec,
495 SIMILARITY_RELATION | EQUIVALENCE_RELATION => BinarySet,
497 PRODUCT_OPERATOR | IMAGE_EXT_OPERATOR | IMAGE_INT_OPERATOR => Vec,
499 SET_EXT_OPERATOR
501 | SET_INT_OPERATOR
502 | INTERSECTION_EXT_OPERATOR
503 | INTERSECTION_INT_OPERATOR
504 | CONJUNCTION_OPERATOR
505 | DISJUNCTION_OPERATOR => Set,
506 id => panic!("Unexpected compound term identifier: {id}"),
508 }
509 }
510}
511
512#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
515pub struct CompoundTermRef<'a> {
516 pub inner: &'a Term,
518 pub components: &'a [Term],
520}
521
522impl<'s> CompoundTermRef<'s> {
523 #[inline]
532 pub fn size(&self) -> usize {
533 self.components.len()
534 }
535
536 #[inline]
544 pub fn component_at(self, index: usize) -> Option<&'s Term> {
545 self.components.get(index)
546 }
547
548 #[inline]
561 pub unsafe fn component_at_unchecked(&self, index: usize) -> &Term {
562 self.components.get_unchecked(index)
563 }
564
565 #[inline]
575 pub(super) fn get_components(&self) -> impl Iterator<Item = &Term> {
576 self.components.iter()
577 }
578
579 pub fn index_of_component(&self, t: &Term) -> Option<usize> {
585 self.components.iter().position(|term| term == t)
586 }
587
588 pub fn clone_components(&self) -> Vec<Term> {
597 self.components.to_vec()
598 }
599
600 pub fn clone_component_refs(&self) -> Vec<&Term> {
603 self.components.iter().collect()
604 }
605
606 pub fn contain_component(&self, component: &Term) -> bool {
614 self.get_components().any(|term| term == component)
615 }
616
617 pub fn contain_term(&self, term: &Term) -> bool {
625 self.get_components()
626 .any(|sub_term| match sub_term.as_compound() {
627 None => term == sub_term,
629 Some(sub_compound) => sub_compound.contain_term(term),
631 })
632 }
633
634 pub fn contain_all_components(&self, other: &Term) -> bool {
644 match self.inner.is_same_type(other) {
645 true => match other.as_compound() {
647 Some(other) => other
649 .get_components()
650 .all(|should_in| self.contain_component(should_in)),
651 _ => false,
652 },
653 false => self.contain_component(other),
654 }
655 }
656
657 pub fn as_conditional(self) -> Option<(StatementRef<'s>, CompoundTermRef<'s>)> {
662 self.as_statement()?.as_conditional()
663 }
664}
665
666impl Display for CompoundTermRef<'_> {
668 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
669 self.inner.fmt(f)
670 }
671}
672
673impl Deref for CompoundTermRef<'_> {
676 type Target = Term;
677
678 fn deref(&self) -> &Self::Target {
679 self.inner
680 }
681}
682
683#[derive(Debug, PartialEq, Eq, Hash)]
688pub struct CompoundTermRefMut<'a> {
689 pub(super) inner: &'a mut Term,
691 pub(super) components: *mut [Term],
694}
695
696impl CompoundTermRefMut<'_> {
697 pub fn inner(&mut self) -> &mut Term {
699 self.inner
700 }
701
702 pub fn components(&mut self) -> &mut [Term] {
709 debug_assert!(self.inner.is_compound());
717 unsafe { &mut *self.components }
720 }
721
722 pub fn into_ref<'s>(self) -> CompoundTermRef<'s>
729 where
730 Self: 's,
731 {
732 debug_assert!(self.inner.is_compound());
734 CompoundTermRef {
736 inner: self.inner,
737 components: unsafe { &*self.components },
739 }
740 }
741
742 pub fn reorder_components(&mut self) {
751 let mut placeholder = TermComponents::Empty;
753 std::mem::swap(&mut placeholder, self.inner.components_mut());
754 let new_components = placeholder.sort_dedup();
756 *self.inner.components_mut() = new_components;
758 }
759}
760
761impl Display for CompoundTermRefMut<'_> {
763 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
764 self.inner.fmt(f)
765 }
766}
767
768impl Deref for CompoundTermRefMut<'_> {
773 type Target = Term;
774
775 fn deref(&self) -> &Self::Target {
776 self.inner
777 }
778}
779
780impl DerefMut for CompoundTermRefMut<'_> {
784 fn deref_mut(&mut self) -> &mut Self::Target {
785 self.inner
786 }
787}
788
789impl<'s> From<CompoundTermRefMut<'s>> for CompoundTermRef<'s> {
791 fn from(r: CompoundTermRefMut<'s>) -> Self {
792 r.into_ref()
793 }
794}
795
796#[derive(Debug, Clone, PartialEq, Eq, Hash)]
799pub struct CompoundTerm {
800 term: Term,
802}
803
804impl CompoundTerm {
805 pub fn get_ref(&self) -> CompoundTermRef {
807 unsafe { self.term.as_compound_unchecked() }
809 }
810
811 pub fn mut_ref(&mut self) -> CompoundTermRefMut {
813 unsafe { self.term.as_compound_mut_unchecked() }
815 }
816
817 pub fn unwrap(self) -> (String, Box<[Term]>) {
820 self.term.unwrap_compound_id_components().unwrap()
821 }
822}
823
824impl TryFrom<Term> for CompoundTerm {
826 type Error = Term;
828
829 fn try_from(term: Term) -> Result<Self, Self::Error> {
830 match term.is_compound() {
832 true => Ok(Self { term }),
833 false => Err(term),
834 }
835 }
836}
837
838impl From<CompoundTerm> for Term {
840 fn from(value: CompoundTerm) -> Self {
841 value.term
842 }
843}
844
845impl Deref for CompoundTerm {
848 type Target = Term;
849
850 fn deref(&self) -> &Self::Target {
851 &self.term
852 }
853}
854
855impl DerefMut for CompoundTerm {
857 fn deref_mut(&mut self) -> &mut Self::Target {
858 &mut self.term
859 }
860}
861
862impl Display for CompoundTerm {
864 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
865 self.term.fmt(f)
866 }
867}
868
869impl CompoundTermRef<'_> {
870 #[must_use]
874 pub fn reduce_components(
875 self,
877 component_to_reduce: &Term,
878 ) -> Option<Term> {
879 let mut components = self.clone_components();
880 let success = match (
882 self.is_same_type(component_to_reduce),
883 component_to_reduce.as_compound(),
884 ) {
885 (
887 true,
888 Some(CompoundTermRef {
889 components: other_components,
890 ..
891 }),
892 ) => vec_utils::remove_all(&mut components, other_components),
893 _ => vec_utils::remove(&mut components, component_to_reduce),
895 };
896 if !success {
897 return None;
898 }
899 match components.len() {
901 2.. => Term::make_compound_term(self, components),
904 1 => match Self::can_extract_to_inner(&self) {
906 true => components.pop(),
907 false => None,
909 },
910 0 => None,
912 }
913 }
914
915 #[inline]
922 fn can_extract_to_inner(&self) -> bool {
923 matches!(
924 self.identifier(),
925 CONJUNCTION_OPERATOR
926 | DISJUNCTION_OPERATOR
927 | INTERSECTION_EXT_OPERATOR
928 | INTERSECTION_INT_OPERATOR
929 | DIFFERENCE_EXT_OPERATOR
930 | DIFFERENCE_INT_OPERATOR
931 )
932 }
933
934 #[must_use]
939 pub fn set_component(self, index: usize, term: Option<Term>) -> Option<Term> {
940 let mut list = self.clone_components();
941 list.remove(index);
942 if let Some(term) = term {
943 match (self.is_same_type(&term), term.as_compound()) {
944 (
946 true,
947 Some(CompoundTermRef {
948 components: list2, ..
949 }),
950 ) => {
951 for (i, term) in list2.iter().enumerate() {
953 list.insert(index + i, term.clone());
954 }
955 }
956 _ => list.insert(index, term),
958 }
959 }
960 Term::make_compound_term(self, list)
962 }
963}
964
965#[cfg(test)]
967pub(crate) mod tests {
968 use super::*;
969 use crate::{language::test_term::*, ok, option_term, test_term as term, util::AResult};
970 use nar_dev_utils::{asserts, macro_once, unwrap_or_return};
971
972 #[macro_export]
974 macro_rules! test_compound {
975 (box $($t:tt)*) => {
977 CompoundTerm::try_from(term!($($t)*)).unwrap()
978 };
979 (mut $($t:tt)*) => {
981 term!($($t)*).as_compound_mut().unwrap()
982 };
983 ($($t:tt)*) => {
985 term!($($t)*).as_compound().unwrap()
986 };
987 }
988
989 macro_rules! compound {
992 ($($t:tt)*) => {
993 test_compound!($($t)*)
994 };
995 }
996
997 mod term {
999 use super::*;
1000
1001 #[test]
1002 fn instanceof_compound() -> AResult {
1003 macro_once! {
1004 macro instanceof_compound($( $s:literal => $expected:expr )*) {
1006 asserts! {$(
1007 term!($s).instanceof_compound() => $expected,
1008 )*}
1009 }
1010 "_" => false
1012 "A" => false
1014 "$A" => false
1015 "#A" => false
1016 "?A" => false
1017 "{A}" => true
1019 "[A]" => true
1020 "(&, A, B)" => true "(|, A, B)" => true
1022 "(-, A, B)" => true
1023 "(~, A, B)" => true
1024 "(*, A)" => true
1025 "(/, R, _)" => true
1026 r"(\, R, _)" => true
1027 "(&&, A, B)" => true
1028 "(||, A, B)" => true
1029 "(--, A)" => true
1030 "<A --> B>" => true
1032 "<A <-> B>" => true
1033 "<A ==> B>" => true
1034 "<A <=> B>" => true
1035 }
1036 ok!()
1037 }
1038
1039 #[test]
1040 fn is_commutative() -> AResult {
1041 macro_once! {
1042 macro is_commutative($( $s:literal => $expected:expr )*) {
1044 asserts! {$(
1045 term!($s).is_commutative() => $expected,
1046 )*}
1047 }
1048 "_" => false
1050 "A" => false
1052 "$A" => false
1053 "#A" => false
1054 "?A" => false
1055 "{A}" => true
1057 "[A]" => true
1058 "(&, A, B)" => true "(|, A, B)" => true
1060 "(-, A, B)" => false
1061 "(~, A, B)" => false
1062 "(*, A)" => false
1063 "(/, R, _)" => false
1064 r"(\, R, _)" => false
1065 "(&&, A, B)" => true
1066 "(||, A, B)" => true
1067 "(--, A)" => false
1068 "<A --> B>" => false
1070 "<A <-> B>" => true
1071 "<A ==> B>" => false
1072 "<A <=> B>" => true
1073 }
1074 ok!()
1075 }
1076 }
1077
1078 mod compound_term_ref {
1080 use super::*;
1081
1082 #[test]
1083 fn deref() -> AResult {
1084 fn test(term: Term) {
1086 assert!(term.is_compound());
1088 let compound = unsafe { term.as_compound_unchecked() };
1090 dbg!(compound.identifier(), compound.components());
1092
1093 let c1 = compound; let c2 = compound.as_compound().unwrap();
1096 let c3 = term.as_compound().unwrap();
1097 dbg!(c1, c2, c3); asserts! {
1101 compound.is_compound(),
1102 compound.as_compound() => Some(compound),
1103 *compound => term, compound.clone() => compound, (*compound).clone() => term, }
1108 }
1109 macro_once! {
1110 macro test($( $term:literal )*) {$(
1112 test(term!($term));
1113 )*}
1114 "{A}"
1123 "[A]"
1124 "(&, A, B)" "(|, A, B)"
1126 "(-, A, B)"
1127 "(~, A, B)"
1128 "(*, A, B, C)"
1129 "(/, R, _)"
1130 r"(\, R, _)"
1131 "(&&, A, B)"
1132 "(||, A, B)"
1133 "(--, A)"
1134 "<A --> B>"
1136 "<A <-> B>"
1137 "<A ==> B>"
1138 "<A <=> B>"
1139 }
1140 ok!()
1141 }
1142
1143 #[test]
1144 fn size() -> AResult {
1145 macro_once! {
1146 macro size($( $s:literal => $expected:expr )*) {
1148 asserts! {$(
1149 compound!($s).size() => $expected,
1150 )*}
1151 }
1152 "{A}" => 1
1161 "[A]" => 1
1162 "(&, A, B)" => 2 "(|, A, B)" => 2
1164 "(-, A, B)" => 2
1165 "(~, A, B)" => 2
1166 "(*, A, B, C)" => 3
1167 "(/, R, _)" => 2 r"(\, R, _)" => 2
1169 "(&&, A, B)" => 2
1170 "(||, A, B)" => 2
1171 "(--, A)" => 1
1172 "<A --> B>" => 2
1174 "<A <-> B>" => 2
1175 "<A ==> B>" => 2
1176 "<A <=> B>" => 2
1177 }
1178 ok!()
1179 }
1180
1181 #[test]
1182 fn component_at() -> AResult {
1183 macro_once! {
1185 macro component_at($( $s:literal [ $index:expr ] => $expected:expr )*) {
1187 asserts! {$(
1188 compound!($s).component_at($index) => Some(&term!($expected)),
1189 )*}
1190 }
1191 "{A}"[0] => "A"
1193 "[A]"[0] => "A"
1194 "(&, A, B)"[0] => "A" "(|, A, B)"[0] => "A"
1196 "(-, A, B)"[1] => "B"
1197 "(~, A, B)"[1] => "B"
1198 "(*, A, B, C)"[2] => "C"
1199 "(/, R, _)"[0] => "R" r"(\, R, _)"[0] => "R"
1201 "(/, R, _)"[1] => "_" r"(\, R, _)"[1] => "_"
1203 "(&&, A, B)"[0] => "A"
1204 "(||, A, B)"[0] => "A"
1205 "(--, A)"[0] => "A"
1206 "<A --> B>"[0] => "A"
1208 "<A <-> B>"[0] => "A"
1209 "<A ==> B>"[0] => "A"
1210 "<A <=> B>"[0] => "A"
1211 }
1212 macro_once! {
1214 macro component_at($( $s:literal [ $index:expr ] )*) {
1216 asserts! {$(
1217 compound!($s).component_at($index) => None,
1218 )*}
1219 }
1220 "{A}"[1]
1229 "[A]"[1]
1230 "(&, A, B)"[2] "(|, A, B)"[2]
1232 "(-, A, B)"[2]
1233 "(~, A, B)"[2]
1234 "(*, A, B, C)"[3]
1235 "(/, R, _)"[2] r"(\, R, _)"[2]
1237 "(&&, A, B)"[2]
1238 "(||, A, B)"[2]
1239 "(--, A)"[1]
1240 "<A --> B>"[2]
1242 "<A <-> B>"[2]
1243 "<A ==> B>"[2]
1244 "<A <=> B>"[2]
1245 }
1246 ok!()
1247 }
1248
1249 #[test]
1250 fn component_at_unchecked() -> AResult {
1251 macro_once! {
1253 macro component_at_unchecked($( $s:literal [ $index:expr ] => $expected:expr )*) {
1255 unsafe {
1256 asserts! {$(
1257 compound!($s).component_at_unchecked($index) => &term!($expected),
1258 )*}
1259 }
1260 }
1261 "{A}"[0] => "A"
1263 "[A]"[0] => "A"
1264 "(&, A, B)"[0] => "A" "(|, A, B)"[0] => "A"
1266 "(-, A, B)"[1] => "B"
1267 "(~, A, B)"[1] => "B"
1268 "(*, A, B, C)"[2] => "C"
1269 "(/, R, _)"[0] => "R" r"(\, R, _)"[0] => "R"
1271 "(&&, A, B)"[0] => "A"
1272 "(||, A, B)"[0] => "A"
1273 "(--, A)"[0] => "A"
1274 "<A --> B>"[0] => "A"
1276 "<A <-> B>"[0] => "A"
1277 "<A ==> B>"[0] => "A"
1278 "<A <=> B>"[0] => "A"
1279 }
1280 ok!()
1281 }
1282
1283 #[test]
1286 fn clone_components() -> AResult {
1287 macro_once! {
1288 macro clone_components($($s:literal)*) {
1290 asserts! {$(
1291 compound!($s).clone_components() => term!($s).components().iter().cloned().collect::<Vec<_>>(),
1293 )*}
1294 }
1295 "{A}"
1304 "[A]"
1305 "(&, A, B)" "(|, A, B)"
1307 "(-, A, B)"
1308 "(~, A, B)"
1309 "(*, A)"
1310 "(/, R, _)"
1311 r"(\, R, _)"
1312 "(&&, A, B)"
1313 "(||, A, B)"
1314 "(--, A)"
1315 "<A --> B>"
1317 "<A <-> B>"
1318 "<A ==> B>"
1319 "<A <=> B>"
1320 }
1321 ok!()
1322 }
1323
1324 #[test]
1325 fn contain_component() -> AResult {
1326 macro_once! {
1327 macro contain_component($($term:literal in $container:expr)*) {
1329 asserts! {$(
1330 compound!($container).contain_component(&term!($term))
1331 )*}
1332 }
1333 "A" in "{A}"
1335 "A" in "[A]"
1336 "A" in "(&, A, B)" "A" in "(|, A, B)"
1338 "A" in "(-, A, B)"
1339 "A" in "(~, A, B)"
1340 "B" in "(-, A, B)"
1341 "B" in "(~, A, B)"
1342 "A" in "(*, A)"
1343 "R" in "(/, R, _)"
1344 "R" in r"(\, R, _)"
1345 "_" in "(/, R, _)" "_" in r"(\, R, _)" "A" in "(&&, A, B)"
1348 "A" in "(||, A, B)"
1349 "A" in "(--, A)"
1350 "A" in "<A --> B>"
1352 "A" in "<A <-> B>"
1353 "A" in "<A ==> B>"
1354 "A" in "<A <=> B>"
1355 "B" in "<A --> B>"
1356 "B" in "<A <-> B>"
1357 "B" in "<A ==> B>"
1358 "B" in "<A <=> B>"
1359 }
1360 macro_once! {
1361 macro contain_component($($term:literal !in $container:expr)*) {
1363 asserts! {$(
1364 !compound!($container).contain_component(&term!($term))
1365 )*}
1366 }
1367 "X" !in "{A}"
1369 "X" !in "[A]"
1370 "X" !in "(&, A, B)" "X" !in "(|, A, B)"
1372 "X" !in "(-, A, B)"
1373 "X" !in "(~, A, B)"
1374 "X" !in "(*, A)"
1375 "X" !in "(/, R, _)"
1376 "X" !in r"(\, R, _)"
1377 "X" !in "(&&, A, B)"
1378 "X" !in "(||, A, B)"
1379 "X" !in "(--, A)"
1380 "C" !in "<A --> B>"
1382 "C" !in "<A <-> B>"
1383 "C" !in "<A ==> B>"
1384 "C" !in "<A <=> B>"
1385 }
1386 ok!()
1387 }
1388
1389 #[test]
1390 fn contain_term() -> AResult {
1391 macro_once! {
1392 macro contain_term($($term:literal in $container:expr)*) {
1394 asserts! {$(
1395 compound!($container).contain_term(&term!($term))
1396 )*}
1397 }
1398 "A" in "{{{{{{A}}}}}}"
1400 "A" in "[[[[[[A]]]]]]"
1401 "A" in "(&, (&, (&, (&, (&, A, B), B), B), B), B)"
1402 "A" in "(|, (|, (|, (|, (|, A, B), B), B), B), B)"
1403 "A" in "(-, (-, A, a), (-, B, b))"
1404 "A" in "(~, (~, A, a), (~, B, b))"
1405 "B" in "(-, (-, A, a), (-, B, b))"
1406 "B" in "(~, (~, A, a), (~, B, b))"
1407 "A" in "(*, (*, (*, (*, (*, A)))))"
1408 "R" in "(/, (/, (/, (/, (/, R, _), _), _), _), _)"
1409 "R" in r"(\, (\, (\, (\, (\, R, _), _), _), _), _)"
1410 "A" in "(&&, (&&, (&&, (&&, (&&, A, B), B), B), B), B)"
1411 "A" in "(||, (||, (||, (||, (||, A, B), B), B), B), B)"
1412 "A" in "(--, (--, (--, (--, (--, A)))))"
1413 "A" in "<<A --> a> --> <B ==> b>>"
1415 "B" in "<<A --> a> --> <B ==> b>>"
1416 "A" in "<<A <-> a> <-> <B <=> b>>"
1417 "B" in "<<A <-> a> <-> <B <=> b>>"
1418 "A" in "<<A --> a> ==> <B ==> b>>"
1419 "B" in "<<A --> a> ==> <B ==> b>>"
1420 "A" in "<<A <-> a> <=> <B <=> b>>"
1421 "B" in "<<A <-> a> <=> <B <=> b>>"
1422 }
1423 macro_once! {
1424 macro contain_term($($term:literal !in $container:expr)*) {
1426 asserts! {$(
1427 !compound!($container).contain_term(&term!($term))
1428 )*}
1429 }
1430 "X" !in "{{{{{{A}}}}}}"
1432 "X" !in "[[[[[[A]]]]]]"
1433 "X" !in "(&, (&, (&, (&, (&, A, B), B), B), B), B)"
1434 "X" !in "(|, (|, (|, (|, (|, A, B), B), B), B), B)"
1435 "X" !in "(-, (-, A, a), (-, B, b))"
1436 "X" !in "(~, (~, A, a), (~, B, b))"
1437 "X" !in "(*, (*, (*, (*, (*, A)))))"
1438 "X" !in "(/, (/, (/, (/, (/, R, _), _), _), _), _)"
1439 "X" !in r"(\, (\, (\, (\, (\, R, _), _), _), _), _)"
1440 "X" !in "(&&, (&&, (&&, (&&, (&&, A, B), B), B), B), B)"
1441 "X" !in "(||, (||, (||, (||, (||, A, B), B), B), B), B)"
1442 "X" !in "(--, (--, (--, (--, (--, A)))))"
1443 "X" !in "<<A --> a> --> <B ==> b>>"
1445 "X" !in "<<A --> a> --> <B ==> b>>"
1446 "X" !in "<<A <-> a> <-> <B <=> b>>"
1447 "X" !in "<<A <-> a> <-> <B <=> b>>"
1448 }
1449 ok!()
1450 }
1451
1452 #[test]
1453 fn contain_all_components() -> AResult {
1454 macro_once! {
1455 macro test($($term:literal in $container:expr)*) {
1457 asserts! {$(
1458 compound!($container).contain_all_components(&term!($term))
1459 )*}
1460 }
1461 "A" in "{A}"
1463 "{A}" in "{A}"
1464 "{A}" in "{A, B}"
1465 "{A}" in "{A, B, C}"
1466 "{B}" in "{A, B, C}"
1467 "{C}" in "{A, B, C}"
1468 "{A, B}" in "{A, B, C}"
1469 "{A, C}" in "{A, B, C}"
1470 "{B, C}" in "{A, B, C}"
1471 "{A, B, C}" in "{A, B, C}"
1472 "A" in "(-, A, B)"
1473 "B" in "(-, A, B)"
1474 "(-, A, B)" in "(-, A, B)"
1475 "A" in "(*, A, B, C, D, E)"
1476 "(*, A)" in "(*, A, B, C, D, E)"
1477 "(*, A, B)" in "(*, A, B, C, D, E)"
1478 "(*, E, B)" in "(*, A, B, C, D, E)"
1479 "(*, E, A)" in "(*, A, B, C, D, E)"
1480 "R" in "(/, R, _)"
1481 "_" in "(/, R, _)"
1482 "R" in "(/, R, _, (*, A))"
1483 "_" in "(/, R, _, (*, A))"
1484 "(*, A)" in "(/, R, _, (*, A))"
1485 "(/, R, _)" in "(/, R, _, (*, A))"
1486 "R" in r"(\, R, _)"
1487 "_" in r"(\, R, _)"
1488 "R" in r"(\, R, _, (*, A))"
1489 "_" in r"(\, R, _, (*, A))"
1490 "(*, A)" in r"(\, R, _, (*, A))"
1491 r"(\, R, _)" in r"(\, R, _, (*, A))"
1492 "A" in "<A --> B>"
1494 "B" in "<A --> B>"
1495 "<A --> B>" in "<A --> B>"
1496 "<B --> A>" in "<A --> B>"
1497 "A" in "<A <-> B>"
1498 "B" in "<A <-> B>"
1499 "<A <-> B>" in "<A <-> B>"
1500 "<B <-> A>" in "<A <-> B>"
1501 "A" in "<A ==> B>"
1502 "B" in "<A ==> B>"
1503 "<A ==> B>" in "<A ==> B>"
1504 "<B ==> A>" in "<A ==> B>"
1505 "A" in "<A <=> B>"
1506 "B" in "<A <=> B>"
1507 "<A <=> B>" in "<A <=> B>"
1508 "<B <=> A>" in "<A <=> B>"
1509 }
1510 ok!()
1511 }
1512
1513 #[test]
1514 fn can_extract() -> AResult {
1515 fn test(term: Term, expected: bool) {
1516 let compound = term.as_compound().unwrap();
1517 assert_eq!(compound.can_extract_to_inner(), expected);
1518 }
1519 macro_once! {
1520 macro test($($term:expr => $expected:expr)*) {
1522 $( test(term!($term), $expected); )*
1523 }
1524 "(&&, A, B)" => true
1526 "(||, A, B)" => true
1527 "(&, A, B)" => true
1528 "(|, A, B)" => true
1529 "(-, A, B)" => true
1530 "(~, A, B)" => true
1531 "{A}" => false
1533 "[A]" => false
1534 }
1535 ok!()
1536 }
1537
1538 #[test]
1539 fn reduce_components() -> AResult {
1540 fn test(compound_str: &str, term_str: &str, expected: Option<Term>) {
1545 let compound: Term = unwrap_or_return!(@compound_str.parse(), err => eprintln!("{compound_str:?}解析失败: {err}"));
1547 let term: Term = unwrap_or_return!(@term_str.parse(), err => eprintln!("{term_str:?}解析失败: {err}"));
1548 let compound_ref = compound.as_compound().expect("构造出来的不是复合词项");
1550 let out = CompoundTermRef::reduce_components(compound_ref, &term);
1552 assert_eq!(
1554 out,
1555 expected,
1556 "{compound_str:?}, {term_str:?} => {} != {}",
1557 format_option_term(&out),
1558 format_option_term(&expected),
1559 );
1560 }
1561 macro_once! {
1562 macro test($($compound:tt, $term:tt => $expected:tt;)*) {
1564 $( test($compound, $term, option_term!($expected)); )*
1565 }
1566 "(&&,<(&,bird,gull) --> bird>,<(&,bird,gull) --> [swimmer]>)", "<(&,bird,gull) --> [swimmer]>" => "<(&,bird,gull) --> bird>"; "(&&,<(&,bird,swan) --> [bird]>,<(&,bird,swan) --> [swimmer]>)", "<(&,bird,swan) --> [swimmer]>" => "<(&,bird,swan) --> [bird]>";
1573 "(&&,<(&,bird,swimmer) --> (&,animal,swimmer)>,<(&,bird,swimmer) --> (|,swan,swimmer)>)", "<(&,bird,swimmer) --> (&,animal,swimmer)>" => "<(&,bird,swimmer) --> (|,swan,swimmer)>";
1574 "(&&,<(&,chess,sport) --> chess>,<(&,chess,sport) --> competition>)", "<(&,chess,sport) --> competition>" => "<(&,chess,sport) --> chess>"; "(&&,<(&,key,(/,open,_,lock)) --> key>,<(&,key,(/,open,_,lock)) --> (/,open,_,{lock1})>)", "<(&,key,(/,open,_,lock)) --> (/,open,_,{lock1})>" => "<(&,key,(/,open,_,lock)) --> key>"; "(&&,<(*,0) --> (*,(/,num,_))>,<{0} --> (*,(/,num,_))>)", "<(*,0) --> (*,(/,num,_))>" => "<{0} --> (*,(/,num,_))>";
1577 "(&&,<(*,0) --> (*,{0})>,<(*,(*,0)) --> (*,{0})>)", "<(*,(*,0)) --> (*,{0})>" => "<(*,0) --> (*,{0})>";
1578 "(&&,<(*,0) --> (/,num,_)>,<(*,0) --> [num]>)", "<(*,0) --> (/,num,_)>" => "<(*,0) --> [num]>";
1579 "(&&,<(*,0) --> num>,<(/,num,_) --> num>)", "<(/,num,_) --> num>" => "<(*,0) --> num>";
1580 "(&&,<(*,0) --> num>,<{0} --> num>)", "<(*,0) --> num>" => "<{0} --> num>";
1581 "(&&,<(*,0) --> num>,<{0} --> num>)", "<{0} --> num>" => "<(*,0) --> num>";
1582 "(&&,<(*,a,b) --> like>,<(*,a,b) --> (*,a,b)>)", "<(*,a,b) --> like>" => "<(*,a,b) --> (*,a,b)>"; "(&&,<(*,b,a) --> [like]>,<(*,b,a) --> (*,b,(/,like,_,b))>)", "<(*,b,a) --> [like]>" => "<(*,b,a) --> (*,b,(/,like,_,b))>";
1584 "(&&,<(*,b,a) --> like>,<(*,b,a) --> (*,(/,like,b,_),b)>)", "<(*,b,a) --> like>" => "<(*,b,a) --> (*,(/,like,b,_),b)>";
1585 "(&&,<(/,(*,(/,num,_)),_) --> (/,num,_)>,<(/,(*,(/,num,_)),_) --> [num]>)", "<(/,(*,(/,num,_)),_) --> (/,num,_)>" => "<(/,(*,(/,num,_)),_) --> [num]>";
1586 "(&&,<(/,(/,REPRESENT,_,<{(*,CAT,FISH)} --> FOOD>),_,eat,fish) --> [cat]>,<(/,(/,REPRESENT,_,<{(*,CAT,FISH)} --> FOOD>),_,eat,fish) --> (&,CAT,cat)>)", "<(/,(/,REPRESENT,_,<{(*,CAT,FISH)} --> FOOD>),_,eat,fish) --> [cat]>" => "<(/,(/,REPRESENT,_,<{(*,CAT,FISH)} --> FOOD>),_,eat,fish) --> (&,CAT,cat)>";
1587 "(&&,<(/,neutralization,(/,reaction,_,base),_) --> base>,<(/,neutralization,(/,reaction,_,base),_) --> (/,reaction,(/,reaction,_,base),_)>)", "<(/,neutralization,(/,reaction,_,base),_) --> (/,reaction,(/,reaction,_,base),_)>" => "<(/,neutralization,(/,reaction,_,base),_) --> base>";
1588 "(&&,<(/,open,_,lock) --> key>,<(/,open,_,lock) --> (/,open,_,{lock1})>)", "<(/,open,_,lock) --> (/,open,_,{lock1})>" => "<(/,open,_,lock) --> key>";
1589 "(&&,<(/,open,{key1},_) --> lock>,<(/,open,{key1},_) --> (/,open,key,_)>)", "<(/,open,{key1},_) --> (/,open,key,_)>" => "<(/,open,{key1},_) --> lock>";
1590 "(&&,<(|,bird,gull) --> [bird]>,<(|,bird,gull) --> [swimmer]>)", "<(|,bird,gull) --> [swimmer]>" => "<(|,bird,gull) --> [bird]>";
1591 "(&&,<(|,robin,swan) --> (&,bird,swimmer)>,<(|,robin,swan) --> (|,bird,swimmer)>)", "<(|,robin,swan) --> (&,bird,swimmer)>" => "<(|,robin,swan) --> (|,bird,swimmer)>";
1592 "(&&,<(~,boy,girl) --> [strong]>,<(~,boy,girl) --> [[strong]]>)", "<(~,boy,girl) --> [strong]>" => "<(~,boy,girl) --> [[strong]]>";
1593 "(&&,<(~,swan,bird) --> [bird]>,<(~,swan,bird) --> [swimmer]>)", "<(~,swan,bird) --> [swimmer]>" => "<(~,swan,bird) --> [bird]>";
1594 "(&&,<0 --> num>,<0 --> {0}>)", "<0 --> num>" => "<0 --> {0}>";
1595 "(&&,<?1 --> animal>,<?1 --> [swimmer]>)", "<?1 --> [swimmer]>" => "<?1 --> animal>";
1596 "(&&,<CAT --> CAT>,<cat --> CAT>)", "<cat --> CAT>" => "<CAT --> CAT>";
1597 "(&&,<[[smart]] --> [bright]>,<[[smart]] --> [[bright]]>)", "<[[smart]] --> [[bright]]>" => "<[[smart]] --> [bright]>";
1598 "(&&,<acid --> (/,reaction,_,base)>,<(/,neutralization,_,base) --> (/,reaction,_,base)>)", "<acid --> (/,reaction,_,base)>" => "<(/,neutralization,_,base) --> (/,reaction,_,base)>";
1599 "(&&,<animal --> (&,bird,swimmer)>,<animal --> (|,bird,swimmer)>)", "<animal --> (|,bird,swimmer)>" => "<animal --> (&,bird,swimmer)>";
1600 "(&&,<animal --> [bird]>,<animal --> (|,bird,swimmer)>)", "<animal --> (|,bird,swimmer)>" => "<animal --> [bird]>";
1601 "(&&,<animal <-> robin>,<robin <-> [flying]>)", "<animal <-> robin>" => "<robin <-> [flying]>";
1602 "(&&,<animal <-> robin>,<robin <-> [flying]>)", "<robin <-> [flying]>" => "<animal <-> robin>";
1603 "(&&,<animal <-> robin>,<robin <-> [flying]>)", "[flying]" => None;
1604 "(&&,<animal <-> robin>,<robin <-> [flying]>)", "animal" => None;
1605 "(&&,<bird --> (|,robin,swimmer)>,<gull --> (|,robin,swimmer)>)", "<gull --> (|,robin,swimmer)>" => "<bird --> (|,robin,swimmer)>";
1606 "(&&,<bird --> [bird]>,<{Tweety} --> [bird]>)", "<{Tweety} --> [bird]>" => "<bird --> [bird]>";
1607 "(&&,<bird --> [with_wings]>,<bird --> [[with_wings]]>)", "<bird --> [with_wings]>" => "<bird --> [[with_wings]]>";
1608 "(&&,<bird --> animal>,<bird --> [swimmer]>)", "<bird --> [swimmer]>" => "<bird --> animal>";
1609 "(&&,<bird --> flyer>,<bird --> {Birdie}>)", "<bird --> {Birdie}>" => "<bird --> flyer>";
1610 "(&&,<bird --> flyer>,<{Tweety} --> flyer>)", "<{Tweety} --> flyer>" => "<bird --> flyer>";
1611 "(&&,<bird --> {Birdie}>,<{Tweety} --> {Birdie}>)", "<{Tweety} --> {Birdie}>" => "<bird --> {Birdie}>";
1612 "(&&,<cat --> [CAT]>,<cat --> (|,CAT,(/,(/,REPRESENT,_,<{(*,CAT,FISH)} --> FOOD>),_,eat,fish))>)", "<cat --> [CAT]>" => "<cat --> (|,CAT,(/,(/,REPRESENT,_,<{(*,CAT,FISH)} --> FOOD>),_,eat,fish))>";
1613 "(&&,<cat --> cat>,<cat --> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>)", "<cat --> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>" => "<cat --> cat>";
1614 "(&&,<chess --> [competition]>,<sport --> [competition]>)", "<sport --> [competition]>" => "<chess --> [competition]>";
1615 "(&&,<flyer --> (|,bird,[yellow])>,<{Tweety} --> (|,bird,[yellow])>)", "<{Tweety} --> (|,bird,[yellow])>" => "<flyer --> (|,bird,[yellow])>";
1616 "(&&,<gull --> [bird]>,<gull --> (&,bird,swimmer)>)", "<gull --> [bird]>" => "<gull --> (&,bird,swimmer)>";
1617 "(&&,<key --> (/,open,_,lock1)>,<(/,open,_,lock) --> (/,open,_,lock1)>)", "<(/,open,_,lock) --> (/,open,_,lock1)>" => "<key --> (/,open,_,lock1)>";
1618 "(&&,<key --> (/,open,_,{lock1})>,<{key1} --> (/,open,_,{lock1})>)", "<key --> (/,open,_,{lock1})>" => "<{key1} --> (/,open,_,{lock1})>";
1619 "(&&,<key --> (/,open,_,{lock1})>,<{key1} --> (/,open,_,{lock1})>)", "<{key1} --> (/,open,_,{lock1})>" => "<key --> (/,open,_,{lock1})>";
1620 "(&&,<key --> (|,key,(/,open,_,{lock1}))>,<{{key1}} --> (|,key,(/,open,_,{lock1}))>)", "<{{key1}} --> (|,key,(/,open,_,{lock1}))>" => "<key --> (|,key,(/,open,_,{lock1}))>";
1621 "(&&,<key --> [key]>,<{{key1}} --> [key]>)", "<{{key1}} --> [key]>" => "<key --> [key]>";
1622 "(&&,<key --> key>,<key --> (/,open,_,{lock1})>)", "<key --> (/,open,_,{lock1})>" => "<key --> key>";
1623 "(&&,<key --> key>,<{{key1}} --> key>)", "<{{key1}} --> key>" => "<key --> key>";
1624 "(&&,<key --> {key1}>,<{{key1}} --> {key1}>)", "<key --> {key1}>" => "<{{key1}} --> {key1}>";
1625 "(&&,<lock --> lock>,<lock --> (/,open,{key1},_)>)", "<lock --> (/,open,{key1},_)>" => "<lock --> lock>";
1626 "(&&,<lock1 --> (/,open,{key1},_)>,<{key1} --> key>)", "<lock1 --> (/,open,{key1},_)>" => "<{key1} --> key>";
1627 "(&&,<lock1 --> (/,open,{key1},_)>,<{key1} --> key>)", "<{key1} --> key>" => "<lock1 --> (/,open,{key1},_)>";
1628 "(&&,<lock1 --> (/,open,{key1},_)>,<{{key1}} --> key>)", "<lock1 --> (/,open,{key1},_)>" => "<{{key1}} --> key>";
1629 "(&&,<lock1 --> [lock]>,<lock1 --> [(/,open,{key1},_)]>)", "<lock1 --> [(/,open,{key1},_)]>" => "<lock1 --> [lock]>";
1630 "(&&,<lock1 --> [lock]>,<lock1 --> [(/,open,{key1},_)]>)", "<lock1 --> [lock]>" => "<lock1 --> [(/,open,{key1},_)]>";
1631 "(&&,<neutralization --> (*,acid,(/,reaction,acid,_))>,<(*,(/,neutralization,_,base),base) --> (*,acid,(/,reaction,acid,_))>)", "<(*,(/,neutralization,_,base),base) --> (*,acid,(/,reaction,acid,_))>" => "<neutralization --> (*,acid,(/,reaction,acid,_))>";
1632 "(&&,<neutralization --> neutralization>,<(*,acid,base) --> neutralization>)", "<(*,acid,base) --> neutralization>" => "<neutralization --> neutralization>";
1633 "(&&,<neutralization --> reaction>,<neutralization --> (*,(/,reaction,_,base),base)>)", "<neutralization --> (*,(/,reaction,_,base),base)>" => "<neutralization --> reaction>";
1634 "(&&,<neutralization --> reaction>,<neutralization --> (*,(/,reaction,_,base),base)>)", "<neutralization --> reaction>" => "<neutralization --> (*,(/,reaction,_,base),base)>";
1635 "(&&,<neutralization --> reaction>,<neutralization --> (*,acid,base)>)", "<neutralization --> (*,acid,base)>" => "<neutralization --> reaction>";
1636 "(&&,<robin --> (&,animal,(|,swimmer,(-,animal,swan)))>,<{bird} --> (&,animal,(|,swimmer,(-,animal,swan)))>)", "<{bird} --> (&,animal,(|,swimmer,(-,animal,swan)))>" => "<robin --> (&,animal,(|,swimmer,(-,animal,swan)))>";
1637 "(&&,<robin --> (&,animal,swimmer)>,<robin --> (|,swan,swimmer)>)", "<robin --> (&,animal,swimmer)>" => "<robin --> (|,swan,swimmer)>";
1638 "(&&,<robin --> (&,bird,[yellow])>,<{Tweety} --> (&,bird,[yellow])>)", "<{Tweety} --> (&,bird,[yellow])>" => "<robin --> (&,bird,[yellow])>";
1639 "(&&,<robin --> (&,bird,swimmer)>,<robin --> (-,bird,swimmer)>)", "<robin --> (-,bird,swimmer)>" => "<robin --> (&,bird,swimmer)>";
1640 "(&&,<robin --> (&,swimmer,(-,animal,swan))>,<{bird} --> (&,swimmer,(-,animal,swan))>)", "<{bird} --> (&,swimmer,(-,animal,swan))>" => "<robin --> (&,swimmer,(-,animal,swan))>";
1641 "(&&,<robin --> (-,animal,swan)>,<{bird} --> (-,animal,swan)>)", "<{bird} --> (-,animal,swan)>" => "<robin --> (-,animal,swan)>";
1642 "(&&,<robin --> (|,swan,swimmer)>,<{bird} --> (|,swan,swimmer)>)", "<{bird} --> (|,swan,swimmer)>" => "<robin --> (|,swan,swimmer)>";
1643 "(&&,<robin --> (|,swimmer,(-,animal,swan))>,<{robin} --> (|,swimmer,(-,animal,swan))>)", "robin" => None;
1644 "(&&,<robin --> [[chirping]]>,<robin --> [[flying]]>)", "robin" => None;
1645 "(&&,<robin --> [[chirping]]>,<robin --> [[flying]]>,<robin --> [[living]]>)", "<robin --> [[flying]]>" => "(&&,<robin --> [[chirping]]>,<robin --> [[living]]>)";
1646 "(&&,<robin --> [[chirping]]>,<robin --> [[flying]]>,<robin --> [[living]]>)", "robin" => None;
1647 "(&&,<robin --> [[flying]]>,<robin --> [[with_wings]]>)", "<robin --> [[flying]]>" => "<robin --> [[with_wings]]>";
1648 "(&&,<robin --> [[flying]]>,<robin --> [[with_wings]]>)", "<robin --> [bird]>" => None;
1649 "(&&,<robin --> [[with_wings]]>,(||,<robin --> [bird]>,<robin --> [[flying]]>))", "robin" => None;
1650 "(&&,<robin --> [animal]>,<robin --> [[flying]]>)", "<robin --> [[flying]]>" => "<robin --> [animal]>";
1651 "(&&,<robin --> [animal]>,<robin --> [[flying]]>)", "robin" => None;
1652 "(&&,<robin --> [animal]>,<robin --> [bird]>)", "robin" => None;
1653 "(&&,<robin --> [bird]>,<robin --> (&,bird,swimmer)>)", "<robin --> (&,bird,swimmer)>" => "<robin --> [bird]>";
1654 "(&&,<robin --> [bird]>,<robin --> [[flying]]>)", "<robin --> [[with_wings]]>" => None;
1655 "(&&,<robin --> [chirping]>,(||,<robin --> bird>,<robin --> flyer>))", "(||,<robin --> bird>,<robin --> flyer>)" => "<robin --> [chirping]>";
1656 "(&&,<robin --> [chirping]>,(||,<robin --> bird>,<robin --> flyer>))", "<robin --> [chirping]>" => "(||,<robin --> bird>,<robin --> flyer>)";
1657 "(&&,<robin --> [chirping]>,(||,<robin --> bird>,<robin --> flyer>))", "<robin --> flyer>" => None;
1658 "(&&,<robin --> [chirping]>,(||,<robin --> bird>,<robin --> flyer>))", "[chirping]" => None;
1659 "(&&,<robin --> [chirping]>,(||,<robin --> bird>,<robin --> flyer>))", "robin" => None;
1660 "(&&,<robin --> [chirping]>,<robin --> [flying]>)", "[chirping]" => None;
1661 "(&&,<robin --> [chirping]>,<robin --> [flying]>,(||,<robin --> bird>,<robin --> flyer>))", "(||,<robin --> bird>,<robin --> flyer>)" => "(&&,<robin --> [chirping]>,<robin --> [flying]>)";
1662 "(&&,<robin --> [chirping]>,<robin --> [flying]>,(||,<robin --> bird>,<robin --> flyer>))", "<robin --> [chirping]>" => "(&&,<robin --> [flying]>,(||,<robin --> bird>,<robin --> flyer>))";
1663 "(&&,<robin --> [chirping]>,<robin --> [flying]>,(||,<robin --> bird>,<robin --> flyer>))", "<robin --> bird>" => None;
1664 "(&&,<robin --> [chirping]>,<robin --> [flying]>,(||,<robin --> bird>,<robin --> flyer>))", "[chirping]" => None;
1665 "(&&,<robin --> [chirping]>,<robin --> [flying]>,(||,<robin --> bird>,<robin --> flyer>))", "robin" => None;
1666 "(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [living]>)", "<robin --> [flying]>" => "(&&,<robin --> [chirping]>,<robin --> [living]>)";
1667 "(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [living]>)", "[chirping]" => None;
1668 "(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [living]>)", "robin" => None;
1669 "(&&,<robin --> [chirping]>,<robin --> {Birdie}>)", "<robin --> {Birdie}>" => "<robin --> [chirping]>";
1670 "(&&,<robin --> [chirping]>,<robin --> {Birdie}>)", "[chirping]" => None;
1671 "(&&,<robin --> [chirping]>,<robin --> {Birdie}>)", "robin" => None;
1672 "(&&,<robin --> [chirping]>,<robin --> {Birdie}>)", "{Birdie}" => None;
1673 "(&&,<robin --> [flyer]>,<robin --> [[flying]]>)", "<robin --> [bird]>" => None;
1674 "(&&,<robin --> animal>,<robin --> [flying]>)", "<robin --> animal>" => "<robin --> [flying]>";
1675 "(&&,<robin --> animal>,<robin --> [flying]>)", "[flying]" => None;
1676 "(&&,<robin --> animal>,<robin --> [flying]>)", "animal" => None;
1677 "(&&,<robin --> flyer>,<(*,robin,worms) --> food>)", "flyer" => None;
1678 "(&&,<robin <-> [chirping]>,<robin <-> [flying]>)", "<robin <-> [chirping]>" => "<robin <-> [flying]>";
1679 "(&&,<robin <-> [chirping]>,<robin <-> [flying]>)", "[chirping]" => None;
1680 "(&&,<robin <-> [chirping]>,<robin <-> [flying]>)", "robin" => None;
1681 "(&&,<robin <-> [chirping]>,<robin <-> [flying]>,<robin <-> [with_wings]>)", "<robin <-> [with_wings]>" => "(&&,<robin <-> [chirping]>,<robin <-> [flying]>)";
1682 "(&&,<robin <-> [chirping]>,<robin <-> [flying]>,<robin <-> [with_wings]>)", "[chirping]" => None;
1683 "(&&,<robin <-> [chirping]>,<robin <-> [flying]>,<robin <-> [with_wings]>)", "robin" => None;
1684 "(&&,<robin <=> swimmer>,<robin <=> [flying]>)", "<robin <=> [flying]>" => "<robin <=> swimmer>";
1685 "(&&,<robin <=> swimmer>,<robin <=> [flying]>)", "<robin <=> swimmer>" => "<robin <=> [flying]>";
1686 "(&&,<robin <=> swimmer>,<robin <=> [flying]>)", "[flying]" => None;
1687 "(&&,<robin <=> swimmer>,<robin <=> [flying]>)", "robin" => None;
1688 "(&&,<robin ==> [flying]>,<robin ==> [with_wings]>)", "<robin ==> [flying]>" => "<robin ==> [with_wings]>";
1689 "(&&,<robin ==> [flying]>,<robin ==> [with_wings]>)", "[flying]" => None;
1690 "(&&,<robin ==> [flying]>,<robin ==> [with_wings]>)", "robin" => None;
1691 "(&&,<robin ==> swimmer>,<robin ==> [flying]>)", "<robin ==> [flying]>" => "<robin ==> swimmer>";
1692 "(&&,<robin ==> swimmer>,<robin ==> [flying]>)", "<robin ==> swimmer>" => "<robin ==> [flying]>";
1693 "(&&,<robin ==> swimmer>,<robin ==> [flying]>)", "[flying]" => None;
1694 "(&&,<robin ==> swimmer>,<robin ==> [flying]>)", "robin" => None;
1695 "(&&,<soda --> [(/,reaction,acid,_)]>,<{base} --> [(/,reaction,acid,_)]>)", "<{base} --> [(/,reaction,acid,_)]>" => "<soda --> [(/,reaction,acid,_)]>";
1696 "(&&,<sport --> competition>,<(&,chess,(|,chess,sport)) --> competition>)", "<(&,chess,(|,chess,sport)) --> competition>" => "<sport --> competition>";
1697 "(&&,<swan --> [bird]>,<swan --> (|,bird,swimmer)>)", "<swan --> [bird]>" => "<swan --> (|,bird,swimmer)>";
1698 "(&&,<swimmer --> animal>,<swimmer --> (|,swimmer,(-,animal,swan))>)", "<swimmer --> animal>" => "<swimmer --> (|,swimmer,(-,animal,swan))>";
1699 "(&&,<worms --> (/,food,{Tweety},_)>,<{Tweety} --> [chirping]>)", "[chirping]" => None;
1700 "(&&,<worms --> (/,food,{Tweety},_)>,<{Tweety} --> [chirping]>)", "{Tweety}" => None;
1701 "(&&,<{(*,a,b)} --> [like]>,<{(*,a,b)} --> (*,b,(/,like,_,b))>)", "<{(*,a,b)} --> [like]>" => "<{(*,a,b)} --> (*,b,(/,like,_,b))>";
1702 "(&&,<{(*,a,b)} --> like>,<{(*,b,a)} --> like>)", "<{(*,a,b)} --> like>" => "<{(*,b,a)} --> like>";
1703 "(&&,<{(|,boy,girl)} --> [youth]>,<{(|,boy,girl)} --> (|,girl,[strong])>)", "<{(|,boy,girl)} --> [youth]>" => "<{(|,boy,girl)} --> (|,girl,[strong])>";
1704 "(&&,<{Tweety} --> (&,[with_wings],(|,flyer,{Birdie}))>,<{{Tweety}} --> (&,[with_wings],(|,flyer,{Birdie}))>)", "<{{Tweety}} --> (&,[with_wings],(|,flyer,{Birdie}))>" => "<{Tweety} --> (&,[with_wings],(|,flyer,{Birdie}))>";
1705 "(&&,<{Tweety} --> (&,[with_wings],{Birdie})>,<{{Tweety}} --> (&,[with_wings],{Birdie})>)", "<{{Tweety}} --> (&,[with_wings],{Birdie})>" => "<{Tweety} --> (&,[with_wings],{Birdie})>";
1706 "(&&,<{Tweety} --> (&,flyer,[[with_wings]])>,<{{Tweety}} --> (&,flyer,[[with_wings]])>)", "<{{Tweety}} --> (&,flyer,[[with_wings]])>" => "<{Tweety} --> (&,flyer,[[with_wings]])>";
1707 "(&&,<{Tweety} --> (|,[[with_wings]],(&,flyer,{Birdie}))>,<{{Tweety}} --> (|,[[with_wings]],(&,flyer,{Birdie}))>)", "<{{Tweety}} --> (|,[[with_wings]],(&,flyer,{Birdie}))>" => "<{Tweety} --> (|,[[with_wings]],(&,flyer,{Birdie}))>";
1708 "(&&,<{Tweety} --> (|,bird,[yellow])>,<{{Tweety}} --> (|,bird,[yellow])>)", "<{Tweety} --> (|,bird,[yellow])>" => "<{{Tweety}} --> (|,bird,[yellow])>";
1709 "(&&,<{Tweety} --> (|,flyer,[[with_wings]])>,<{{Tweety}} --> (|,flyer,[[with_wings]])>)", "<{{Tweety}} --> (|,flyer,[[with_wings]])>" => "<{Tweety} --> (|,flyer,[[with_wings]])>";
1710 "(&&,<{Tweety} --> (|,flyer,[with_wings])>,<{{Tweety}} --> (|,flyer,[with_wings])>)", "<{{Tweety}} --> (|,flyer,[with_wings])>" => "<{Tweety} --> (|,flyer,[with_wings])>";
1711 "(&&,<{Tweety} --> (|,flyer,{Birdie})>,<{{Tweety}} --> (|,flyer,{Birdie})>)", "<{{Tweety}} --> (|,flyer,{Birdie})>" => "<{Tweety} --> (|,flyer,{Birdie})>";
1712 "(&&,<{Tweety} --> [chirping]>,<(*,{Tweety},worms) --> food>)", "[chirping]" => None;
1713 "(&&,<{Tweety} --> [chirping]>,<(*,{Tweety},worms) --> food>)", "{Tweety}" => None;
1714 "(&&,<{Tweety} --> [flyer]>,<{{Tweety}} --> [flyer]>)", "<{{Tweety}} --> [flyer]>" => "<{Tweety} --> [flyer]>";
1715 "(&&,<{Tweety} --> [yellow]>,<{{Tweety}} --> [yellow]>)", "<{Tweety} --> [yellow]>" => "<{{Tweety}} --> [yellow]>";
1716 "(&&,<{Tweety} --> [{Birdie}]>,<{Tweety} --> (&,flyer,[[with_wings]])>)", "<{Tweety} --> [{Birdie}]>" => "<{Tweety} --> (&,flyer,[[with_wings]])>";
1717 "(&&,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "<{Tweety} --> [with_wings]>" => "<{Tweety} --> bird>";
1718 "(&&,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "<{Tweety} --> bird>" => "<{Tweety} --> [with_wings]>";
1719 "(&&,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "[with_wings]" => None;
1720 "(&&,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "bird" => None;
1721 "(&&,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "{Tweety}" => None;
1722 "(&&,<{Tweety} --> flyer>,<(*,{Tweety},worms) --> food>)", "<(*,{Tweety},worms) --> food>" => "<{Tweety} --> flyer>";
1723 "(&&,<{Tweety} --> flyer>,<(*,{Tweety},worms) --> food>)", "<{Tweety} --> flyer>" => "<(*,{Tweety},worms) --> food>";
1724 "(&&,<{Tweety} --> flyer>,<(*,{Tweety},worms) --> food>)", "flyer" => None;
1725 "(&&,<{Tweety} --> flyer>,<(*,{Tweety},worms) --> food>)", "{Tweety}" => None;
1726 "(&&,<{Tweety} --> flyer>,<{Tweety} --> [{Birdie}]>)", "<{Tweety} --> [{Birdie}]>" => "<{Tweety} --> flyer>";
1727 "(&&,<{Tweety} --> flyer>,<{{Tweety}} --> flyer>)", "<{{Tweety}} --> flyer>" => "<{Tweety} --> flyer>";
1728 "(&&,<{[smart]} --> [bright]>,<{[smart]} --> [[bright]]>)", "<{[smart]} --> [[bright]]>" => "<{[smart]} --> [bright]>";
1729 "(&&,<{bird} --> animal>,<(&,robin,swimmer) --> animal>)", "<{bird} --> animal>" => "<(&,robin,swimmer) --> animal>";
1730 "(&&,<{key1} --> (/,open,_,{lock1})>,<{{key1}} --> (/,open,_,{lock1})>)", "<{key1} --> (/,open,_,{lock1})>" => "<{{key1}} --> (/,open,_,{lock1})>";
1731 "(&&,<{key1} --> [key]>,<{lock1} --> [(/,open,key1,_)]>)", "<{key1} --> [key]>" => "<{lock1} --> [(/,open,key1,_)]>";
1732 "(&&,<{key1} --> [key]>,<{lock1} --> [(/,open,{key1},_)]>)", "<{key1} --> [key]>" => "<{lock1} --> [(/,open,{key1},_)]>";
1733 "(&&,<{key1} --> key>,<{key1} --> (/,open,_,{lock1})>)", "<{key1} --> key>" => "<{key1} --> (/,open,_,{lock1})>";
1734 "(&&,<{lock1} --> [lock]>,<{lock1} --> [(/,open,{key1},_)]>)", "<{lock1} --> [(/,open,{key1},_)]>" => "<{lock1} --> [lock]>";
1735 "(&&,<{lock1} --> lock>,<{lock1} --> (/,open,key,_)>)", "<{lock1} --> (/,open,key,_)>" => "<{lock1} --> lock>";
1736 "(&&,<{robin} --> (&,bird,swimmer)>,<{robin} --> (-,bird,swimmer)>)", "<{robin} --> (-,bird,swimmer)>" => "<{robin} --> (&,bird,swimmer)>";
1737 "(&&,<{robin} --> [[chirping]]>,<{robin} --> [[flying]]>)", "<{robin} --> [[chirping]]>" => "<{robin} --> [[flying]]>";
1738 "(&&,<{robin} --> [[chirping]]>,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>)", "<{robin} --> [[chirping]]>" => "(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>)";
1739 "(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>)", "<{robin} --> [bird]>" => None;
1740 "(&&,<{robin} --> [animal]>,<{robin} --> [[flying]]>)", "<{robin} --> [[flying]]>" => "<{robin} --> [animal]>";
1741 "(&&,<{robin} --> [animal]>,<{robin} --> [[flying]]>)", "<{robin} --> [animal]>" => "<{robin} --> [[flying]]>";
1742 "(&&,<{robin} --> [chirping]>,<{robin} --> [flying]>)", "[chirping]" => None;
1743 "(&&,<{robin} --> [chirping]>,<{robin} --> [flying]>,<{robin} --> [with_wings]>)", "[chirping]" => None;
1744 "(&&,<{robin} --> [flying]>,<{robin} --> [with_wings]>)", "<{robin} --> [flying]>" => "<{robin} --> [with_wings]>";
1745 "(&&,<{robin} --> bird>,<{robin} --> [flying]>)", "<{robin} --> [with_wings]>" => None;
1746 "(&&,<{swan} --> [bird]>,<{swan} --> (&,bird,swimmer)>)", "<{swan} --> (&,bird,swimmer)>" => "<{swan} --> [bird]>";
1747 "(&&,<{swan} --> [bird]>,<{swan} --> (|,bird,swimmer)>)", "<{swan} --> (|,bird,swimmer)>" => "<{swan} --> [bird]>";
1748 "(&&,<{tim} --> [(/,uncle,_,tom)]>,<(/,(*,tim,tom),_,tom) --> [(/,uncle,_,tom)]>)", "<{tim} --> [(/,uncle,_,tom)]>" => "<(/,(*,tim,tom),_,tom) --> [(/,uncle,_,tom)]>";
1749 "(&&,<{{key1}} --> key>,<{{key1}} --> [(/,open,_,{lock1})]>)", "<{{key1}} --> [(/,open,_,{lock1})]>" => "<{{key1}} --> key>";
1750 "(&&,robin,(--,<robin ==> [flying]>))", "(--,<robin ==> [flying]>)" => "robin";
1751 "(&&,robin,(--,<robin ==> [flying]>))", "<robin ==> [flying]>" => None;
1752 "(&&,robin,(--,<robin ==> [flying]>))", "robin" => "(--,<robin ==> [flying]>)";
1753 "(&&,robin,(--,<robin ==> bird>))", "(--,<robin ==> bird>)" => "robin";
1754 "(&&,robin,(--,<robin ==> bird>))", "<robin ==> bird>" => None;
1755 "(&&,robin,(--,<robin ==> bird>))", "robin" => "(--,<robin ==> bird>)";
1756 "(&&,robin,<robin ==> [chirping]>)", "<robin ==> [chirping]>" => "robin";
1757 "(&&,robin,<robin ==> [chirping]>)", "robin" => "<robin ==> [chirping]>";
1758 "(&&,robin,<robin ==> [chirping]>,<robin ==> [flying]>)", "(&&,robin,<robin ==> [chirping]>)" => "<robin ==> [flying]>";
1759 "(&&,robin,<robin ==> [chirping]>,<robin ==> [flying]>)", "[flying]" => None;
1760 "(&&,robin,<robin ==> [chirping]>,<robin ==> [flying]>)", "robin" => "(&&,<robin ==> [chirping]>,<robin ==> [flying]>)";
1761 "(&&,robin,<robin ==> [chirping]>,<robin ==> [flying]>,<robin ==> [with_wings]>)", "[flying]" => None;
1762 "(&&,robin,<robin ==> [chirping]>,<robin ==> [flying]>,<robin ==> [with_wings]>)", "robin" => "(&&,<robin ==> [chirping]>,<robin ==> [flying]>,<robin ==> [with_wings]>)";
1763 "(&&,robin,<robin ==> [chirping]>,<robin ==> [with_wings]>)", "<robin ==> [chirping]>" => "(&&,robin,<robin ==> [with_wings]>)";
1764 "(&&,robin,<robin ==> [flying]>)", "[flying]" => None;
1765 "(&&,robin,<robin ==> bird>)", "<robin ==> bird>" => "robin";
1766 "(&&,robin,<robin ==> bird>)", "bird" => None;
1767 "(&&,robin,<robin ==> bird>)", "robin" => "<robin ==> bird>";
1768 "(&&,robin,<robin ==> bird>,<robin ==> [flying]>)", "(&&,robin,(--,<robin ==> bird>))" => "(&&,<robin ==> bird>,<robin ==> [flying]>)";
1769 "(&&,robin,<robin ==> bird>,<robin ==> [flying]>)", "<robin ==> [flying]>" => "(&&,robin,<robin ==> bird>)";
1770 "(&&,robin,<robin ==> bird>,<robin ==> [flying]>)", "<robin ==> bird>" => "(&&,robin,<robin ==> [flying]>)";
1771 "(&&,robin,<robin ==> bird>,<robin ==> [flying]>)", "[flying]" => None;
1772 "(&&,robin,<robin ==> bird>,<robin ==> [flying]>)", "bird" => None;
1773 "(&&,robin,<robin ==> bird>,<robin ==> [flying]>)", "robin" => "(&&,<robin ==> bird>,<robin ==> [flying]>)";
1774 "(&,(*,0),(*,(*,0)))", "(*,0)" => "(*,(*,0))";
1775 "(&,(/,neutralization,_,base),(/,neutralization,_,soda),(/,reaction,_,(/,reaction,acid,_)))", "(/,reaction,_,(/,reaction,acid,_))" => "(&,(/,neutralization,_,base),(/,neutralization,_,soda))";
1776 "(&,(|,bird,robin),(|,robin,swimmer))", "(|,robin,swimmer)" => "(|,bird,robin)";
1777 "(&,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))", "CAT" => "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)";
1778 "(&,animal,swimmer)", "animal" => "swimmer";
1779 "(&,bird,[yellow])", "bird" => "[yellow]";
1780 "(&,bird,{Birdie})", "bird" => "{Birdie}";
1781 "(&,chess,(|,chess,sport))", "chess" => "(|,chess,sport)";
1782 "(&,flyer,[[with_wings]])", "flyer" => "[[with_wings]]";
1783 "(&,gull,robin,swan)", "robin" => "(&,gull,swan)";
1784 "(&,key,(/,open,_,{lock1}))", "key" => "(/,open,_,{lock1})";
1785 "(&,tim,(|,{tim},(/,(*,tim,tom),_,tom)))", "tim" => "(|,{tim},(/,(*,tim,tom),_,tom))";
1786 "(*,(/,num,_))", "(/,num,_)" => None;
1787 "(*,0)", "0" => None;
1788 "(*,a,b)", "(*,b,a)" => None;
1789 "(-,bird,(-,mammal,swimmer))", "bird" => "(-,mammal,swimmer)";
1790 "(-,bird,swimmer)", "bird" => "swimmer";
1791 "(-,{Mars,Pluto,Venus},[{Pluto,Saturn}])", "[{Pluto,Saturn}]" => "{Mars,Pluto,Venus}";
1792 "(|,(-,{Mars,Pluto,Venus},[{Pluto,Saturn}]),{Pluto,Saturn})", "(-,{Mars,Pluto,Venus},[{Pluto,Saturn}])" => "{Pluto,Saturn}";
1793 "(|,[{Pluto,Saturn}],{Mars,Pluto,Venus})", "[{Pluto,Saturn}]" => "{Mars,Pluto,Venus}";
1794 "(|,[{Pluto,Saturn}],{Mars,Venus})", "[{Pluto,Saturn}]" => "{Mars,Venus}";
1795 "(|,animal,swimmer,(-,animal,swan))", "swimmer" => "(|,animal,(-,animal,swan))";
1796 "(|,bird,(-,mammal,swimmer))", "bird" => "(-,mammal,swimmer)";
1797 "(|,bird,[yellow])", "bird" => "[yellow]";
1798 "(|,bird,robin)", "bird" => "robin";
1799 "(|,boy,girl,youth,[strong])", "youth" => "(|,boy,girl,[strong])";
1800 "(|,key,(/,open,_,lock))", "key" => "(/,open,_,lock)";
1801 "(|,key,(/,open,_,{lock1}))", "key" => "(/,open,_,{lock1})";
1802 "(|,like,{(*,a,b)})", "like" => "{(*,a,b)}";
1803 "(|,lock,[(/,open,key1,_)])", "lock" => "[(/,open,key1,_)]";
1804 "(|,tim,{tim},(/,(*,tim,tom),_,tom))", "tim" => "(|,{tim},(/,(*,tim,tom),_,tom))";
1805 "(||,(&&,<robin --> [bird]>,<robin --> [[flying]]>),<robin --> [[with_wings]]>)", "(&&,<robin --> [bird]>,<robin --> [[flying]]>)" => "<robin --> [[with_wings]]>";
1806 "(||,(&&,<robin --> [bird]>,<robin --> [[flying]]>),<robin --> [[with_wings]]>)", "<robin --> [[flying]]>" => None;
1807 "(||,(&&,<robin --> [bird]>,<robin --> [[flying]]>),<robin --> [[with_wings]]>)", "robin" => None;
1808 "(||,(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>),<{robin} --> [bird]>)", "(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>)" => "<{robin} --> [bird]>";
1809 "(||,(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>),<{robin} --> [bird]>)", "<{robin} --> [[with_wings]]>" => None;
1810 "(||,(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>),<{robin} --> [bird]>)", "<{robin} --> [bird]>" => "(&&,<{robin} --> [[flying]]>,<{robin} --> [[with_wings]]>)";
1811 "(||,(&&,<{robin} --> bird>,<{robin} --> [flying]>),<{robin} --> [with_wings]>)", "<{robin} --> [flying]>" => None;
1812 "(||,(&&,<{robin} --> bird>,<{robin} --> [flying]>),<{robin} --> [with_wings]>)", "[with_wings]" => None;
1813 "(||,<robin --> [[flying]]>,<robin --> [[with_wings]]>)", "<robin --> [[flying]]>" => "<robin --> [[with_wings]]>";
1814 "(||,<robin --> [[flying]]>,<robin --> [[with_wings]]>)", "robin" => None;
1815 "(||,<robin --> [animal]>,<robin --> [bird]>)", "<robin --> [animal]>" => "<robin --> [bird]>";
1816 "(||,<robin --> [animal]>,<robin --> [bird]>)", "robin" => None;
1817 "(||,<robin --> [bird]>,<robin --> [[flying]]>)", "<robin --> [[flying]]>" => "<robin --> [bird]>";
1818 "(||,<robin --> [bird]>,<robin --> [[flying]]>)", "<robin --> [bird]>" => "<robin --> [[flying]]>";
1819 "(||,<robin --> [bird]>,<robin --> [[flying]]>)", "robin" => None;
1820 "(||,<robin --> bird>,<robin --> [living]>)", "<robin --> [living]>" => "<robin --> bird>";
1821 "(||,<robin --> bird>,<robin --> [living]>)", "<robin --> bird>" => "<robin --> [living]>";
1822 "(||,<robin --> bird>,<robin --> [living]>)", "[living]" => None;
1823 "(||,<robin --> bird>,<robin --> [living]>)", "bird" => None;
1824 "(||,<robin --> bird>,<robin --> flyer>)", "<robin --> flyer>" => "<robin --> bird>";
1825 "(||,<robin --> bird>,<robin --> flyer>)", "bird" => None;
1826 "(||,<robin <-> swimmer>,<robin <-> [flying]>)", "<robin <-> [flying]>" => "<robin <-> swimmer>";
1827 "(||,<robin <-> swimmer>,<robin <-> [flying]>)", "<robin <-> swimmer>" => "<robin <-> [flying]>";
1828 "(||,<robin <-> swimmer>,<robin <-> [flying]>)", "[flying]" => None;
1829 "(||,<robin <-> swimmer>,<robin <-> [flying]>)", "robin" => None;
1830 "(||,<robin <=> swimmer>,<robin <=> [flying]>)", "<robin <=> [flying]>" => "<robin <=> swimmer>";
1831 "(||,<robin <=> swimmer>,<robin <=> [flying]>)", "<robin <=> swimmer>" => "<robin <=> [flying]>";
1832 "(||,<robin <=> swimmer>,<robin <=> [flying]>)", "[flying]" => None;
1833 "(||,<robin <=> swimmer>,<robin <=> [flying]>)", "robin" => None;
1834 "(||,<robin ==> swimmer>,<robin ==> [flying]>)", "<robin ==> [flying]>" => "<robin ==> swimmer>";
1835 "(||,<robin ==> swimmer>,<robin ==> [flying]>)", "<robin ==> swimmer>" => "<robin ==> [flying]>";
1836 "(||,<robin ==> swimmer>,<robin ==> [flying]>)", "[flying]" => None;
1837 "(||,<robin ==> swimmer>,<robin ==> [flying]>)", "robin" => None;
1838 "(||,<{Tweety} --> [with_wings]>,<{Tweety} --> [[with_wings]]>)", "<{Tweety} --> [[with_wings]]>" => "<{Tweety} --> [with_wings]>";
1839 "(||,<{Tweety} --> [with_wings]>,<{Tweety} --> [[with_wings]]>)", "<{Tweety} --> [with_wings]>" => "<{Tweety} --> [[with_wings]]>";
1840 "(||,<{Tweety} --> [with_wings]>,<{Tweety} --> [[with_wings]]>)", "[with_wings]" => None;
1841 "(||,<{Tweety} --> [with_wings]>,<{Tweety} --> [[with_wings]]>)", "{Tweety}" => None;
1842 "(||,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "<{Tweety} --> [with_wings]>" => "<{Tweety} --> bird>";
1843 "(||,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "<{Tweety} --> bird>" => "<{Tweety} --> [with_wings]>";
1844 "(||,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "[with_wings]" => None;
1845 "(||,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "bird" => None;
1846 "(||,<{Tweety} --> bird>,<{Tweety} --> [with_wings]>)", "{Tweety}" => None;
1847 "(||,<{lock1} --> [(/,open,{key1},_)]>,<{{lock1}} --> [(/,open,key1,_)]>)", "<{lock1} --> [(/,open,{key1},_)]>" => "<{{lock1}} --> [(/,open,key1,_)]>";
1848 "(||,<{lock1} --> [(/,open,{key1},_)]>,<{{lock1}} --> [(/,open,key1,_)]>)", "<{{lock1}} --> [(/,open,key1,_)]>" => "<{lock1} --> [(/,open,{key1},_)]>";
1849 "(~,boy,girl)", "boy" => "girl";
1850 "[(*,acid,base)]", "(*,acid,base)" => None;
1851 "[(/,reaction,_,base)]", "(/,reaction,_,base)" => None;
1852 "[acid]", "acid" => None;
1853 "[{Mars,Pluto,Venus}]", "{Mars,Pluto,Venus}" => None;
1854 "[{Pluto,Saturn}]", "{Pluto,Saturn}" => None;
1855 "{(*,a,b)}", "(*,a,b)" => None;
1856 "{(/,num,_)}", "(/,num,_)" => None;
1857 "{(|,boy,girl)}", "(|,boy,girl)" => None;
1858 "{(~,boy,girl)}", "(~,boy,girl)" => None;
1859 "{0}", "0" => None;
1860 "{Mars,Pluto,Saturn,Venus}", "{Mars,Pluto,Venus}" => None;
1861 "{Mars,Pluto,Saturn,Venus}", "{Pluto,Saturn}" => "{Mars,Venus}";
1862 "{Mars,Pluto,Venus}", "{Mars,Venus}" => None;
1863 "{[bright]}", "[bright]" => None;
1864 }
1865 ok!()
1866 }
1867
1868 #[test]
1869 fn set_component() -> AResult {
1870 fn test(compound: Term, index: usize, term: Option<Term>, expected: Option<Term>) {
1875 let compound_ref = compound.as_compound().expect("构造出来的不是复合词项");
1876 let compound_s = compound.to_string();
1877 let term_s = format_option_term(&term);
1878 let out = CompoundTermRef::set_component(compound_ref, index, term);
1879 assert_eq!(
1880 out,
1881 expected,
1882 "{compound_s:?}, {index:?}, {term_s:?} => {} != {}",
1883 format_option_term(&out),
1884 format_option_term(&expected),
1885 );
1886 }
1887 macro_once! {
1888 macro test($($compound:tt, $index:tt, $term:tt => $expected:tt;)*) {
1890 $( test(term!($compound), $index, option_term!($term), option_term!($expected)); )*
1891 }
1892 "(*, <robin --> [chirping]>, <robin --> [flying]>, (||, <robin --> bird>, <robin --> flyer>))", 0, None => "(*, <robin --> [flying]>, (||, <robin --> bird>, <robin --> flyer>))";
1896 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [living]>)", 0, None => "(*, <robin --> [flying]>, <robin --> [living]>)";
1897 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [living]>)", 2, None => "(*, <robin --> [chirping]>, <robin --> [flying]>)";
1898 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 0, "<robin --> bird>" => "(*, <robin --> bird>, <robin --> [flying]>, <robin --> [with_wings]>)";
1899 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 0, None => "(*, <robin --> [flying]>, <robin --> [with_wings]>)";
1900 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 1, None => "(*, <robin --> [chirping]>, <robin --> [with_wings]>)";
1901 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 2, "(||, <robin --> bird>, <robin --> flyer>)" => "(*, <robin --> [chirping]>, <robin --> [flying]>, (||, <robin --> bird>, <robin --> flyer>))";
1902 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 2, "<robin --> [living]>" => "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [living]>)";
1903 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 2, "<robin --> bird>" => "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> bird>)";
1904 "(*, <robin --> [chirping]>, <robin --> [flying]>, <robin --> [with_wings]>)", 2, None => "(*, <robin --> [chirping]>, <robin --> [flying]>)";
1905 "(*, <robin --> [chirping]>, <robin --> [with_wings]>)", 0, "<robin --> bird>" => "(*, <robin --> bird>, <robin --> [with_wings]>)";
1906 "(*, <robin --> [chirping]>, <robin --> [with_wings]>)", 1, "(||, <robin --> bird>, <robin --> flyer>)" => "(*, <robin --> [chirping]>, (||, <robin --> bird>, <robin --> flyer>))";
1907 "(*, <robin --> [chirping]>, <robin --> [with_wings]>)", 1, "<robin --> [living]>" => "(*, <robin --> [chirping]>, <robin --> [living]>)";
1908 "(*, <robin --> [chirping]>, <robin --> [with_wings]>)", 1, "<robin --> bird>" => "(*, <robin --> [chirping]>, <robin --> bird>)";
1909 "(*, <robin --> [chirping]>, <robin --> [with_wings]>)", 1, "<robin --> flyer>" => "(*, <robin --> [chirping]>, <robin --> flyer>)";
1910 "(*, <robin --> [chirping]>, <robin --> [with_wings]>, <(*, robin, worms) --> food>)", 0, "<robin --> bird>" => "(*, <robin --> bird>, <robin --> [with_wings]>, <(*, robin, worms) --> food>)";
1911 "(*, <robin --> [chirping]>, <robin --> [with_wings]>, <(*, robin, worms) --> food>)", 0, None => "(*, <robin --> [with_wings]>, <(*, robin, worms) --> food>)";
1912 "(*, <robin --> [chirping]>, <robin --> [with_wings]>, <worms --> (/, food, robin, _)>)", 0, None => "(*, <robin --> [with_wings]>, <worms --> (/, food, robin, _)>)";
1913 "(*, <robin --> [flying]>, <robin --> [with_wings]>)", 1, "(||, <robin --> bird>, <robin --> flyer>)" => "(*, <robin --> [flying]>, (||, <robin --> bird>, <robin --> flyer>))";
1914 "(*, <robin --> [flying]>, <robin --> [with_wings]>)", 1, "<robin --> bird>" => "(*, <robin --> [flying]>, <robin --> bird>)";
1915 "(*, <robin --> flyer>, <(*, robin, worms) --> food>)", 0, "<robin --> bird>" => "(*, <robin --> bird>, <(*, robin, worms) --> food>)";
1916 "(*, <robin --> flyer>, <robin --> [chirping]>, <(*, robin, worms) --> food>)", 1, "<robin --> bird>" => "(*, <robin --> flyer>, <robin --> bird>, <(*, robin, worms) --> food>)";
1917 "(*, <robin --> flyer>, <robin --> [chirping]>, <(*, robin, worms) --> food>)", 1, None => "(*, <robin --> flyer>, <(*, robin, worms) --> food>)";
1918 "(*, <robin --> flyer>, <robin --> [chirping]>, <worms --> (/, food, robin, _)>)", 0, None => "(*, <robin --> [chirping]>, <worms --> (/, food, robin, _)>)";
1919 "(*, <robin --> flyer>, <robin --> [chirping]>, <worms --> (/, food, robin, _)>)", 1, "<robin --> bird>" => "(*, <robin --> flyer>, <robin --> bird>, <worms --> (/, food, robin, _)>)";
1920 "(*, <robin <-> [chirping]>, <robin <-> [flying]>)", 0, "<bird <-> robin>" => "(*, <bird <-> robin>, <robin <-> [flying]>)";
1921 "(*, <robin <-> [chirping]>, <robin <-> [flying]>, <robin <-> [with_wings]>)", 0, "<bird <-> robin>" => "(*, <bird <-> robin>, <robin <-> [flying]>, <robin <-> [with_wings]>)";
1922 "(*, <robin <-> [chirping]>, <robin <-> [flying]>, <robin <-> [with_wings]>)", 0, None => "(*, <robin <-> [flying]>, <robin <-> [with_wings]>)";
1923 "(*, <robin <-> [chirping]>, <robin <-> [flying]>, <robin <-> [with_wings]>)", 1, None => "(*, <robin <-> [chirping]>, <robin <-> [with_wings]>)";
1924 "(*, <robin <-> [chirping]>, <robin <-> [flying]>, <robin <-> [with_wings]>)", 2, None => "(*, <robin <-> [chirping]>, <robin <-> [flying]>)";
1925 "(*, <robin <-> [chirping]>, <robin <-> [with_wings]>)", 1, "<bird <-> robin>" => "(*, <robin <-> [chirping]>, <bird <-> robin>)";
1926 "(*, <robin <-> [flying]>, <robin <-> [with_wings]>)", 1, "<bird <-> robin>" => "(*, <robin <-> [flying]>, <bird <-> robin>)";
1927 "(*, <worms --> (/, food, {Tweety}, _)>, <{Tweety} --> flyer>, <{Tweety} --> [chirping]>)", 1, None => "(*, <worms --> (/, food, {Tweety}, _)>, <{Tweety} --> [chirping]>)";
1928 "(*, <{Tweety} --> flyer>, <{Tweety} --> [chirping]>, <(*, {Tweety}, worms) --> food>)", 0, None => "(*, <{Tweety} --> [chirping]>, <(*, {Tweety}, worms) --> food>)";
1929 "(*, <{Tweety} --> flyer>, <{Tweety} --> [chirping]>, <(*, {Tweety}, worms) --> food>)", 1, None => "(*, <{Tweety} --> flyer>, <(*, {Tweety}, worms) --> food>)";
1930 "(*, <{Tweety} --> flyer>, <{Tweety} --> [chirping]>, <(*, {Tweety}, worms) --> food>)", 2, None => "(*, <{Tweety} --> flyer>, <{Tweety} --> [chirping]>)";
1931 "(*, <{robin} --> [chirping]>, <{robin} --> [flying]>, <{robin} --> [with_wings]>)", 0, None => "(*, <{robin} --> [flying]>, <{robin} --> [with_wings]>)";
1932 "(*, <{robin} --> [chirping]>, <{robin} --> [flying]>, <{robin} --> [with_wings]>)", 1, None => "(*, <{robin} --> [chirping]>, <{robin} --> [with_wings]>)";
1933 "(*, <{robin} --> [chirping]>, <{robin} --> [flying]>, <{robin} --> [with_wings]>)", 2, None => "(*, <{robin} --> [chirping]>, <{robin} --> [flying]>)";
1934 "(*, <{robin} --> [flying]>, <{robin} --> [with_wings]>)", 1, "<{robin} --> bird>" => "(*, <{robin} --> [flying]>, <{robin} --> bird>)";
1935 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>)", 0, None => "(*, <robin ==> [chirping]>, <robin ==> [flying]>)";
1936 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>)", 1, None => "(*, robin, <robin ==> [flying]>)";
1937 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>)", 2, None => "(*, robin, <robin ==> [chirping]>)";
1938 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>, <robin ==> [with_wings]>)", 0, None => "(*, <robin ==> [chirping]>, <robin ==> [flying]>, <robin ==> [with_wings]>)";
1939 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>, <robin ==> [with_wings]>)", 1, None => "(*, robin, <robin ==> [flying]>, <robin ==> [with_wings]>)";
1940 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>, <robin ==> [with_wings]>)", 2, None => "(*, robin, <robin ==> [chirping]>, <robin ==> [with_wings]>)";
1941 "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>, <robin ==> [with_wings]>)", 3, None => "(*, robin, <robin ==> [chirping]>, <robin ==> [flying]>)";
1942 "(*, robin, <robin ==> [chirping]>, <robin ==> [with_wings]>)", 0, None => "(*, <robin ==> [chirping]>, <robin ==> [with_wings]>)";
1943 "(*, robin, <robin ==> [chirping]>, <robin ==> [with_wings]>)", 1, None => "(*, robin, <robin ==> [with_wings]>)";
1944 "(*, robin, <robin ==> [chirping]>, <robin ==> [with_wings]>)", 2, None => "(*, robin, <robin ==> [chirping]>)";
1945 "(*, robin, <robin ==> [flying]>, <robin ==> [with_wings]>)", 0, None => "(*, <robin ==> [flying]>, <robin ==> [with_wings]>)";
1946 "(*, robin, <robin ==> [flying]>, <robin ==> [with_wings]>)", 1, None => "(*, robin, <robin ==> [with_wings]>)";
1947 "(*, robin, <robin ==> [flying]>, <robin ==> [with_wings]>)", 2, None => "(*, robin, <robin ==> [flying]>)";
1948 "(*, robin, <robin ==> bird>, <robin ==> [flying]>)", 0, None => "(*, <robin ==> bird>, <robin ==> [flying]>)";
1949 "(*, robin, <robin ==> bird>, <robin ==> [flying]>)", 1, None => "(*, robin, <robin ==> [flying]>)";
1950 "(*, robin, <robin ==> bird>, <robin ==> [flying]>)", 2, None => "(*, robin, <robin ==> bird>)";
1951 "(*, robin, <robin ==> bird>, <robin ==> [living]>)", 0, None => "(*, <robin ==> bird>, <robin ==> [living]>)";
1952 "(*, robin, <robin ==> bird>, <robin ==> [living]>)", 1, None => "(*, robin, <robin ==> [living]>)";
1953 "(*, robin, <robin ==> bird>, <robin ==> [living]>)", 2, None => "(*, robin, <robin ==> bird>)";
1954 "(*, robin, <robin ==> swimmer>, <robin ==> [flying]>)", 0, None => "(*, <robin ==> swimmer>, <robin ==> [flying]>)";
1955 "(*, robin, <robin ==> swimmer>, <robin ==> [flying]>)", 1, None => "(*, robin, <robin ==> [flying]>)";
1956 "(*, robin, <robin ==> swimmer>, <robin ==> [flying]>)", 2, None => "(*, robin, <robin ==> swimmer>)";
1957 }
1958 ok!()
1959 }
1960 }
1961
1962 mod compound_term_ref_mut {
1964 use super::*;
1965
1966 #[test]
1968 #[allow(unused_variables)]
1969 pub fn assure_safe_interface() -> AResult {
1970 fn use_inner(_: &mut Term) {}
1971 fn use_components(_: &mut [Term]) {}
1972 let mut term = term!("(*, A, B, C)");
1973 let mut mut_compound = term.as_compound_mut().expect("无法转换为可变复合词项");
1974
1975 let components = mut_compound.components();
1977 let inner = mut_compound.inner();
1978 use_inner(inner);
1982 use_components(mut_compound.components());
1984 use_inner(mut_compound.inner()); let inner = mut_compound.inner();
1989 let components = mut_compound.components();
1990 use_components(components);
1994 use_inner(mut_compound.inner());
1996 use_components(mut_compound.components()); ok!()
2003 }
2004
2005 #[test]
2008 fn deref_and_mut() -> AResult {
2009 #[allow(clippy::explicit_auto_deref)]
2011 fn test(mut term: Term) {
2012 assert!(term.is_compound());
2014 let term2 = term.clone();
2016 let mut compound = unsafe { term.as_compound_mut_unchecked() };
2017 dbg!(compound.identifier());
2022 dbg!(compound.components());
2023
2024 dbg!(compound.components_mut());
2026 let original_id = compound.identifier().to_string();
2027 let (id, _) = compound.id_comp_mut();
2028 *id = "MUTATED".into(); assert_eq!(*id, "MUTATED");
2030 *id = original_id; let compound_ref = compound.as_compound().unwrap();
2034 dbg!(compound_ref, compound_ref, compound_ref); asserts! {
2042 compound.is_compound(),
2043 compound.as_compound().is_some(),
2044 compound.as_compound_mut().is_some(),
2045 *compound => term2, compound.clone() => term2, (*compound).clone() => term2, }
2050 }
2051 macro_once! {
2052 macro test($( $term:literal )*) {$(
2054 test(term!($term));
2055 )*}
2056 "{A}"
2065 "[A]"
2066 "(&, A, B)" "(|, A, B)"
2068 "(-, A, B)"
2069 "(~, A, B)"
2070 "(*, A, B, C)"
2071 "(/, R, _)"
2072 r"(\, R, _)"
2073 "(&&, A, B)"
2074 "(||, A, B)"
2075 "(--, A)"
2076 "<A --> B>"
2078 "<A <-> B>"
2079 "<A ==> B>"
2080 "<A <=> B>"
2081 }
2082 ok!()
2083 }
2084
2085 #[test]
2086 pub fn components() -> AResult {
2087 macro_once! {
2088 macro test($($term:literal => $container:expr)*) {
2089 asserts! {$(
2090 compound!(mut $term).components()
2091 => $container
2092 )*}
2093 }
2094 "{A}" => [term!(A)]
2095 "(--, A)" => [term!(A)]
2096 "(-, A, B)" => term!(["A", "B"])
2097 "(~, A, B)" => term!(["A", "B"])
2098 "{A, B, C}" => term!(["A", "B", "C"])
2099 "[A, B, C]" => term!(["A", "B", "C"])
2100 "(*, A, B, C)" => term!(["A", "B", "C"])
2101 "(/, A, B, C, _)" => term!(["A", "B", "C", "_"])
2102 "<A --> B>" => term!(["A", "B"])
2103 "<A <-> B>" => term!(["A", "B"])
2104 "<A ==> B>" => term!(["A", "B"])
2105 "<A <=> B>" => term!(["A", "B"])
2106 "<A --> B>" => term!(["A", "B"])
2107 "<A <-> B>" => term!(["A", "B"])
2108 "<A ==> B>" => term!(["A", "B"])
2109 "<A <=> B>" => term!(["A", "B"])
2110 }
2111 ok!()
2112 }
2113
2114 #[test]
2115 pub fn into_ref() -> AResult {
2116 macro_once! {
2117 macro test($($term:literal)*) {
2118 asserts! {$(
2119 compound!(mut $term).into_ref()
2120 => compound!($term)
2121 )*}
2122 }
2123 "{A}"
2124 "(--, A)"
2125 "(-, A, B)"
2126 "(~, A, B)"
2127 "{A, B, C}"
2128 "[A, B, C]"
2129 "(*, A, B, C)"
2130 "(/, A, B, C, _)"
2131 "<A --> B>"
2132 "<A <-> B>"
2133 "<A ==> B>"
2134 "<A <=> B>"
2135 }
2136 ok!()
2137 }
2138
2139 #[test]
2141 pub fn set_term_when_dealing_variables() -> AResult {
2142 fn test(mut term: Term, i: usize, new: Term, expected: Term) {
2143 term.as_compound_mut().unwrap().components()[i] = new;
2144 assert_eq!(term, expected);
2145 }
2146 macro_once! {
2147 macro test($(
2148 $term:literal [$i:expr] = $new:literal =>
2149 $expected:literal
2150 )*) {
2151 $( test( term!($term), $i, term!($new), term!($expected)); )*
2152 }
2153 "{A}"[0] = "B" => "{B}"
2154 "(--, A)"[0] = "B" => "(--, B)"
2155 "(-, A, B)"[0] = "a" => "(-, a, B)"
2156 "(~, A, B)"[0] = "a" => "(~, a, B)"
2157 "{A, B, Z}"[1] = "X" => "{A, X, Z}" "[A, B, Z]"[1] = "X" => "[A, X, Z]" "(*, A, B, C)"[1] = "X" => "(*, A, X, C)"
2160 "(/, A, _, B, C)"[2] = "X" => "(/, A, _, X, C)"
2161 "<A --> B>"[0] = "a" => "<a --> B>"
2162 "<A <-> B>"[1] = "X" => "<A <-> X>" "<A ==> B>"[0] = "a" => "<a ==> B>"
2164 "<A <=> B>"[1] = "X" => "<A <=> X>" }
2166 ok!()
2167 }
2168
2169 #[test]
2170 pub fn reorder_components() -> AResult {
2171 fn test(mut term: Term, i: usize, new: Term, expected: Term) {
2172 let mut ref_mut = term.as_compound_mut().unwrap();
2173 ref_mut.components()[i] = new;
2174 ref_mut.reorder_components();
2176 assert_eq!(term, expected);
2177 }
2178 macro_once! {
2179 macro test($(
2180 $term:literal [$i:expr] = $new:literal =>
2181 $expected:literal
2182 )*) {
2183 $( test( term!($term), $i, term!($new), term!($expected)); )*
2184 }
2185 "{A, B, C}"[1] = "X" => "{A, X, C}" "[A, B, C]"[1] = "X" => "[A, X, C]" "<A <-> B>"[0] = "a" => "<a <-> B>" "<A <=> B>"[0] = "a" => "<a <=> B>" }
2190 ok!()
2191 }
2192 }
2193
2194 mod compound_term {
2196 use super::*;
2197 use std::str::FromStr;
2198
2199 #[test]
2203 fn from_into() -> AResult {
2204 fn test(compound: CompoundTerm) {
2206 assert!(compound.is_compound());
2208
2209 let term: Term = (*compound).clone();
2211 let _: CompoundTerm = term.try_into().expect("应该是复合词项!");
2212
2213 let term: Term = compound.into();
2215 let _: CompoundTerm = term.try_into().expect("应该是复合词项!");
2216 }
2217 macro_once! {
2218 macro test($( $term:literal )*) {$(
2220 test(test_compound!(box $term));
2221 )*}
2222 "{A}"
2224 "[A]"
2225 "(&, A, B)" "(|, A, B)"
2227 "(-, A, B)"
2228 "(~, A, B)"
2229 "(*, A, B, C)"
2230 "(/, R, _)"
2231 r"(\, R, _)"
2232 "(&&, A, B)"
2233 "(||, A, B)"
2234 "(--, A)"
2235 "<A --> B>"
2237 "<A <-> B>"
2238 "<A ==> B>"
2239 "<A <=> B>"
2240 }
2241 ok!()
2242 }
2243
2244 #[test]
2245 fn get_ref() -> AResult {
2246 fn test(compound: CompoundTerm) {
2248 assert!(compound.is_compound());
2250
2251 let size = compound.get_ref().size();
2253 println!("{compound}.size() => {size}");
2254
2255 compound
2257 .get_ref()
2258 .components()
2259 .iter()
2260 .enumerate()
2261 .for_each(|(i, component)| println!(" [{i}] => {component}"))
2262 }
2263 macro_once! {
2264 macro test($( $term:literal )*) {$(
2266 test(test_compound!(box $term));
2267 )*}
2268 "{A}"
2270 "[A]"
2271 "(&, A, B)" "(|, A, B)"
2273 "(-, A, B)"
2274 "(~, A, B)"
2275 "(*, A, B, C)"
2276 "(/, R, _)"
2277 r"(\, R, _)"
2278 "(&&, A, B)"
2279 "(||, A, B)"
2280 "(--, A)"
2281 "<A --> B>"
2283 "<A <-> B>"
2284 "<A ==> B>"
2285 "<A <=> B>"
2286 }
2287 ok!()
2288 }
2289
2290 #[test]
2291 fn mut_ref() -> AResult {
2292 fn test(mut compound: CompoundTerm) -> AResult {
2294 assert!(compound.is_compound());
2296
2297 let old_s = compound.to_string();
2299 let mut mut_ref = compound.mut_ref();
2300 let first = &mut mut_ref.components()[0];
2301 let x = term!("X");
2302 *first = x.clone();
2303 println!("modification: {old_s:?} => \"{compound}\"");
2304 assert_eq!(compound.get_ref().components[0], x); compound
2308 .mut_ref()
2309 .components()
2310 .iter_mut()
2311 .enumerate()
2312 .for_each(|(i, component)| {
2313 *component = Term::from_str(&format!("T{i}")).unwrap()
2314 });
2315 print!(" => \"{compound}\"");
2316
2317 ok!()
2318 }
2319 macro_once! {
2320 macro test($( $term:literal )*) {$(
2322 test(test_compound!(box $term))?;
2323 )*}
2324 "{A}"
2326 "[A]"
2327 "(&, A, B)" "(|, A, B)"
2329 "(-, A, B)"
2330 "(~, A, B)"
2331 "(*, A, B, C)"
2332 "(/, R, _)"
2333 r"(\, R, _)"
2334 "(&&, A, B)"
2335 "(||, A, B)"
2336 "(--, A)"
2337 "<A --> B>"
2339 "<A <-> B>"
2340 "<A ==> B>"
2341 "<A <=> B>"
2342 }
2343 ok!()
2344 }
2345 }
2346}