1use super::{Term, TermComponents};
11use crate::{
12 language::{variable::MaximumVariableId, vec_utils, CompoundTermRef, StatementRef},
13 symbols::*,
14};
15
16impl Term {
17 #[inline]
21 pub fn make_word(name: impl Into<String>) -> Term {
22 Term::new_word(name)
23 }
24
25 #[inline]
29 pub fn make_placeholder() -> Term {
30 Term::new_placeholder()
31 }
32
33 #[inline]
37 pub fn make_var_i(to_max: impl MaximumVariableId) -> Term {
38 Term::new_var_i(to_max.maximum_variable_id() + 1)
39 }
40
41 #[inline]
43 pub fn make_var_d(to_max: impl MaximumVariableId) -> Term {
44 Term::new_var_d(to_max.maximum_variable_id() + 1)
45 }
46
47 #[inline]
49 pub fn make_var_q(to_max: impl MaximumVariableId) -> Term {
50 Term::new_var_q(to_max.maximum_variable_id() + 1)
51 }
52
53 #[inline]
57 pub fn make_var_similar(from: &Term, id: impl Into<usize>) -> Term {
58 Term::from_var_similar(from.identifier(), id)
59 }
60
61 pub fn make_compound_term(template: CompoundTermRef, components: Vec<Term>) -> Option<Term> {
65 let term = template.inner;
76 match term.identifier.as_str() {
77 IMAGE_EXT_OPERATOR => {
78 Self::make_image_ext_arg(components, template.get_placeholder_index())
79 }
80 IMAGE_INT_OPERATOR => {
81 Self::make_image_int_arg(components, template.get_placeholder_index())
82 }
83 identifier => Self::make_compound_term_from_identifier(identifier, components),
84 }
85 }
86
87 pub fn make_compound_term_or_statement(
88 template: CompoundTermRef,
89 mut components: Vec<Term>,
90 ) -> Option<Term> {
91 match template.as_statement() {
92 Some(statement) => match &components.as_slice() {
94 &[_, _] => {
96 let predicate = components.pop().unwrap();
98 let subject = components.pop().unwrap();
99 Self::make_statement(&statement, subject, predicate)
100 }
101 _ => None,
103 },
104 _ => Self::make_compound_term(template, components),
106 }
107 }
108
109 pub fn make_compound_term_from_identifier(
111 identifier: impl AsRef<str>,
112 argument: Vec<Term>,
113 ) -> Option<Term> {
114 match identifier.as_ref() {
115 SET_EXT_OPERATOR => Self::make_set_ext_arg(argument),
116 SET_INT_OPERATOR => Self::make_set_int_arg(argument),
117 INTERSECTION_EXT_OPERATOR => Self::make_intersection_ext_arg(argument),
118 INTERSECTION_INT_OPERATOR => Self::make_intersection_int_arg(argument),
119 DIFFERENCE_EXT_OPERATOR => Self::make_difference_ext_arg(argument),
120 DIFFERENCE_INT_OPERATOR => Self::make_difference_int_arg(argument),
121 PRODUCT_OPERATOR => Self::make_product_arg(argument),
122 IMAGE_EXT_OPERATOR => Self::make_image_ext_vec(argument),
123 IMAGE_INT_OPERATOR => Self::make_image_int_vec(argument),
124 NEGATION_OPERATOR => Self::make_negation_arg(argument),
125 CONJUNCTION_OPERATOR => Self::make_conjunction_arg(argument),
126 DISJUNCTION_OPERATOR => Self::make_disjunction_arg(argument),
127 _ => None,
129 }
130 }
131
132 #[deprecated]
136 #[allow(unused)]
137 fn arguments_to_list(t1: Term, t2: Term) -> Vec<Term> {
138 vec![t1, t2]
144 }
145
146 fn make_set(t: Term, make_set_arg: fn(Vec<Term>) -> Option<Term>) -> Option<Term> {
151 make_set_arg(vec![t])
152 }
153
154 fn make_set_arg(mut argument: Vec<Term>, new_set: fn(Vec<Term>) -> Term) -> Option<Term> {
158 if argument.is_empty() {
160 return None;
161 }
162 TermComponents::sort_dedup_term_vec(&mut argument);
164 Some(new_set(argument))
166 }
167
168 pub fn make_set_ext(t: Term) -> Option<Term> {
172 Self::make_set(t, Self::make_set_ext_arg)
173 }
174
175 pub fn make_set_ext_arg(argument: Vec<Term>) -> Option<Term> {
177 Self::make_set_arg(argument, Term::new_set_ext)
178 }
179
180 pub fn make_set_int(t: Term) -> Option<Term> {
184 Self::make_set(t, Self::make_set_int_arg)
185 }
186
187 pub fn make_set_int_arg(argument: Vec<Term>) -> Option<Term> {
189 Self::make_set_arg(argument, Term::new_set_int)
190 }
191
192 #[allow(clippy::too_many_arguments)]
200 fn make_intersection(
201 term1: Term,
202 term2: Term,
203 ex_in_set_operator: &str,
205 ex_in_intersection_operator: &str,
206 ex_in_make_set_arg: fn(Vec<Term>) -> Option<Term>,
207 ex_in_make_intersection_vec: fn(Vec<Term>) -> Option<Term>,
208 in_ex_set_operator: &str,
210 in_ex_make_set_arg: fn(Vec<Term>) -> Option<Term>,
211 ) -> Option<Term> {
212 let mut terms = vec![];
214 let make: fn(Vec<Term>) -> Option<Term>;
215 if let [Some(s1), Some(s2)] = [
219 term1.as_compound_type(in_ex_set_operator),
220 term2.as_compound_type(in_ex_set_operator),
221 ] {
222 terms.extend(s1.components.iter().cloned());
224 terms.extend(s2.components.iter().cloned());
226 make = in_ex_make_set_arg;
228 }
229 else if let [Some(s1), Some(s2)] = [
233 term1.as_compound_type(ex_in_set_operator),
234 term2.as_compound_type(ex_in_set_operator),
235 ] {
236 terms.extend(s1.components.iter().cloned());
238 vec_utils::retain_all(&mut terms, s2.components);
240 make = ex_in_make_set_arg;
242 } else {
243 make = ex_in_make_intersection_vec;
245 match [
246 term1.as_compound_type(ex_in_intersection_operator),
247 term2.as_compound_type(ex_in_intersection_operator),
248 ] {
249 [Some(s1), Some(s2)] => {
253 terms.extend(s1.components.iter().cloned());
254 terms.extend(s2.components.iter().cloned());
255 }
256 [Some(s1), None] => {
260 terms.extend(s1.components.iter().cloned());
261 terms.push(term2);
262 }
263 [None, Some(s2)] => {
267 terms.extend(s2.components.iter().cloned());
268 terms.push(term1);
269 }
270 _ => {
274 terms.push(term1);
275 terms.push(term2);
276 }
277 }
278 }
279
280 TermComponents::sort_dedup_term_vec(&mut terms);
282 make(terms)
283 }
284
285 fn make_intersection_arg(
289 mut argument: Vec<Term>,
290 make_arg: fn(Term, Term) -> Option<Term>,
291 ) -> Option<Term> {
292 if argument.is_empty() {
293 return None;
294 }
295 let mut term = argument.remove(0);
298 let mut argument = argument.into_iter();
300 while let Some(t) = argument.next() {
301 term = match make_arg(term, t) {
303 Some(new_term) => new_term,
305 None => argument.next()?,
307 };
308 }
309 Some(term)
311 }
312
313 fn make_intersection_vec(
315 mut terms: Vec<Term>,
316 new_intersection: fn(Vec<Term>) -> Term,
317 ) -> Option<Term> {
318 TermComponents::sort_dedup_term_vec(&mut terms);
320 match terms.len() {
322 0 => None,
324 1 => terms.pop(),
326 _ => Some(new_intersection(terms)),
328 }
329 }
330
331 pub fn make_intersection_ext(term1: Term, term2: Term) -> Option<Term> {
334 Self::make_intersection(
335 term1,
336 term2,
337 SET_EXT_OPERATOR,
338 INTERSECTION_EXT_OPERATOR,
339 Self::make_set_ext_arg,
340 Self::make_intersection_ext_vec,
341 SET_INT_OPERATOR,
342 Self::make_set_int_arg,
343 )
344 }
345
346 pub fn make_intersection_ext_arg(argument: Vec<Term>) -> Option<Term> {
350 Self::make_intersection_arg(argument, Self::make_intersection_ext)
351 }
352
353 pub fn make_intersection_ext_vec(terms: Vec<Term>) -> Option<Term> {
355 Self::make_intersection_vec(terms, Term::new_intersection_ext)
356 }
357
358 pub fn make_intersection_int(term1: Term, term2: Term) -> Option<Term> {
361 Self::make_intersection(
362 term1,
363 term2,
364 SET_INT_OPERATOR,
365 INTERSECTION_INT_OPERATOR,
366 Self::make_set_int_arg,
367 Self::make_intersection_int_vec,
368 SET_EXT_OPERATOR,
369 Self::make_set_ext_arg,
370 )
371 }
372
373 pub fn make_intersection_int_arg(argument: Vec<Term>) -> Option<Term> {
377 Self::make_intersection_arg(argument, Self::make_intersection_int)
378 }
379
380 pub fn make_intersection_int_vec(terms: Vec<Term>) -> Option<Term> {
382 Self::make_intersection_vec(terms, Term::new_intersection_int)
383 }
384
385 fn make_difference(
388 left: Term,
389 right: Term,
390 set_operator: &str,
391 make_set_arg: fn(Vec<Term>) -> Option<Term>,
392 new_diff: fn(Term, Term) -> Term,
393 ) -> Option<Term> {
394 if left == right {
396 return None;
397 }
398 match [
399 left.as_compound_type(set_operator),
400 right.as_compound_type(set_operator),
401 ] {
402 [Some(..), Some(..)] => {
405 let [left, right] = [
407 left.unwrap_compound_components().unwrap(), right.unwrap_compound_components().unwrap(), ];
410 let mut terms = left.into();
413 vec_utils::remove_all(&mut terms, &right);
415 make_set_arg(terms)
417 }
418 _ => Some(new_diff(left, right)),
422 }
423 }
424
425 fn make_difference_arg(
426 mut argument: Vec<Term>,
427 make_difference: fn(Term, Term) -> Option<Term>,
428 ) -> Option<Term> {
429 match argument.len() {
430 1 => argument.pop(), 2 => {
436 let right = argument.pop().unwrap();
437 let left = argument.pop().unwrap();
438 make_difference(left, right)
439 }
440 _ => None,
442 }
443 }
444
445 pub fn make_difference_ext(left: Term, right: Term) -> Option<Term> {
448 Self::make_difference(
449 left,
450 right,
451 SET_EXT_OPERATOR,
452 Self::make_set_ext_arg,
453 Term::new_diff_ext,
454 )
455 }
456
457 fn make_difference_ext_arg(argument: Vec<Term>) -> Option<Term> {
458 Self::make_difference_arg(argument, Self::make_difference_ext)
459 }
460
461 pub fn make_difference_int(left: Term, right: Term) -> Option<Term> {
464 Self::make_difference(
465 left,
466 right,
467 SET_INT_OPERATOR,
468 Self::make_set_int_arg,
469 Term::new_diff_int,
470 )
471 }
472
473 fn make_difference_int_arg(argument: Vec<Term>) -> Option<Term> {
474 Self::make_difference_arg(argument, Self::make_difference_int)
475 }
476
477 pub fn make_product_arg(argument: Vec<Term>) -> Option<Term> {
480 Some(Term::new_product(argument))
481 }
482
483 pub fn make_product(image: CompoundTermRef, component: &Term) -> Option<[Term; 2]> {
488 let mut terms = vec![];
489 let mut image_components = image.components.iter();
490 let relation = image_components.next()?.clone();
491 for term in image_components {
492 if term.is_placeholder() {
494 terms.push(component.clone());
496 continue;
497 }
498 terms.push(term.clone());
500 }
501 Self::make_product_arg(terms).map(|product| [product, relation])
503 }
504
505 fn make_image_arg(
517 mut argument: Vec<Term>,
518 placeholder_index: usize,
519 make_image_vec: fn(Vec<Term>) -> Option<Term>,
520 ) -> Option<Term> {
521 debug_assert!(placeholder_index > 0);
523 if let Some(old_placeholder_index) = argument.iter().position(|term| term.is_placeholder())
525 {
526 argument.remove(old_placeholder_index);
528 } else {
529 let relation = argument.remove(placeholder_index - 1);
531 argument.insert(0, relation);
532 }
533 match placeholder_index >= argument.len() {
535 true => argument.push(Term::new_placeholder()),
537 false => argument.insert(placeholder_index, Term::new_placeholder()),
539 }
540 make_image_vec(argument)
542 }
543
544 fn make_image_vec(
545 argument: Vec<Term>,
546 new_image: fn(Vec<Term>) -> anyhow::Result<Term>,
547 ) -> Option<Term> {
548 if argument.len() < 2 {
550 return None;
551 }
552 debug_assert!(argument.iter().filter(|term| term.is_placeholder()).count() == 1);
554 new_image(argument).ok()
556 }
557
558 fn make_image_from_product(
564 product: CompoundTermRef,
565 relation: &Term,
566 index: usize, make_image_vec: fn(Vec<Term>) -> Option<Term>,
568 ) -> Option<Term> {
569 if let Some(p2) = relation.as_compound_type(PRODUCT_OPERATOR) {
571 if product.size() == 2 && p2.size() == 2 {
573 if index == 0 && product.components[1] == p2.components[1] {
574 return Some(p2.components[0].clone());
577 }
578 if index == 1 && product.components[0] == p2.components[0] {
579 return Some(p2.components[1].clone());
582 }
583 }
584 }
585 let mut argument = vec![relation.clone()];
587 for (i, term) in product.components.iter().enumerate() {
588 let term = match i == index {
589 true => Term::new_placeholder(),
591 false => term.clone(),
593 };
594 argument.push(term);
596 }
597 make_image_vec(argument)
599 }
600
601 fn make_image_from_image(
618 old_image: CompoundTermRef,
619 component: &Term,
620 index: usize,
621 make_image_vec: fn(Vec<Term>) -> Option<Term>,
622 ) -> Option<[Term; 2]> {
623 let old_placeholder_index = old_image.get_placeholder_index();
625 if index + 1 == old_placeholder_index {
627 return Some([old_image.inner.clone(), component.clone()]);
628 }
629 if index + 1 >= old_image.components.len() {
641 return None;
642 }
643 let mut argument = vec![];
645 let outer = old_image.components[index + 1].clone();
646 for (i, term) in old_image.components.iter().enumerate() {
647 let term = if i == index + 1 {
648 Term::new_placeholder()
650 } else if i == old_placeholder_index {
651 component.clone()
653 } else {
654 term.clone()
656 };
657 argument.push(term);
658 }
659 make_image_vec(argument).map(|image| [image, outer])
661 }
662
663 fn make_image_ext_arg(argument: Vec<Term>, placeholder_index: usize) -> Option<Term> {
666 Self::make_image_arg(argument, placeholder_index, Self::make_image_ext_vec)
667 }
668
669 pub fn make_image_ext_vec(argument: impl Into<Vec<Term>>) -> Option<Term> {
684 Self::make_image_vec(argument.into(), Term::new_image_ext)
685 }
686
687 pub fn make_image_ext_from_product(
701 product: CompoundTermRef,
702 relation: &Term,
703 index: usize, ) -> Option<Term> {
705 Self::make_image_from_product(product, relation, index, Self::make_image_ext_vec)
707 }
708
709 pub fn make_image_ext_from_image(
718 old_image: CompoundTermRef,
719 component: &Term,
720 index: usize,
721 ) -> Option<[Term; 2]> {
722 Self::make_image_from_image(old_image, component, index, Self::make_image_ext_vec)
724 }
725
726 fn make_image_int_arg(argument: Vec<Term>, placeholder_index: usize) -> Option<Term> {
729 Self::make_image_arg(argument, placeholder_index, Self::make_image_int_vec)
730 }
731
732 pub fn make_image_int_vec(argument: impl Into<Vec<Term>>) -> Option<Term> {
733 Self::make_image_vec(argument.into(), Term::new_image_int)
734 }
735
736 pub fn make_image_int_from_product(
737 product: CompoundTermRef,
738 relation: &Term,
739 index: usize, ) -> Option<Term> {
741 Self::make_image_from_product(product, relation, index, Self::make_image_int_vec)
743 }
744
745 pub fn make_image_int_from_image(
756 old_image: CompoundTermRef,
757 component: &Term,
758 index: usize,
759 ) -> Option<[Term; 2]> {
760 Self::make_image_from_image(old_image, component, index, Self::make_image_int_vec)
762 }
763
764 fn make_junction_arg(
768 mut argument: Vec<Term>,
769 new_junction: fn(Vec<Term>) -> Term,
770 ) -> Option<Term> {
771 TermComponents::sort_dedup_term_vec(&mut argument);
773 match argument.len() {
775 0 => None,
777 1 => argument.pop(),
780 _ => Some(new_junction(argument)),
782 }
783 }
784
785 fn make_junction(
787 term1: Term,
788 term2: Term,
789 junction_operator: &str,
790 make_junction_arg: fn(Vec<Term>) -> Option<Term>,
791 ) -> Option<Term> {
792 let mut terms: Vec<Term> = vec![];
793 match term1.as_compound_type(junction_operator) {
794 Some(..) => terms.extend(
796 term1
797 .unwrap_compound_components()
798 .expect("已判断是复合词项")
799 .into_vec(),
800 ),
801 _ => terms.push(term1),
803 }
804 match term2.as_compound_type(junction_operator) {
805 Some(..) => terms.extend(
807 term2
808 .unwrap_compound_components()
809 .expect("已判断是复合词项")
810 .into_vec(),
811 ),
812 _ => terms.push(term2),
814 }
815 make_junction_arg(terms)
816 }
817
818 pub fn make_conjunction_arg(argument: Vec<Term>) -> Option<Term> {
822 Self::make_junction_arg(argument, Term::new_conjunction)
823 }
824
825 pub fn make_conjunction(term1: Term, term2: Term) -> Option<Term> {
826 Self::make_junction(
827 term1,
828 term2,
829 CONJUNCTION_OPERATOR,
830 Self::make_conjunction_arg,
831 )
832 }
833
834 pub fn make_disjunction_arg(argument: Vec<Term>) -> Option<Term> {
838 Self::make_junction_arg(argument, Term::new_disjunction)
839 }
840
841 pub fn make_disjunction(term1: Term, term2: Term) -> Option<Term> {
842 Self::make_junction(
843 term1,
844 term2,
845 DISJUNCTION_OPERATOR,
846 Self::make_disjunction_arg,
847 )
848 }
849
850 pub fn make_negation(t: Term) -> Option<Term> {
854 match t.as_compound_type(NEGATION_OPERATOR) {
855 Some(..) => t
858 .unwrap_compound_components()
859 .expect("已经假定是复合词项")
860 .into_vec()
861 .pop(), None => Self::make_negation_arg(vec![t]),
864 }
865 }
866
867 fn make_negation_arg(mut argument: Vec<Term>) -> Option<Term> {
868 match argument.len() {
869 1 => Some(Term::new_negation(argument.pop().unwrap())),
871 _ => None,
873 }
874 }
875
876 pub fn make_statement_relation(
880 copula: impl AsRef<str>,
881 subject: Term,
882 predicate: Term,
883 ) -> Option<Term> {
884 if StatementRef::invalid_statement(&subject, &predicate) {
886 return None;
887 }
888 match copula.as_ref() {
890 INHERITANCE_RELATION => Self::make_inheritance(subject, predicate),
891 SIMILARITY_RELATION => Self::make_similarity(subject, predicate),
892 INSTANCE_RELATION => Self::make_instance(subject, predicate),
893 PROPERTY_RELATION => Self::make_property(subject, predicate),
894 INSTANCE_PROPERTY_RELATION => Self::make_instance_property(subject, predicate),
895 IMPLICATION_RELATION => Self::make_implication(subject, predicate),
896 EQUIVALENCE_RELATION => Self::make_equivalence(subject, predicate),
897 _ => None,
898 }
899 }
900
901 pub fn make_statement(template: &Term, subject: Term, predicate: Term) -> Option<Term> {
909 Term::make_statement_relation(template.identifier(), subject, predicate)
911 }
912
913 pub fn make_statement_symmetric(
922 template: &Term,
923 subject: Term,
924 predicate: Term,
925 ) -> Option<Term> {
926 match template.identifier() {
927 INHERITANCE_RELATION => Self::make_similarity(subject, predicate),
929 IMPLICATION_RELATION => Self::make_equivalence(subject, predicate),
931 identifier => unimplemented!("不支持的标识符:{identifier:?}"),
933 }
934 }
935
936 pub fn make_inheritance(subject: Term, predicate: Term) -> Option<Term> {
939 match StatementRef::invalid_statement(&subject, &predicate) {
941 true => None,
942 false => Some(Term::new_inheritance(subject, predicate)),
943 }
944 }
945
946 pub fn make_instance(subject: Term, predicate: Term) -> Option<Term> {
950 Self::make_inheritance(Self::make_set_ext(subject)?, predicate)
951 }
952
953 pub fn make_property(subject: Term, predicate: Term) -> Option<Term> {
957 Self::make_inheritance(subject, Self::make_set_int(predicate)?)
958 }
959
960 pub fn make_instance_property(subject: Term, predicate: Term) -> Option<Term> {
964 Self::make_inheritance(Self::make_set_ext(subject)?, Self::make_set_int(predicate)?)
965 }
966
967 pub fn make_similarity(subject: Term, predicate: Term) -> Option<Term> {
970 match StatementRef::invalid_statement(&subject, &predicate) {
972 true => None,
973 false => Some(Term::new_similarity(subject, predicate)),
975 }
976 }
977
978 pub fn make_implication(subject: Term, predicate: Term) -> Option<Term> {
981 if StatementRef::invalid_statement(&subject, &predicate) {
985 return None;
986 }
987 if subject.instanceof_implication() || subject.instanceof_equivalence() {
989 return None;
990 }
991 if predicate.instanceof_equivalence() {
992 return None;
993 }
994 if predicate.as_compound_type(IMPLICATION_RELATION).is_some() {
996 let [old_condition, predicate_predicate] = predicate
997 .unwrap_statement_components()
998 .expect("已经假定是复合词项");
999 if let Some(conjunction) = old_condition.as_compound_type(CONJUNCTION_OPERATOR) {
1002 if conjunction.contain_component(&subject) {
1003 return None;
1004 }
1005 }
1006 let new_condition = Self::make_conjunction(subject, old_condition)?;
1008 Self::make_implication(new_condition, predicate_predicate)
1009 } else {
1010 Some(Term::new_implication(subject, predicate))
1011 }
1012 }
1013
1014 pub fn make_equivalence(subject: Term, predicate: Term) -> Option<Term> {
1017 if subject.instanceof_implication() || subject.instanceof_equivalence() {
1021 return None;
1022 }
1023 if subject.instanceof_implication() || subject.instanceof_equivalence() {
1025 return None;
1026 }
1027 match StatementRef::invalid_statement(&subject, &predicate) {
1030 true => None,
1031 false => Some(Term::new_equivalence(subject, predicate)),
1033 }
1034 }
1035}
1036
1037#[cfg(test)]
1038mod tests {
1039 use super::super::test_term::*;
1040 use super::*;
1041 use crate::{ok, option_term, test_term as term, util::AResult};
1042 use nar_dev_utils::macro_once;
1043
1044 mod concrete_type {
1047 use super::*;
1048
1049 fn test_make_one(term: Term, expected: Option<Term>, make: fn(Term) -> Option<Term>) {
1050 let term_str = term.to_string();
1052 let out = make(term);
1054 assert_eq!(
1056 out,
1057 expected,
1058 "{term_str:?} => {} != {}",
1059 format_option_term(&out),
1060 format_option_term(&expected)
1061 );
1062 }
1063
1064 fn test_make_one_f(make: fn(Term) -> Option<Term>) -> impl Fn(Term, Option<Term>) {
1065 move |term, expected| test_make_one(term, expected, make)
1066 }
1067
1068 fn test_make_two(
1069 term1: Term,
1070 term2: Term,
1071 expected: Option<Term>,
1072 make: fn(Term, Term) -> Option<Term>,
1073 ) {
1074 let term1_str = term1.to_string();
1076 let term2_str = term2.to_string();
1077 let out = make(term1, term2);
1079 assert_eq!(
1081 out,
1082 expected,
1083 "{term1_str:?}, {term2_str:?} => {} != {}",
1084 format_option_term(&out),
1085 format_option_term(&expected)
1086 );
1087 }
1088
1089 fn test_make_two_f(
1090 make: fn(Term, Term) -> Option<Term>,
1091 ) -> impl Fn(Term, Term, Option<Term>) {
1092 move |t1, t2, expected| test_make_two(t1, t2, expected, make)
1093 }
1094
1095 fn test_make_arg(
1096 terms: Vec<Term>,
1097 expected: Option<Term>,
1098 make: fn(Vec<Term>) -> Option<Term>,
1099 ) {
1100 let terms_str = format!("{terms:?}");
1102 let out = make(terms);
1104 assert_eq!(
1106 out,
1107 expected,
1108 "{terms_str:?} => {} != {}",
1109 format_option_term(&out),
1110 format_option_term(&expected)
1111 );
1112 }
1113
1114 fn test_make_arg_f(
1115 make: fn(Vec<Term>) -> Option<Term>,
1116 ) -> impl Fn(Vec<Term>, Option<Term>) {
1117 move |argument, expected| test_make_arg(argument, expected, make)
1118 }
1119
1120 fn test_make_image_from_product_f(
1121 make: fn(CompoundTermRef, &Term, usize) -> Option<Term>,
1122 ) -> impl Fn(Term, Term, usize, Term) {
1123 move |p, relation, index, expected| {
1124 let product = p.as_compound().expect("解析出的不是复合词项!");
1125 let image = make(product, &relation, index).expect("词项制作失败!");
1126 assert_eq!(
1127 image, expected,
1128 "{product}, {relation}, {index} => {image} != {expected}"
1129 );
1130 }
1131 }
1132
1133 fn test_make_image_from_image_f(
1134 make: fn(CompoundTermRef, &Term, usize) -> Option<[Term; 2]>,
1135 ) -> impl Fn(Term, Term, usize, Term, Term) {
1136 move |i, component, index, expected, expected_outer| {
1137 let old_image = i.as_compound().expect("解析出的不是复合词项!");
1138 let [image, outer] = make(old_image, &component, index).expect("词项制作失败!");
1139 assert_eq!(
1140 image, expected,
1141 "{old_image}, {component}, {index} => {image} != {expected}"
1142 );
1143 assert_eq!(
1144 outer, expected_outer,
1145 "{old_image}, {component}, {index} => {outer} != {expected_outer}"
1146 );
1147 }
1148 }
1149
1150 #[test]
1153 fn make_set_ext() -> AResult {
1154 let test = test_make_one_f(Term::make_set_ext);
1155 macro_once! {
1156 macro test($($t:tt => $expected:tt;)*) {
1158 $( test(term!($t) ,option_term!($expected)); )*
1159 }
1160 "tom" => "{tom}";
1161 "Tweety" => "{Tweety}";
1162 "Saturn" => "{Saturn}";
1163 "Venus" => "{Venus}";
1164 "tim" => "{tim}";
1165 "Birdie" => "{Birdie}";
1166 "Pluto" => "{Pluto}";
1167 }
1168 ok!()
1169 }
1170
1171 #[test]
1172 fn make_set_ext_arg() -> AResult {
1173 let test = test_make_arg_f(Term::make_set_ext_arg);
1174 macro_once! {
1175 macro test($($argument:tt => $expected:tt;)*) {
1177 $( test(term!($argument).into(), option_term!($expected)); )*
1178 }
1179 [] => None;
1180 ["?49"] => "{?49}";
1181 ["Mars", "Pluto", "Venus"] => "{Mars,Pluto,Venus}";
1182 ["Birdie"] => "{Birdie}";
1183 ["lock"] => "{lock}";
1184 ["#1"] => "{#1}";
1185 ["key1"] => "{key1}";
1186 ["Pluto", "Saturn"] => "{Pluto,Saturn}";
1187 ["Mars", "Venus"] => "{Mars,Venus}";
1188 ["lock1"] => "{lock1}";
1189 ["Tweety"] => "{Tweety}";
1190 }
1191 ok!()
1192 }
1193
1194 #[test]
1197 fn make_set_int() -> AResult {
1198 let test = test_make_one_f(Term::make_set_int);
1199 macro_once! {
1200 macro test($($t:tt => $expected:tt;)*) {
1202 $( test(term!($t) ,option_term!($expected)); )*
1203 }
1204 "[1]" => "[[1]]";
1205 "[{1}]" => "[[{1}]]";
1206 "{[<[1] --> {1}>]}" => "[{[<[1] --> {1}>]}]";
1207 "black" => "[black]";
1209 "yellow" => "[yellow]";
1210 }
1211 ok!()
1212 }
1213
1214 #[test]
1215 fn make_set_int_arg() -> AResult {
1216 let test = test_make_arg_f(Term::make_set_int_arg);
1217 macro_once! {
1218 macro test($($argument:tt => $expected:tt;)*) {
1220 $( test(term!($argument).into(), option_term!($expected)); )*
1221 }
1222 [] => None;
1223 ["1", "2"] => "[1, 2]";
1224 ["1", "2", "[1]", "[2]"] => "[1, 2, [1], [2]]";
1225 ["1", "2", "<1 --> 2>", "<1 --> 2>"] => "[1, 2, <1 --> 2>]"; ["flying"] => "[flying]";
1228 ["unscrewing"] => "[unscrewing]";
1229 ["with_wings"] => "[with_wings]";
1230 ["smart"] => "[smart]";
1231 ["bright"] => "[bright]";
1232 ["strong"] => "[strong]";
1233 ["living"] => "[living]";
1234 ["chirping"] => "[chirping]";
1235 ["aggressive"] => "[aggressive]";
1236 ["black"] => "[black]";
1237 ["bendable"] => "[bendable]";
1238 ["hurt"] => "[hurt]";
1239 ["with_beak"] => "[with_beak]";
1240 }
1241 ok!()
1242 }
1243
1244 #[test]
1247 fn make_intersection_ext() -> AResult {
1248 let test = test_make_two_f(Term::make_intersection_ext);
1249 macro_once! {
1250 macro test($($term1:tt, $term2:tt => $expected:tt;)*) {
1252 $( test(term!($term1), term!($term2), option_term!($expected)); )*
1253 }
1254 "[with_wings]", "[with_wings,yellow]" => "[with_wings,with_wings,yellow]";
1257 "[with_wings]", "[with_wings]" => "[with_wings,with_wings]";
1258 "{Mars,Pluto,Venus}", "{Pluto,Saturn}" => "{Pluto}";
1259 "{Mars,Venus}", "{Pluto,Saturn}" => None;
1260 "{Pluto,Saturn}", "{Mars,Pluto,Venus}" => "{Pluto}";
1261 "{Tweety}", "{Birdie}" => None;
1262 "#1", "bird" => "(&,#1,bird)";
1264 "#1", "{Birdie}" => "(&,#1,{Birdie})";
1265 "(&,bird,{Birdie})", "[yellow]" => "(&,bird,[yellow],{Birdie})";
1266 "(&,bird,{Birdie})", "flyer" => "(&,bird,flyer,{Birdie})";
1267 "(&,flyer,{Birdie})", "(&,bird,[yellow])" => "(&,bird,flyer,[yellow],{Birdie})";
1268 "(|,bird,flyer)", "#1" => "(&,#1,(|,bird,flyer))";
1269 "(|,bird,flyer)", "(|,bird,{Birdie})" => "(&,(|,bird,flyer),(|,bird,{Birdie}))";
1270 "(|,flyer,{Birdie})", "(|,#1,flyer)" => "(&,(|,#1,flyer),(|,flyer,{Birdie}))";
1271 "(|,flyer,{Birdie})", "[with-wings]" => "(&,[with-wings],(|,flyer,{Birdie}))";
1272 "<{Tweety} --> bird>", "<bird --> fly>" => "(&,<bird --> fly>,<{Tweety} --> bird>)";
1273 "[strong]", "(~,youth,girl)" => "(&,[strong],(~,youth,girl))";
1274 "[yellow]", "bird" => "(&,bird,[yellow])";
1275 "animal", "bird" => "(&,animal,bird)";
1276 "bird", "#1" => "(&,#1,bird)";
1277 "bird", "(|,#1,flyer)" => "(&,bird,(|,#1,flyer))";
1278 "bird", "[with-wings]" => "(&,bird,[with-wings])";
1279 "bird", "[yellow]" => "(&,bird,[yellow])";
1280 "bird", "{Birdie}" => "(&,bird,{Birdie})";
1281 "flyer", "(&,bird,[yellow])" => "(&,bird,flyer,[yellow])";
1282 "flyer", "(&,bird,{Birdie})" => "(&,bird,flyer,{Birdie})";
1283 "{Birdie}", "[with-wings]" => "(&,[with-wings],{Birdie})";
1284 "{Birdie}", "[with_wings]" => "(&,[with_wings],{Birdie})";
1285 "{Birdie}", "bird" => "(&,bird,{Birdie})";
1286 "{Tweety}", "#1" => "(&,#1,{Tweety})";
1287 }
1288 ok!()
1289 }
1290
1291 #[test]
1293 fn make_intersection_int() -> AResult {
1294 let test = test_make_two_f(Term::make_intersection_int);
1295 macro_once! {
1296 macro test($($term1:tt, $term2:tt => $expected:tt;)*) {
1298 $( test(term!($term1), term!($term2), option_term!($expected)); )*
1299 }
1300 "#1", "(&,bird,{Birdie})" => "(|,#1,(&,bird,{Birdie}))";
1302 "#1", "bird" => "(|,#1,bird)";
1303 "#1", "{Birdie}" => "(|,#1,{Birdie})";
1304 "(&,#1,{lock1})", "lock1" => "(|,lock1,(&,#1,{lock1}))";
1305 "(&,[with-wings],{Birdie})", "(&,bird,flyer)" => "(|,(&,bird,flyer),(&,[with-wings],{Birdie}))";
1306 "(&,bird,{Birdie})", "[yellow]" => "(|,[yellow],(&,bird,{Birdie}))";
1307 "(&,bird,{Birdie})", "flyer" => "(|,flyer,(&,bird,{Birdie}))";
1308 "(&,flyer,{Birdie})", "(&,bird,[yellow])" => "(|,(&,bird,[yellow]),(&,flyer,{Birdie}))";
1309 "(&,flyer,{Birdie})", "(&,bird,{Birdie})" => "(|,(&,bird,{Birdie}),(&,flyer,{Birdie}))";
1310 "(|,#1,bird)", "{Birdie}" => "(|,#1,bird,{Birdie})";
1311 "(|,[with-wings],(&,bird,[yellow]))", "flyer" => "(|,flyer,[with-wings],(&,bird,[yellow]))";
1312 "(|,bird,flyer)", "#1" => "(|,#1,bird,flyer)";
1313 "(|,bird,flyer)", "(|,bird,{Birdie})" => "(|,bird,flyer,{Birdie})";
1314 "(|,bird,flyer)", "{Birdie}" => "(|,bird,flyer,{Birdie})";
1315 "(|,flyer,[with_wings])", "{Birdie}" => "(|,flyer,[with_wings],{Birdie})";
1316 "(|,flyer,{Birdie})", "(|,#1,flyer)" => "(|,#1,flyer,{Birdie})";
1317 "(|,flyer,{Birdie})", "[with-wings]" => "(|,flyer,[with-wings],{Birdie})";
1318 "(|,flyer,{Tweety})", "{Birdie}" => "(|,flyer,{Birdie},{Tweety})";
1319 "(~,boy,girl)", "(~,youth,girl)" => "(|,(~,boy,girl),(~,youth,girl))";
1320 "[strong]", "(~,youth,girl)" => "(|,[strong],(~,youth,girl))";
1321 "[with-wings]", "#1" => "(|,#1,[with-wings])";
1322 "[with-wings]", "(&,bird,[yellow])" => "(|,[with-wings],(&,bird,[yellow]))";
1323 "[with-wings]", "(&,bird,flyer)" => "(|,[with-wings],(&,bird,flyer))";
1324 "[with-wings]", "(&,bird,{Birdie})" => "(|,[with-wings],(&,bird,{Birdie}))";
1325 "[with-wings]", "(|,bird,flyer)" => "(|,bird,flyer,[with-wings])";
1326 "[with-wings]", "[with_wings,yellow]" => None;
1327 "[with-wings]", "{Birdie}" => "(|,[with-wings],{Birdie})";
1328 "[with_wings]", "(&,bird,[with-wings])" => "(|,[with_wings],(&,bird,[with-wings]))";
1329 "[with_wings]", "(&,bird,{Birdie})" => "(|,[with_wings],(&,bird,{Birdie}))";
1330 "[with_wings]", "(|,bird,{Birdie})" => "(|,bird,[with_wings],{Birdie})";
1331 "[with_wings]", "[with-wings]" => None;
1332 "[with_wings]", "[yellow]" => None;
1333 "[with_wings]", "bird" => "(|,bird,[with_wings])";
1334 "[with_wings]", "{Birdie}" => "(|,[with_wings],{Birdie})";
1335 "animal", "bird" => "(|,animal,bird)";
1336 "bird", "#1" => "(|,#1,bird)";
1337 "bird", "(&,bird,{Birdie})" => "(|,bird,(&,bird,{Birdie}))";
1338 "bird", "(|,#1,flyer)" => "(|,#1,bird,flyer)";
1339 "bird", "(|,bird,flyer)" => "(|,bird,flyer)";
1340 "bird", "(|,flyer,[with-wings])" => "(|,bird,flyer,[with-wings])";
1341 "bird", "[with-wings]" => "(|,bird,[with-wings])";
1342 "bird", "[yellow]" => "(|,bird,[yellow])";
1343 "bird", "{Birdie}" => "(|,bird,{Birdie})";
1344 "boy", "(~,youth,girl)" => "(|,boy,(~,youth,girl))";
1345 "flyer", "(&,bird,[with-wings])" => "(|,flyer,(&,bird,[with-wings]))";
1346 "flyer", "(&,bird,[yellow])" => "(|,flyer,(&,bird,[yellow]))";
1347 "robin", "(|,#1,{Birdie})" => "(|,#1,robin,{Birdie})";
1348 "{Birdie}", "(|,[with_wings],(&,bird,[with-wings]))" => "(|,[with_wings],{Birdie},(&,bird,[with-wings]))";
1349 "{Birdie}", "[with-wings]" => "(|,[with-wings],{Birdie})";
1350 "{Birdie}", "[with_wings]" => "(|,[with_wings],{Birdie})";
1351 "{Birdie}", "bird" => "(|,bird,{Birdie})";
1352 "{Mars,Pluto,Venus}", "{Pluto,Saturn}" => "{Mars,Pluto,Saturn,Venus}";
1353 "{Mars,Venus}", "{Pluto,Saturn}" => "{Mars,Pluto,Saturn,Venus}";
1354 "{Pluto,Saturn}", "{Mars,Pluto,Venus}" => "{Mars,Pluto,Saturn,Venus}";
1355 "{Tweety}", "#1" => "(|,#1,{Tweety})";
1356 "{Tweety}", "{Birdie}" => "{Birdie,Tweety}";
1357 }
1358 ok!()
1359 }
1360
1361 #[test]
1364 fn make_difference_ext_arg() -> AResult {
1365 let test = test_make_arg_f(Term::make_difference_ext_arg);
1366 macro_once! {
1367 macro test($($arg_list:tt => $expected:expr;)*) {
1369 $( test(term!($arg_list).into(), option_term!($expected)); )*
1370 }
1371 ["swimmer", "bird"] => "(-,swimmer,bird)";
1373 ["mammal", "swimmer"] => "(-,mammal,swimmer)";
1374 ["bird", "swimmer"] => "(-,bird,swimmer)";
1375 ["swimmer", "animal"] => "(-,swimmer,animal)";
1376 }
1377 ok!()
1378 }
1379
1380 #[test]
1381 fn make_difference_ext() -> AResult {
1382 let test = test_make_two_f(Term::make_difference_ext);
1383 macro_once! {
1384 macro test($($term1:tt, $term2:tt => $expected:expr;)*) {
1386 $( test(term!($term1), term!($term2), option_term!($expected)); )*
1387 }
1388 "(&,bird,(|,[yellow],{Birdie}))", "[with_wings]" => "(-,(&,bird,(|,[yellow],{Birdie})),[with_wings])";
1390 "(&,bird,flyer)", "[with_wings]" => "(-,(&,bird,flyer),[with_wings])";
1391 "(&,flyer,[yellow])", "[with_wings]" => "(-,(&,flyer,[yellow]),[with_wings])";
1392 "(&,flyer,{Birdie})", "[with_wings]" => "(-,(&,flyer,{Birdie}),[with_wings])";
1393 "(/,open,_,#1)", "(/,open,_,{lock1})" => "(-,(/,open,_,#1),(/,open,_,{lock1}))";
1394 "(|,[yellow],{Birdie})", "[with_wings]" => "(-,(|,[yellow],{Birdie}),[with_wings])";
1395 "(|,[yellow],{Birdie})", "bird" => "(-,(|,[yellow],{Birdie}),bird)";
1396 "(|,bird,flyer)", "[with_wings]" => "(-,(|,bird,flyer),[with_wings])";
1397 "(|,bird,swimmer)", "animal" => "(-,(|,bird,swimmer),animal)";
1398 "(|,bird,{Birdie})", "[with_wings]" => "(-,(|,bird,{Birdie}),[with_wings])";
1399 "(|,chess,competition)", "(|,competition,sport)" => "(-,(|,chess,competition),(|,competition,sport))";
1400 "(|,flyer,[with_wings])", "[yellow]" => "(-,(|,flyer,[with_wings]),[yellow])";
1401 "(|,flyer,[yellow])", "{Birdie}" => "(-,(|,flyer,[yellow]),{Birdie})";
1402 "[yellow]", "[with_wings]" => "(-,[yellow],[with_wings])";
1403 "[yellow]", "bird" => "(-,[yellow],bird)";
1404 "[yellow]", "{Birdie}" => "(-,[yellow],{Birdie})";
1405 "animal", "swimmer" => "(-,animal,swimmer)";
1406 "bird", "[with_wings]" => "(-,bird,[with_wings])";
1407 "{Birdie}", "[with_wings]" => "(-,{Birdie},[with_wings])";
1408 "{Birdie}", "flyer" => "(-,{Birdie},flyer)";
1409 "{Mars,Pluto,Venus}", "{Pluto,Saturn}" => "{Mars,Venus}";
1410 }
1411 ok!()
1412 }
1413
1414 #[test]
1417 fn make_difference_int_arg() -> AResult {
1418 let test = test_make_arg_f(Term::make_difference_int_arg);
1419 macro_once! {
1420 macro test($($arg_list:tt => $expected:expr;)*) {
1422 $( test(term!($arg_list).into(), option_term!($expected)); )*
1423 }
1424 ["(~,boy,girl)", "girl"] => "(~,(~,boy,girl),girl)";
1426 ["swimmer", "swan"] => "(~,swimmer,swan)";
1427 ["youth", "girl"] => "(~,youth,girl)";
1428 ["(|,boy,girl)", "girl"] => "(~,(|,boy,girl),girl)";
1429 ["boy", "girl"] => "(~,boy,girl)";
1430 ["(/,(*,tim,tom),tom,_)", "(/,uncle,tom,_)"] => "(~,(/,(*,tim,tom),tom,_),(/,uncle,tom,_))";
1431 ["[strong]", "girl"] => "(~,[strong],girl)";
1432 }
1433 ok!()
1434 }
1435
1436 #[test]
1437 fn make_difference_int() -> AResult {
1438 let test = test_make_two_f(Term::make_difference_int);
1439 macro_once! {
1440 macro test($($term1:tt, $term2:tt => $expected:expr;)*) {
1442 $( test(term!($term1), term!($term2), option_term!($expected)); )*
1443 }
1444 "(&,bird,robin)", "tiger" => "(~,(&,bird,robin),tiger)";
1446 "(&,flyer,{Birdie})", "(&,flyer,robin)" => "(~,(&,flyer,{Birdie}),(&,flyer,robin))";
1447 "(&,flyer,{Birdie})", "robin" => "(~,(&,flyer,{Birdie}),robin)";
1448 "(/,(*,tim,tom),tom,_)", "(/,uncle,tom,_)" => "(~,(/,(*,tim,tom),tom,_),(/,uncle,tom,_))";
1449 "(/,(*,tim,tom),tom,_)", "tim" => "(~,(/,(*,tim,tom),tom,_),tim)";
1450 "(/,open,_,lock)", "{key1}" => "(~,(/,open,_,lock),{key1})";
1451 "(|,bird,robin)", "tiger" => "(~,(|,bird,robin),tiger)";
1452 "(|,flyer,[with_wings],{Birdie})", "robin" => "(~,(|,flyer,[with_wings],{Birdie}),robin)";
1453 "(|,flyer,{Birdie})", "robin" => "(~,(|,flyer,{Birdie}),robin)";
1454 "(~,boy,girl)", "girl" => "(~,(~,boy,girl),girl)";
1455 "[strong]", "girl" => "(~,[strong],girl)";
1456 "animal", "bird" => "(~,animal,bird)";
1457 "bird", "#1" => "(~,bird,#1)";
1458 "bird", "(|,robin,tiger)" => "(~,bird,(|,robin,tiger))";
1459 "{Birdie}", "(|,flyer,robin)" => "(~,{Birdie},(|,flyer,robin))";
1460 "{Birdie}", "robin" => "(~,{Birdie},robin)";
1461 "{Tweety}", "(&,flyer,robin)" => "(~,{Tweety},(&,flyer,robin))";
1462 "{Tweety}", "(|,robin,[yellow],{Birdie})" => "(~,{Tweety},(|,robin,[yellow],{Birdie}))";
1463 "{lock1}", "#1" => "(~,{lock1},#1)";
1464 }
1465 ok!()
1466 }
1467
1468 #[test]
1471 fn make_image_ext_vec() -> AResult {
1472 let test = test_make_arg_f(Term::make_image_ext_vec);
1473 macro_once! {
1474 macro test($($arg_list:tt => $expected:expr;)*) {
1476 $( test(term!($arg_list).into(), option_term!($expected)); )*
1477 }
1478 ["reaction", "_", "base"] => "(/,reaction,_,base)";
1479 ["reaction", "acid", "_"] => "(/,reaction,acid,_)";
1480 ["neutralization", "_", "base"] => "(/,neutralization,_,base)";
1481 ["open", "$120", "_"] => "(/,open,$120,_)";
1482 }
1483 ok!()
1484 }
1485
1486 #[test]
1487 fn make_image_ext_from_product() -> AResult {
1488 let test = test_make_image_from_product_f(Term::make_image_ext_from_product);
1489 macro_once! {
1490 macro test($($product:tt, $relation:tt, $index:tt => $expected:expr;)*) {
1492 $( test( term!($product), term!($relation), $index, term!($expected) ); )*
1493 }
1494 "(*,$1,sunglasses)", "own", 1 => "(/,own,$1,_)";
1496 "(*,bird,plant)", "?1", 0 => "(/,?1,_,plant)";
1497 "(*,bird,plant)", "?1", 1 => "(/,?1,bird,_)";
1498 "(*,robin,worms)", "food", 1 => "(/,food,robin,_)";
1499 "(*,CAT,eat,fish)", "R", 0 => "(/,R,_,eat,fish)";
1500 "(*,CAT,eat,fish)", "R", 1 => "(/,R,CAT,_,fish)";
1501 "(*,CAT,eat,fish)", "R", 2 => "(/,R,CAT,eat,_)";
1502 "(*,b,a)", "(*,b,(/,like,b,_))", 1 => "(/,like,b,_)";
1503 "(*,a,b)", "(*,(/,like,b,_),b)", 0 => "(/,like,b,_)";
1504 r"(*,(/,like,b,_),b)", r"(*,a,b)", 0 => r"a";
1506 r"(*,(&,key,(/,open,_,{lock1})),lock1)", r"(*,{key1},lock1)", 0 => r"{key1}";
1507 r"(*,(\,reaction,_,soda),base)", r"(*,(\,neutralization,_,soda),base)", 0 => r"(\,neutralization,_,soda)";
1508 r"(*,(&,key,(/,open,_,{lock1})),lock)", r"(*,{key1},lock)", 0 => r"{key1}";
1509 r"(*,b,(/,like,b,_))", r"(*,b,a)", 1 => r"a";
1510 r"(*,(/,like,_,a),a)", r"(*,b,a)", 0 => r"b";
1511 }
1512 ok!()
1513 }
1514
1515 #[test]
1516 fn make_image_ext_from_image() -> AResult {
1517 let test = test_make_image_from_image_f(Term::make_image_ext_from_image);
1518 macro_once! {
1519 macro test($($image:tt, $component:tt, $index:tt => [$expected:expr, $expected_outer:expr];)*) {
1521 $( test( term!($image), term!($component), $index, term!($expected), term!($expected_outer) ); )*
1522 }
1523 "(/,open,{key1},_)", "lock", 1 => ["(/,open,{key1},_)", "lock"];
1525 "(/,open,{key1},_)", "lock", 0 => ["(/,open,_,lock)", "{key1}"];
1527 "(/,uncle,_,tom)", "tim", 1 => ["(/,uncle,tim,_)", "tom"];
1528 "(/,open,{key1},_)", "$2", 0 => ["(/,open,_,$2)", "{key1}"];
1529 "(/,open,{key1},_)", "#1", 0 => ["(/,open,_,#1)", "{key1}"];
1530 "(/,like,_,a)", "b", 1 => ["(/,like,b,_)", "a"];
1531 "(/,like,b,_)", "a", 0 => ["(/,like,_,a)", "b"];
1532 }
1533 ok!()
1534 }
1535
1536 #[test]
1539 fn make_image_int_vec() -> AResult {
1540 let test = test_make_arg_f(Term::make_image_int_vec);
1541 macro_once! {
1542 macro test($($arg_list:tt => $expected:expr;)*) {
1544 $( test(term!($arg_list).into(), option_term!($expected)); )*
1545 }
1546 ["reaction", "_", "base"] => r"(\,reaction,_,base)";
1548 ["reaction", "acid", "_"] => r"(\,reaction,acid,_)";
1549 ["neutralization", "_", "base"] => r"(\,neutralization,_,base)";
1550 ["open", "$120", "_"] => r"(\,open,$120,_)";
1551 }
1552 ok!()
1553 }
1554
1555 #[test]
1556 fn make_image_int_from_product() -> AResult {
1557 let test = test_make_image_from_product_f(Term::make_image_int_from_product);
1558 macro_once! {
1559 macro test($($product:tt, $relation:tt, $index:tt => $expected:expr;)*) {
1561 $( test( term!($product), term!($relation), $index, term!($expected) ); )*
1562 }
1563 r"(*,(/,num,_))", "#1", 0 => r"(\,#1,_)";
1565 r"(*,(\,reaction,_,soda),base)", "neutralization", 1 => r"(\,neutralization,(\,reaction,_,soda),_)";
1566 r"(*,(\,reaction,_,soda),base)", "neutralization", 0 => r"(\,neutralization,_,base)";
1567 r"(*,(/,num,_))", "(*,num)", 0 => r"(\,(*,num),_)";
1568 r"(*,acid,soda)", "reaction", 0 => r"(\,reaction,_,soda)";
1569 r"(*,(*,num))", "(*,(*,(/,num,_)))", 0 => r"(\,(*,(*,(/,num,_))),_)";
1570 r"(*,(*,(*,num)))", "(*,(*,(*,0)))", 0 => r"(\,(*,(*,(*,0))),_)";
1571 r"(*,(\,reaction,_,soda),base)", "#1", 1 => r"(\,#1,(\,reaction,_,soda),_)";
1572 r"(*,(*,num))", "(*,(*,0))", 0 => r"(\,(*,(*,0)),_)";
1573 r"(*,acid,base)", "reaction", 0 => r"(\,reaction,_,base)";
1574 r"(*,b,(/,like,b,_))", "(*,b,a)", 0 => r"(\,(*,b,a),_,(/,like,b,_))";
1575 r"(*,(\,reaction,_,soda),base)", "#1", 0 => r"(\,#1,_,base)";
1576 r"(*,(*,(/,num,_)))", "(*,(*,0))", 0 => r"(\,(*,(*,0)),_)";
1577 r"(*,(/,num,_))", "(*,0)", 0 => r"(\,(*,0),_)";
1578 r"(*,(/,num,_))", "$1", 0 => r"(\,$1,_)";
1579 r"(*,num)", "(*,0)", 0 => r"(\,(*,0),_)";
1580 r"(*,acid,soda)", "reaction", 1 => r"(\,reaction,acid,_)";
1581 r"(*,(/,like,_,a),a)", "(*,b,a)", 1 => r"(\,(*,b,a),(/,like,_,a),_)";
1582 r"(*,acid,base)", "reaction", 1 => r"(\,reaction,acid,_)";
1583 r"(*,(&,key,(/,open,_,{lock1})),lock)", "(*,{key1},lock)", 1 => r"(\,(*,{key1},lock),(&,key,(/,open,_,{lock1})),_)";
1584 r"(*,(/,like,b,_),b)", "(*,a,b)", 1 => r"(\,(*,a,b),(/,like,b,_),_)";
1585 r"(*,(\,reaction,_,soda),base)", r"(*,(\,reaction,_,soda),soda)", 1 => r"soda";
1587 r"(*,(\,reaction,_,soda),base)", r"(*,acid,base)", 0 => r"acid";
1588 r"(*,acid,(\,neutralization,acid,_))", r"(*,acid,(\,reaction,acid,_))", 1 => r"(\,reaction,acid,_)";
1589 r"(*,(&,key,(/,open,_,{lock1})),lock)", r"(*,{key1},lock)", 0 => r"{key1}";
1590 r"(*,(\,neutralization,_,soda),base)", r"(*,(\,reaction,_,soda),base)", 0 => r"(\,reaction,_,soda)";
1591 r"(*,(/,open,_,#1),{lock1})", r"(*,{key1},{lock1})", 0 => r"{key1}";
1592 r"(*,key,lock)", r"(*,{key1},lock)", 0 => r"{key1}";
1593 r"(*,acid,(\,reaction,acid,_))", r"(*,acid,soda)", 1 => r"soda";
1594 r"(*,(|,key,(/,open,_,{lock1})),lock1)", r"(*,{key1},lock1)", 0 => r"{key1}";
1595 r"(*,(&,key,(/,open,_,{lock1})),lock1)", r"(*,{key1},lock1)", 0 => r"{key1}";
1596 }
1597 ok!()
1598 }
1599
1600 #[test]
1601 fn make_image_int_from_image() -> AResult {
1602 let test = test_make_image_from_image_f(Term::make_image_int_from_image);
1603 macro_once! {
1604 macro test($($image:tt, $component:tt, $index:tt => [$expected:expr, $expected_outer:expr];)*) {
1606 $( test( term!($image), term!($component), $index, term!($expected), term!($expected_outer) ); )*
1607 }
1608 r"(\,R,_,eat,fish)", "cat", 0 => [r"(\,R,_,eat,fish)", "cat"];
1610 r"(\,R,_,eat,fish)", "cat", 2 => [r"(\,R,cat,eat,_)", "fish"];
1612 r"(\,reaction,acid,_)", "soda", 0 => [r"(\,reaction,_,soda)", "acid"];
1613 r"(\,R,_,eat,fish)", r"(\,REPRESENT,_,$1)", 2 => [r"(\,R,(\,REPRESENT,_,$1),eat,_)", "fish"];
1614 r"(\,neutralization,_,soda)", "acid", 1 => [r"(\,neutralization,acid,_)", "soda"];
1615 r"(\,neutralization,acid,_)", "$1", 0 => [r"(\,neutralization,_,$1)", "acid"];
1616 r"(\,REPRESENT,_,$1)", r"(\,R,_,eat,fish)", 1 => [r"(\,REPRESENT,(\,R,_,eat,fish),_)", "$1"];
1617 r"(\,neutralization,acid,_)", "soda", 0 => [r"(\,neutralization,_,soda)", "acid"];
1618 r"(\,neutralization,acid,_)", "?1", 0 => [r"(\,neutralization,_,?1)", "acid"];
1619 r"(\,reaction,acid,_)", r"(\,neutralization,acid,_)", 0 => [r"(\,reaction,_,(\,neutralization,acid,_))", "acid"];
1620 r"(\,REPRESENT,_,CAT)", "(/,R,_,eat,fish)", 1 => [r"(\,REPRESENT,(/,R,_,eat,fish),_)", "CAT"];
1621 r"(\,R,_,eat,fish)", r"(\,REPRESENT,_,$1)", 1 => [r"(\,R,(\,REPRESENT,_,$1),_,fish)", "eat"];
1622 r"(\,R,_,eat,fish)", "cat", 1 => [r"(\,R,cat,_,fish)", "eat"];
1623 r"(\,reaction,_,soda)", "acid", 1 => [r"(\,reaction,acid,_)", "soda"];
1624 r"(\,reaction,_,base)", r"(\,reaction,_,soda)", 1 => [r"(\,reaction,(\,reaction,_,soda),_)", "base"];
1625 r"(\,neutralization,acid,_)", "#1", 0 => [r"(\,neutralization,_,#1)", "acid"];
1626 r"(\,neutralization,acid,_)", "base", 0 => [r"(\,neutralization,_,base)", "acid"];
1627 r"(\,reaction,_,base)", "acid", 1 => [r"(\,reaction,acid,_)", "base"];
1628 r"(\,neutralization,acid,_)", "(/,reaction,acid,_)", 0 => [r"(\,neutralization,_,(/,reaction,acid,_))", "acid"];
1629 }
1630 ok!()
1631 }
1632 }
1633
1634 mod compound {
1635 use super::*;
1636
1637 fn test_make_term_with_identifier_f(
1638 make: fn(&str, Vec<Term>) -> Option<Term>,
1639 ) -> impl Fn(&str, Vec<Term>, Option<Term>) {
1640 move |identifier, terms, expected| {
1641 let terms_str = terms
1642 .iter()
1643 .map(|t| format!("\"{t}\""))
1644 .collect::<Vec<_>>()
1645 .join(", ");
1646 let out = make(identifier, terms);
1647 assert_eq!(
1648 out,
1649 expected,
1650 "{identifier:?}, {terms_str} => {} != {}",
1651 format_option_term(&out),
1652 format_option_term(&expected),
1653 );
1654 }
1655 }
1656
1657 #[test]
1658 fn make_compound_term_from_identifier() -> AResult {
1659 fn make(identifier: &str, terms: Vec<Term>) -> Option<Term> {
1660 Term::make_compound_term_from_identifier(identifier, terms)
1661 }
1662 let test = test_make_term_with_identifier_f(make);
1663 macro_once! {
1664 macro test($($identifier:tt, $terms:tt => $expected:tt;)*) {
1666 $( test($identifier, term!($terms).into(), option_term!($expected)); )*
1667 }
1668 "&", ["(&,robin,{Tweety})", "{Birdie}"] => "(&,robin,{Birdie},{Tweety})";
1670 "&", ["(/,neutralization,_,(\\,neutralization,acid,_))", "acid"] => "(&,acid,(/,neutralization,_,(\\,neutralization,acid,_)))";
1671 "&", ["(/,neutralization,_,base)", "(/,reaction,_,base)"] => "(&,(/,neutralization,_,base),(/,reaction,_,base))";
1672 "&", ["(/,neutralization,_,base)", "acid"] => "(&,acid,(/,neutralization,_,base))";
1673 "&", ["(/,open,_,{lock1})", "(/,open,_,lock)"] => "(&,(/,open,_,lock),(/,open,_,{lock1}))";
1674 "&", ["(\\,REPRESENT,_,CAT)", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(&,(\\,REPRESENT,_,CAT),(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1675 "&", ["(\\,reaction,_,soda)", "(\\,neutralization,_,base)"] => "(&,(\\,neutralization,_,base),(\\,reaction,_,soda))";
1676 "&", ["(|,(/,open,_,lock1),(/,open,_,{lock1}))", "(/,open,_,lock)"] => "(&,(/,open,_,lock),(|,(/,open,_,lock1),(/,open,_,{lock1})))";
1677 "&", ["(|,bird,{Tweety})", "(|,bird,{Birdie})"] => "(&,(|,bird,{Birdie}),(|,bird,{Tweety}))";
1678 "&", ["(|,key,(/,open,_,{lock1}))", "(/,open,_,lock)"] => "(&,(/,open,_,lock),(|,key,(/,open,_,{lock1})))";
1679 "&", ["acid", "(/,reaction,_,base)"] => "(&,acid,(/,reaction,_,base))";
1680 "&", ["acid", "(\\,neutralization,_,base)"] => "(&,acid,(\\,neutralization,_,base))";
1681 "&", ["animal", "(&,robin,swan)"] => "(&,animal,robin,swan)";
1682 "&", ["animal", "(|,animal,swimmer)"] => "(&,animal,(|,animal,swimmer))";
1683 "&", ["animal", "gull"] => "(&,animal,gull)";
1684 "&", ["bird", "robin", "{Birdie}", "(|,[yellow],{Birdie})"] => "(&,bird,robin,{Birdie},(|,[yellow],{Birdie}))";
1685 "&", ["flyer", "[with_wings]"] => "(&,flyer,[with_wings])";
1686 "&", ["flyer", "{Birdie}", "(|,[with_wings],{Birdie})"] => "(&,flyer,{Birdie},(|,[with_wings],{Birdie}))";
1687 "&", ["flyer", "{Birdie}"] => "(&,flyer,{Birdie})";
1688 "&", ["key", "(/,open,_,{lock1})"] => "(&,key,(/,open,_,{lock1}))";
1689 "&", ["neutralization", "(*,(\\,neutralization,_,base),base)"] => "(&,neutralization,(*,(\\,neutralization,_,base),base))";
1690 "&", ["neutralization", "(*,acid,(/,reaction,acid,_))"] => "(&,neutralization,(*,acid,(/,reaction,acid,_)))";
1691 "&", ["neutralization", "(*,acid,base)"] => "(&,neutralization,(*,acid,base))";
1692 "&", ["num", "(/,num,_)"] => "(&,num,(/,num,_))";
1693 "&", ["{Birdie}", "(|,flyer,{Tweety})"] => "(&,{Birdie},(|,flyer,{Tweety}))";
1694 "&", ["{Birdie}", "{Tweety}"] => None;
1695 "&&", ["<robin --> [chirping]>", "<robin --> [flying]>"] => "(&&,<robin --> [chirping]>,<robin --> [flying]>)";
1696 "&&", ["<robin --> [chirping]>"] => "<robin --> [chirping]>";
1697 "&&", ["<robin --> bird>", "(||,(&&,<robin --> [flying]>,<robin --> [with_wings]>),<robin --> bird>)"] => "(&&,<robin --> bird>,(||,(&&,<robin --> [flying]>,<robin --> [with_wings]>),<robin --> bird>))";
1698 "&&", ["<robin --> bird>", "<robin --> [flying]>", "<robin --> [with_wings]>"] => "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)";
1699 "&&", ["<robin --> bird>", "<robin --> [flying]>"] => "(&&,<robin --> bird>,<robin --> [flying]>)";
1700 "&&", ["<robin --> bird>"] => "<robin --> bird>";
1701 "&&", ["<robin --> flyer>", "<(*,robin,worms) --> food>"] => "(&&,<robin --> flyer>,<(*,robin,worms) --> food>)";
1702 "&&", ["<robin --> flyer>", "<robin --> bird>", "<(*,robin,worms) --> food>"] => "(&&,<robin --> bird>,<robin --> flyer>,<(*,robin,worms) --> food>)";
1703 "&&", ["<robin --> flyer>", "<robin --> bird>", "<worms --> (/,food,robin,_)>"] => "(&&,<robin --> bird>,<robin --> flyer>,<worms --> (/,food,robin,_)>)";
1704 "&&", ["<robin --> flyer>", "<robin --> bird>"] => "(&&,<robin --> bird>,<robin --> flyer>)";
1705 "&&", ["<robin --> flyer>", "<worms --> (/,food,robin,_)>"] => "(&&,<robin --> flyer>,<worms --> (/,food,robin,_)>)";
1706 "*", ["(&,key,(/,open,_,{lock1}))", "lock"] => "(*,(&,key,(/,open,_,{lock1})),lock)";
1707 "*", ["(&,num,(/,(*,(/,num,_)),_))"] => "(*,(&,num,(/,(*,(/,num,_)),_)))";
1708 "*", ["(*,num)"] => "(*,(*,num))";
1709 "*", ["(/,(*,(/,num,_)),_)"] => "(*,(/,(*,(/,num,_)),_))";
1710 "*", ["(/,(/,num,_),_)"] => "(*,(/,(/,num,_),_))";
1711 "*", ["(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>)", "<(*,CAT,FISH) --> FOOD>"] => "(*,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),<(*,CAT,FISH) --> FOOD>)";
1712 "*", ["(/,num,_)"] => "(*,(/,num,_))";
1713 "*", ["(/,open,_,lock)", "lock"] => "(*,(/,open,_,lock),lock)";
1714 "*", ["(/,open,_,lock)", "{lock1}"] => "(*,(/,open,_,lock),{lock1})";
1715 "*", ["(/,open,_,{lock1})", "lock"] => "(*,(/,open,_,{lock1}),lock)";
1716 "*", ["(/,open,_,{lock1})", "{lock1}"] => "(*,(/,open,_,{lock1}),{lock1})";
1717 "*", ["(\\,neutralization,_,base)", "base"] => "(*,(\\,neutralization,_,base),base)";
1718 "*", ["(|,(/,open,_,lock1),(/,open,_,{lock1}))", "lock1"] => "(*,(|,(/,open,_,lock1),(/,open,_,{lock1})),lock1)";
1719 "*", ["(|,key,(/,open,_,{lock1}))", "lock"] => "(*,(|,key,(/,open,_,{lock1})),lock)";
1720 "*", ["0"] => "(*,0)";
1721 "*", ["a", "b"] => "(*,a,b)";
1722 "*", ["acid", "(&,soda,(/,neutralization,acid,_))"] => "(*,acid,(&,soda,(/,neutralization,acid,_)))";
1723 "*", ["acid", "(/,neutralization,acid,_)"] => "(*,acid,(/,neutralization,acid,_))";
1724 "*", ["acid", "(\\,neutralization,acid,_)"] => "(*,acid,(\\,neutralization,acid,_))";
1725 "*", ["acid", "(|,base,(\\,reaction,acid,_))"] => "(*,acid,(|,base,(\\,reaction,acid,_)))";
1726 "*", ["key", "{lock1}"] => "(*,key,{lock1})";
1727 "*", ["{key1}", "lock1"] => "(*,{key1},lock1)";
1728 "[]", ["bright"] => "[bright]";
1729 "{}", ["Birdie"] => "{Birdie}";
1730 "{}", ["Mars", "Venus"] => "{Mars,Venus}";
1731 "|", ["(&,animal,gull)", "swimmer"] => "(|,swimmer,(&,animal,gull))";
1732 "|", ["(&,flyer,{Birdie})", "(|,[yellow],{Birdie})"] => "(|,[yellow],{Birdie},(&,flyer,{Birdie}))";
1733 "|", ["(&,flyer,{Birdie})", "{Birdie}"] => "(|,{Birdie},(&,flyer,{Birdie}))";
1734 "|", ["(/,neutralization,_,base)", "(/,reaction,_,(\\,neutralization,acid,_))"] => "(|,(/,neutralization,_,base),(/,reaction,_,(\\,neutralization,acid,_)))";
1735 "|", ["(/,neutralization,_,base)", "(/,reaction,_,base)"] => "(|,(/,neutralization,_,base),(/,reaction,_,base))";
1736 "|", ["(/,neutralization,_,base)", "acid"] => "(|,acid,(/,neutralization,_,base))";
1737 "|", ["(/,neutralization,acid,_)", "(\\,neutralization,acid,_)"] => "(|,(/,neutralization,acid,_),(\\,neutralization,acid,_))";
1738 "|", ["(/,num,_)", "0"] => "(|,0,(/,num,_))";
1739 "|", ["(/,open,_,{lock1})", "(/,open,_,lock)"] => "(|,(/,open,_,lock),(/,open,_,{lock1}))";
1740 "|", ["(\\,REPRESENT,_,CAT)", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(|,(\\,REPRESENT,_,CAT),(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1741 "|", ["(|,key,(/,open,_,{lock1}))", "(/,open,_,lock)"] => "(|,key,(/,open,_,lock),(/,open,_,{lock1}))";
1742 "|", ["(~,boy,girl)", "(~,youth,girl)"] => "(|,(~,boy,girl),(~,youth,girl))";
1743 "|", ["[with_wings]", "(|,flyer,{Tweety})", "{Birdie}"] => "(|,flyer,[with_wings],{Birdie},{Tweety})";
1744 "|", ["[with_wings]", "flyer", "{Birdie}"] => "(|,flyer,[with_wings],{Birdie})";
1745 "|", ["[with_wings]", "{Birdie}", "(|,[with_wings],{Birdie})"] => "(|,[with_wings],{Birdie})";
1746 "|", ["[with_wings]", "{Tweety}", "{Birdie}"] => "(|,[with_wings],{Birdie},{Tweety})";
1747 "|", ["[yellow]", "[with_wings]"] => None;
1748 "|", ["[yellow]", "bird"] => "(|,bird,[yellow])";
1749 "|", ["[yellow]", "{Tweety}"] => "(|,[yellow],{Tweety})";
1750 "|", ["acid", "(/,reaction,_,base)"] => "(|,acid,(/,reaction,_,base))";
1751 "|", ["acid", "(\\,neutralization,_,base)"] => "(|,acid,(\\,neutralization,_,base))";
1752 "|", ["animal", "robin"] => "(|,animal,robin)";
1753 "|", ["bird", "[with_wings]"] => "(|,bird,[with_wings])";
1754 "|", ["bird", "flyer", "{Birdie}"] => "(|,bird,flyer,{Birdie})";
1755 "|", ["bird", "{Birdie}"] => "(|,bird,{Birdie})";
1756 "|", ["bird", "{Tweety}", "{Birdie}"] => "(|,bird,{Birdie},{Tweety})";
1757 "|", ["boy", "(~,youth,girl)"] => "(|,boy,(~,youth,girl))";
1758 "|", ["chess", "(|,chess,sport)"] => "(|,chess,sport)";
1759 "|", ["flyer", "(&,flyer,{Birdie})", "{Birdie}"] => "(|,flyer,{Birdie},(&,flyer,{Birdie}))";
1760 "|", ["flyer", "(&,flyer,{Birdie})"] => "(|,flyer,(&,flyer,{Birdie}))";
1761 "|", ["flyer", "(|,flyer,{Tweety})", "{Birdie}"] => "(|,flyer,{Birdie},{Tweety})";
1762 "|", ["flyer", "[yellow]", "{Birdie}"] => "(|,flyer,[yellow],{Birdie})";
1763 "|", ["flyer", "{Birdie}", "(&,bird,(|,[yellow],{Birdie}))"] => "(|,flyer,{Birdie},(&,bird,(|,[yellow],{Birdie})))";
1764 "|", ["flyer", "{Birdie}", "(&,flyer,{Birdie})"] => "(|,flyer,{Birdie},(&,flyer,{Birdie}))";
1765 "|", ["key", "(/,open,_,{lock1})"] => "(|,key,(/,open,_,{lock1}))";
1766 "|", ["neutralization", "(*,acid,(\\,neutralization,acid,_))"] => "(|,neutralization,(*,acid,(\\,neutralization,acid,_)))";
1767 "|", ["neutralization", "(*,acid,base)"] => "(|,neutralization,(*,acid,base))";
1768 "|", ["robin", "(|,flyer,{Tweety})", "{Birdie}"] => "(|,flyer,robin,{Birdie},{Tweety})";
1769 "|", ["tiger", "(|,animal,swimmer)"] => "(|,animal,swimmer,tiger)";
1770 "|", ["{Birdie}", "{Tweety}"] => "{Birdie,Tweety}";
1771 "|", ["{Tweety}", "{Birdie}", "(&,flyer,{Birdie})"] => "(|,(&,flyer,{Birdie}),{Birdie,Tweety})";
1772 "~", ["(/,(*,tim,tom),tom,_)", "(/,uncle,tom,_)"] => "(~,(/,(*,tim,tom),tom,_),(/,uncle,tom,_))";
1773 "~", ["(|,boy,girl)", "girl"] => "(~,(|,boy,girl),girl)";
1774 "~", ["(~,boy,girl)", "girl"] => "(~,(~,boy,girl),girl)";
1775 "~", ["[strong]", "girl"] => "(~,[strong],girl)";
1776 "~", ["boy", "girl"] => "(~,boy,girl)";
1777 }
1778 ok!()
1779 }
1780
1781 #[test]
1782 fn make_compound_term() -> AResult {
1783 fn test(template: Term, terms: Vec<Term>, expected: Option<Term>) {
1784 let terms_str = terms
1785 .iter()
1786 .map(|t| format!("\"{t}\""))
1787 .collect::<Vec<_>>()
1788 .join(", ");
1789 let out = Term::make_compound_term(
1790 template.as_compound().expect("模板不是复合词项!"),
1791 terms,
1792 );
1793 assert_eq!(
1794 out,
1795 expected,
1796 "\"{template}\", {terms_str} => {} != {}",
1797 format_option_term(&out),
1798 format_option_term(&expected),
1799 );
1800 }
1801 macro_once! {
1802 macro test($($template:tt, $terms:tt => $expected:tt;)*) {
1804 $(
1805 test(
1806 term!($template),
1807 term!($terms).into(),
1808 option_term!($expected),
1809 );
1810 )*
1811 }
1812 "(&&,<robin --> [chirping]>,<robin --> [flying]>)", ["<robin --> [chirping]>"] => "<robin --> [chirping]>";
1814 "(&&,<robin --> [chirping]>,<robin --> [flying]>)", ["<robin --> bird>", "<robin --> [flying]>"] => "(&&,<robin --> bird>,<robin --> [flying]>)";
1815 "(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [with_wings]>)", ["<robin --> [chirping]>", "<robin --> [flying]>"] => "(&&,<robin --> [chirping]>,<robin --> [flying]>)";
1816 "(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [with_wings]>)", ["<robin --> bird>", "<robin --> [flying]>", "<robin --> [with_wings]>"] => "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)";
1817 "(&&,<robin --> [chirping]>,<robin --> [with_wings]>)", ["<robin --> [chirping]>", "<robin --> bird>"] => "(&&,<robin --> bird>,<robin --> [chirping]>)";
1818 "(&&,<robin --> bird>,<robin --> [flying]>)", ["<robin --> [flying]>"] => "<robin --> [flying]>";
1819 "(&&,<robin --> bird>,<robin --> [flying]>)", ["<robin --> bird>"] => "<robin --> bird>";
1820 "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)", ["<robin --> [flying]>", "<robin --> [with_wings]>"] => "(&&,<robin --> [flying]>,<robin --> [with_wings]>)";
1821 "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)", ["<robin --> bird>", "<robin --> [flying]>", "<robin --> bird>"] => "(&&,<robin --> bird>,<robin --> [flying]>)";
1822 "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)", ["<robin --> bird>", "<robin --> [flying]>"] => "(&&,<robin --> bird>,<robin --> [flying]>)";
1823 "(&&,<robin --> bird>,<robin --> [living]>)", ["<robin --> bird>", "(||,(&&,<robin --> [flying]>,<robin --> [with_wings]>),<robin --> bird>)"] => "(&&,<robin --> bird>,(||,(&&,<robin --> [flying]>,<robin --> [with_wings]>),<robin --> bird>))";
1824 "(&&,<robin --> bird>,<robin --> [living]>)", ["<robin --> bird>", "<robin --> [flying]>", "<robin --> [with_wings]>"] => "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)";
1825 "(&&,<robin --> bird>,<robin --> [living]>)", ["<robin --> bird>", "<robin --> [flying]>"] => "(&&,<robin --> bird>,<robin --> [flying]>)";
1826 "(&&,<robin --> bird>,<robin --> [living]>)", ["<robin --> bird>", "<robin --> bird>", "<robin --> [flying]>"] => "(&&,<robin --> bird>,<robin --> [flying]>)";
1827 "(&&,<robin --> flyer>,<(*,robin,worms) --> food>)", ["<robin --> flyer>", "<worms --> (/,food,robin,_)>"] => "(&&,<robin --> flyer>,<worms --> (/,food,robin,_)>)";
1828 "(&&,<robin --> flyer>,<robin --> [chirping]>)", ["<robin --> flyer>", "<robin --> bird>"] => "(&&,<robin --> bird>,<robin --> flyer>)";
1829 "(&&,<robin --> flyer>,<robin --> [chirping]>,<(*,robin,worms) --> food>)", ["<robin --> flyer>", "<(*,robin,worms) --> food>"] => "(&&,<robin --> flyer>,<(*,robin,worms) --> food>)";
1830 "(&&,<robin --> flyer>,<robin --> [chirping]>,<(*,robin,worms) --> food>)", ["<robin --> flyer>", "<robin --> bird>", "<(*,robin,worms) --> food>"] => "(&&,<robin --> bird>,<robin --> flyer>,<(*,robin,worms) --> food>)";
1831 "(&&,<robin --> flyer>,<robin --> [chirping]>,<worms --> (/,food,robin,_)>)", ["<robin --> flyer>", "<robin --> bird>", "<worms --> (/,food,robin,_)>"] => "(&&,<robin --> bird>,<robin --> flyer>,<worms --> (/,food,robin,_)>)";
1832 "(&&,<robin --> flyer>,<robin --> [chirping]>,<worms --> (/,food,robin,_)>)", ["<robin --> flyer>", "<worms --> (/,food,robin,_)>"] => "(&&,<robin --> flyer>,<worms --> (/,food,robin,_)>)";
1833 "(&&,<robin --> flyer>,<worms --> (/,food,robin,_)>)", ["<robin --> flyer>", "<(*,robin,worms) --> food>"] => "(&&,<robin --> flyer>,<(*,robin,worms) --> food>)";
1834 "(&,(/,neutralization,_,(\\,neutralization,acid,_)),(/,reaction,_,base))", ["(/,neutralization,_,(\\,neutralization,acid,_))", "acid"] => "(&,acid,(/,neutralization,_,(\\,neutralization,acid,_)))";
1835 "(&,(/,neutralization,_,(\\,neutralization,acid,_)),(/,reaction,_,base))", ["acid", "(/,reaction,_,base)"] => "(&,acid,(/,reaction,_,base))";
1836 "(&,(/,neutralization,_,base),(/,reaction,_,soda))", ["(/,neutralization,_,base)", "(/,reaction,_,base)"] => "(&,(/,neutralization,_,base),(/,reaction,_,base))";
1837 "(&,(/,neutralization,_,base),(/,reaction,_,soda))", ["(/,neutralization,_,base)", "acid"] => "(&,acid,(/,neutralization,_,base))";
1838 "(&,(/,neutralization,_,soda),(/,reaction,_,base))", ["acid", "(/,reaction,_,base)"] => "(&,acid,(/,reaction,_,base))";
1839 "(&,(/,open,_,lock),(/,open,_,{lock1}))", ["(/,open,_,lock)", "key"] => "(&,key,(/,open,_,lock))";
1840 "(&,(\\,REPRESENT,_,CAT),(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))", ["(\\,REPRESENT,_,CAT)", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(&,(\\,REPRESENT,_,CAT),(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1841 "(&,(\\,REPRESENT,_,CAT),(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))", ["cat", "(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(&,cat,(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1842 "(&,(\\,reaction,_,soda),(|,acid,(\\,reaction,_,base)))", ["(\\,reaction,_,soda)", "(\\,neutralization,_,base)"] => "(&,(\\,neutralization,_,base),(\\,reaction,_,soda))";
1843 "(&,(|,bird,flyer),(|,bird,{Birdie}))", ["(|,bird,{Tweety})", "(|,bird,{Birdie})"] => "(&,(|,bird,{Birdie}),(|,bird,{Tweety}))";
1844 "(&,(|,bird,flyer),(|,bird,{Birdie}))", ["{Tweety}", "(|,bird,{Birdie})"] => "(&,{Tweety},(|,bird,{Birdie}))";
1845 "(&,[with_wings],{Birdie})", ["(&,robin,{Tweety})", "{Birdie}"] => "(&,robin,{Birdie},{Tweety})";
1846 "(&,[with_wings],{Birdie})", ["flyer", "{Birdie}"] => "(&,flyer,{Birdie})";
1847 "(&,[with_wings],{Birdie})", ["{Tweety}", "{Birdie}"] => None;
1848 "(&,acid,(/,neutralization,_,soda))", ["acid", "(/,reaction,_,base)"] => "(&,acid,(/,reaction,_,base))";
1849 "(&,acid,(\\,reaction,_,base))", ["acid", "(\\,neutralization,_,base)"] => "(&,acid,(\\,neutralization,_,base))";
1850 "(&,animal,(|,animal,swimmer))", ["animal", "gull"] => "(&,animal,gull)";
1851 "(&,animal,(|,bird,swimmer))", ["animal", "(&,robin,swan)"] => "(&,animal,robin,swan)";
1852 "(&,animal,gull)", ["animal", "(|,animal,swimmer)"] => "(&,animal,(|,animal,swimmer))";
1853 "(&,animal,gull)", ["animal", "swan"] => "(&,animal,swan)";
1854 "(&,base,(\\,reaction,acid,_))", ["base", "(/,reaction,acid,_)"] => "(&,base,(/,reaction,acid,_))";
1855 "(&,base,(\\,reaction,acid,_))", ["base", "soda"] => "(&,base,soda)";
1856 "(&,bird,[with_wings],{Birdie},(|,[yellow],{Birdie}))", ["bird", "robin", "{Birdie}", "(|,[yellow],{Birdie})"] => "(&,bird,robin,{Birdie},(|,[yellow],{Birdie}))";
1857 "(&,flyer,[with_wings])", ["flyer", "(&,robin,{Tweety})"] => "(&,flyer,robin,{Tweety})";
1858 "(&,flyer,[with_wings])", ["flyer", "robin"] => "(&,flyer,robin)";
1859 "(&,flyer,[with_wings])", ["flyer", "{Birdie}"] => "(&,flyer,{Birdie})";
1860 "(&,flyer,[yellow],(|,[with_wings],{Birdie}))", ["flyer", "{Birdie}", "(|,[with_wings],{Birdie})"] => "(&,flyer,{Birdie},(|,[with_wings],{Birdie}))";
1861 "(&,flyer,{Birdie})", ["flyer", "[with_wings]"] => "(&,flyer,[with_wings])";
1862 "(&,flyer,{Birdie})", ["flyer", "bird"] => "(&,bird,flyer)";
1863 "(&,flyer,{Birdie})", ["flyer", "{Tweety}"] => "(&,flyer,{Tweety})";
1864 "(&,key,(/,open,_,lock))", ["key", "(/,open,_,{lock1})"] => "(&,key,(/,open,_,{lock1}))";
1865 "(&,key,(/,open,_,lock))", ["key", "{key1}"] => "(&,key,{key1})";
1866 "(&,neutralization,(*,(\\,reaction,_,soda),base))", ["neutralization", "(*,(\\,neutralization,_,base),base)"] => "(&,neutralization,(*,(\\,neutralization,_,base),base))";
1867 "(&,neutralization,(*,(\\,reaction,_,soda),base))", ["neutralization", "reaction"] => "(&,neutralization,reaction)";
1868 "(&,neutralization,(*,acid,(\\,neutralization,acid,_)))", ["neutralization", "(*,acid,(/,reaction,acid,_))"] => "(&,neutralization,(*,acid,(/,reaction,acid,_)))";
1869 "(&,neutralization,(*,acid,(\\,neutralization,acid,_)))", ["neutralization", "(*,acid,soda)"] => "(&,neutralization,(*,acid,soda))";
1870 "(&,neutralization,(*,acid,soda))", ["neutralization", "(*,acid,base)"] => "(&,neutralization,(*,acid,base))";
1871 "(&,neutralization,(*,acid,soda))", ["neutralization", "reaction"] => "(&,neutralization,reaction)";
1872 "(&,num,(/,(*,0),_))", ["num", "(/,num,_)"] => "(&,num,(/,num,_))";
1873 "(&,tiger,(|,bird,robin))", ["bird", "(|,bird,robin)"] => "(&,bird,(|,bird,robin))";
1874 "(&,{Birdie},(|,flyer,[yellow]))", ["{Birdie}", "(|,flyer,{Tweety})"] => "(&,{Birdie},(|,flyer,{Tweety}))";
1875 "(&,{Birdie},(|,flyer,[yellow]))", ["{Birdie}", "{Tweety}"] => None;
1876 "(&,{key1},(/,open,_,lock))", ["(/,open,_,{lock1})", "(/,open,_,lock)"] => "(&,(/,open,_,lock),(/,open,_,{lock1}))";
1877 "(&,{key1},(/,open,_,lock))", ["(|,(/,open,_,lock1),(/,open,_,{lock1}))", "(/,open,_,lock)"] => "(&,(/,open,_,lock),(|,(/,open,_,lock1),(/,open,_,{lock1})))";
1878 "(&,{key1},(/,open,_,lock))", ["(|,key,(/,open,_,{lock1}))", "(/,open,_,lock)"] => "(&,(/,open,_,lock),(|,key,(/,open,_,{lock1})))";
1879 "(&,{key1},(/,open,_,lock))", ["key", "(/,open,_,lock)"] => "(&,key,(/,open,_,lock))";
1880 "(*,(*,(*,0)))", ["(*,(*,(/,num,_)))"] => "(*,(*,(*,(/,num,_))))";
1881 "(*,(*,0))", ["(*,(/,num,_))"] => "(*,(*,(/,num,_)))";
1882 "(*,(*,0))", ["(*,num)"] => "(*,(*,num))";
1883 "(*,(*,CAT,eat,fish),<(*,CAT,FISH) --> FOOD>)", ["(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>)", "<(*,CAT,FISH) --> FOOD>"] => "(*,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),<(*,CAT,FISH) --> FOOD>)";
1884 "(*,(/,(*,0),_))", ["(/,num,_)"] => "(*,(/,num,_))";
1885 "(*,(/,(/,num,_),_))", ["(/,num,_)"] => "(*,(/,num,_))";
1886 "(*,(/,num,_))", ["(/,(/,num,_),_)"] => "(*,(/,(/,num,_),_))";
1887 "(*,(/,num,_))", ["0"] => "(*,0)";
1888 "(*,(/,open,_,lock1),lock1)", ["{key1}", "lock1"] => "(*,{key1},lock1)";
1889 "(*,(\\,reaction,_,base),base)", ["(\\,neutralization,_,base)", "base"] => "(*,(\\,neutralization,_,base),base)";
1890 "(*,(\\,reaction,_,soda),base)", ["acid", "base"] => "(*,acid,base)";
1891 "(*,(|,key,(/,open,_,{lock1})),lock)", ["(/,open,_,lock)", "lock"] => "(*,(/,open,_,lock),lock)";
1892 "(*,0)", ["(&,num,(/,(*,(/,num,_)),_))"] => "(*,(&,num,(/,(*,(/,num,_)),_)))";
1893 "(*,0)", ["(/,(*,(/,num,_)),_)"] => "(*,(/,(*,(/,num,_)),_))";
1894 "(*,0)", ["(/,num,_)"] => "(*,(/,num,_))";
1895 "(*,0)", ["num"] => "(*,num)";
1896 "(*,a,(/,like,_,a))", ["a", "b"] => "(*,a,b)";
1897 "(*,a,b)", ["(/,like,b,_)", "b"] => "(*,(/,like,b,_),b)";
1898 "(*,a,b)", ["a", "(/,like,_,a)"] => "(*,a,(/,like,_,a))";
1899 "(*,acid,(&,soda,(/,neutralization,acid,_)))", ["acid", "(/,reaction,acid,_)"] => "(*,acid,(/,reaction,acid,_))";
1900 "(*,acid,(/,reaction,acid,_))", ["acid", "(&,soda,(/,neutralization,acid,_))"] => "(*,acid,(&,soda,(/,neutralization,acid,_)))";
1901 "(*,acid,(/,reaction,acid,_))", ["acid", "(/,neutralization,acid,_)"] => "(*,acid,(/,neutralization,acid,_))";
1902 "(*,acid,(/,reaction,acid,_))", ["acid", "(\\,neutralization,acid,_)"] => "(*,acid,(\\,neutralization,acid,_))";
1903 "(*,acid,(/,reaction,acid,_))", ["acid", "(|,base,(\\,reaction,acid,_))"] => "(*,acid,(|,base,(\\,reaction,acid,_)))";
1904 "(*,acid,base)", ["acid", "(\\,neutralization,acid,_)"] => "(*,acid,(\\,neutralization,acid,_))";
1905 "(*,acid,base)", ["acid", "soda"] => "(*,acid,soda)";
1906 "(*,{key1},lock)", ["(&,key,(/,open,_,{lock1}))", "lock"] => "(*,(&,key,(/,open,_,{lock1})),lock)";
1907 "(*,{key1},lock)", ["(/,open,_,{lock1})", "lock"] => "(*,(/,open,_,{lock1}),lock)";
1908 "(*,{key1},lock)", ["(|,key,(/,open,_,{lock1}))", "lock"] => "(*,(|,key,(/,open,_,{lock1})),lock)";
1909 "(*,{key1},lock)", ["key", "lock"] => "(*,key,lock)";
1910 "(*,{key1},lock1)", ["(/,open,_,lock)", "lock1"] => "(*,(/,open,_,lock),lock1)";
1911 "(*,{key1},lock1)", ["(|,(/,open,_,lock1),(/,open,_,{lock1}))", "lock1"] => "(*,(|,(/,open,_,lock1),(/,open,_,{lock1})),lock1)";
1912 "(*,{key1},{lock1})", ["(/,open,_,lock)", "{lock1}"] => "(*,(/,open,_,lock),{lock1})";
1913 "(*,{key1},{lock1})", ["(/,open,_,{lock1})", "{lock1}"] => "(*,(/,open,_,{lock1}),{lock1})";
1914 "(*,{key1},{lock1})", ["key", "{lock1}"] => "(*,key,{lock1})";
1915 "(/,(*,(/,num,_)),_)", ["(*,num)"] => "(/,(*,num),_)";
1916 "(/,(*,b,(/,like,b,_)),_,a)", ["(*,b,a)", "a"] => "(/,(*,b,a),_,a)";
1917 "(/,(*,num),_)", ["(*,0)"] => "(/,(*,0),_)";
1918 "(/,(*,tim,tom),tom,_)", ["tom", "uncle"] => "(/,uncle,tom,_)";
1919 "(/,(/,num,_),_)", ["0"] => "(/,0,_)";
1920 "(/,0,_)", ["(&,num,(/,(*,(/,num,_)),_))"] => "(/,(&,num,(/,(*,(/,num,_)),_)),_)";
1921 "(/,0,_)", ["(/,num,_)"] => "(/,(/,num,_),_)";
1922 "(/,0,_)", ["num"] => "(/,num,_)";
1923 "(/,like,_,a)", ["like", "(/,like,b,_)"] => "(/,like,_,(/,like,b,_))";
1924 "(/,like,b,_)", ["(/,like,_,a)", "like"] => "(/,like,(/,like,_,a),_)";
1925 "(/,neutralization,_,base)", ["neutralization", "(\\,neutralization,acid,_)"] => "(/,neutralization,_,(\\,neutralization,acid,_))";
1926 "(/,neutralization,_,base)", ["neutralization", "soda"] => "(/,neutralization,_,soda)";
1927 "(/,num,_)", ["(*,0)"] => "(/,(*,0),_)";
1928 "(/,open,_,(|,lock,(/,open,{key1},_)))", ["open", "{lock1}"] => "(/,open,_,{lock1})";
1929 "(/,open,_,{lock1})", ["open", "(|,lock,(/,open,{key1},_))"] => "(/,open,_,(|,lock,(/,open,{key1},_)))";
1930 "(/,open,_,{lock1})", ["open", "lock"] => "(/,open,_,lock)";
1931 "(/,reaction,_,base)", ["(*,acid,soda)", "base"] => "(/,(*,acid,soda),_,base)";
1932 "(/,reaction,acid,_)", ["acid", "(*,acid,soda)"] => "(/,(*,acid,soda),acid,_)";
1933 "(\\,(*,b,a),_,(/,like,b,_))", ["like", "(/,like,b,_)"] => "(\\,like,_,(/,like,b,_))";
1934 "(\\,REPRESENT,_,CAT)", ["REPRESENT", "(\\,REPRESENT,_,CAT)"] => "(\\,REPRESENT,_,(\\,REPRESENT,_,CAT))";
1935 "(\\,neutralization,_,(/,neutralization,acid,_))", ["neutralization", "soda"] => "(\\,neutralization,_,soda)";
1936 "(\\,neutralization,_,(/,reaction,acid,_))", ["neutralization", "(/,neutralization,acid,_)"] => "(\\,neutralization,_,(/,neutralization,acid,_))";
1937 "(\\,neutralization,_,(/,reaction,acid,_))", ["neutralization", "(\\,neutralization,acid,_)"] => "(\\,neutralization,_,(\\,neutralization,acid,_))";
1938 "(\\,neutralization,_,(/,reaction,acid,_))", ["neutralization", "(|,base,(\\,reaction,acid,_))"] => "(\\,neutralization,_,(|,base,(\\,reaction,acid,_)))";
1939 "(\\,neutralization,_,base)", ["neutralization", "(/,neutralization,acid,_)"] => "(\\,neutralization,_,(/,neutralization,acid,_))";
1940 "(\\,neutralization,_,base)", ["neutralization", "soda"] => "(\\,neutralization,_,soda)";
1941 "(\\,neutralization,acid,_)", ["(\\,reaction,_,base)", "neutralization"] => "(\\,neutralization,(\\,reaction,_,base),_)";
1942 "(\\,reaction,(\\,reaction,_,soda),_)", ["(\\,reaction,_,base)", "reaction"] => "(\\,reaction,(\\,reaction,_,base),_)";
1943 "(\\,reaction,_,base)", ["(*,acid,soda)", "base"] => "(\\,(*,acid,soda),_,base)";
1944 "(\\,reaction,acid,_)", ["acid", "(*,acid,soda)"] => "(\\,(*,acid,soda),acid,_)";
1945 "(|,(&,animal,gull),(&,bird,robin))", ["(&,animal,gull)", "swimmer"] => "(|,swimmer,(&,animal,gull))";
1946 "(|,(&,flyer,{Birdie}),{Birdie,Tweety})", ["(&,flyer,{Birdie})", "(|,[yellow],{Birdie})"] => "(|,[yellow],{Birdie},(&,flyer,{Birdie}))";
1947 "(|,(/,neutralization,_,(\\,neutralization,acid,_)),(/,reaction,_,base))", ["(/,neutralization,_,base)", "(/,reaction,_,base)"] => "(|,(/,neutralization,_,base),(/,reaction,_,base))";
1948 "(|,(/,neutralization,_,(\\,neutralization,acid,_)),(/,reaction,_,base))", ["acid", "(/,reaction,_,base)"] => "(|,acid,(/,reaction,_,base))";
1949 "(|,(/,neutralization,_,base),(/,reaction,_,base))", ["(/,neutralization,_,base)", "acid"] => "(|,acid,(/,neutralization,_,base))";
1950 "(|,(/,neutralization,_,base),(/,reaction,_,soda))", ["(/,neutralization,_,base)", "(/,neutralization,_,(\\,neutralization,acid,_))"] => "(|,(/,neutralization,_,base),(/,neutralization,_,(\\,neutralization,acid,_)))";
1951 "(|,(/,neutralization,_,base),(/,reaction,_,soda))", ["(/,neutralization,_,base)", "(/,reaction,_,base)"] => "(|,(/,neutralization,_,base),(/,reaction,_,base))";
1952 "(|,(/,neutralization,_,soda),(/,reaction,_,base))", ["acid", "(/,reaction,_,base)"] => "(|,acid,(/,reaction,_,base))";
1953 "(|,(/,num,_),(/,(*,num),_))", ["(/,num,_)", "0"] => "(|,0,(/,num,_))";
1954 "(|,(\\,REPRESENT,_,CAT),(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))", ["(\\,REPRESENT,_,CAT)", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(|,(\\,REPRESENT,_,CAT),(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1955 "(|,(\\,REPRESENT,_,CAT),(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))", ["cat", "(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(|,cat,(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1956 "(|,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))", ["(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)"] => "(|,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish),(\\,(\\,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))";
1957 "(|,[strong],(~,youth,girl))", ["(~,boy,girl)", "(~,youth,girl)"] => "(|,(~,boy,girl),(~,youth,girl))";
1958 "(|,[strong],(~,youth,girl))", ["boy", "(~,youth,girl)"] => "(|,boy,(~,youth,girl))";
1959 "(|,X,Y)", ["[with_wings]", "(|,flyer,{Tweety})", "{Birdie}"] => "(|,flyer,[with_wings],{Birdie},{Tweety})"; "(|,X,Y)", ["[with_wings]", "flyer", "{Birdie}"] => "(|,flyer,[with_wings],{Birdie})"; "(|,X,Y)", ["[with_wings]", "{Tweety}", "{Birdie}"] => "(|,[with_wings],{Birdie},{Tweety})"; "(|,X,Y)", ["flyer", "[yellow]", "{Birdie}"] => "(|,flyer,[yellow],{Birdie})"; "(|,[with_wings],{Birdie})", ["flyer", "{Birdie}"] => "(|,flyer,{Birdie})";
1964 "(|,[with_wings],{Birdie})", ["{Tweety}", "{Birdie}"] => "{Birdie,Tweety}";
1965 "(|,[with_wings],{Birdie},(&,bird,(|,[yellow],{Birdie})))", ["flyer", "{Birdie}", "(&,bird,(|,[yellow],{Birdie}))"] => "(|,flyer,{Birdie},(&,bird,(|,[yellow],{Birdie})))";
1966 "(|,[with_wings],{Birdie},(&,flyer,[yellow]))", ["[with_wings]", "{Birdie}", "(|,[with_wings],{Birdie})"] => "(|,[with_wings],{Birdie})";
1967 "(|,[yellow],{Birdie})", ["(&,flyer,{Birdie})", "{Birdie}"] => "(|,{Birdie},(&,flyer,{Birdie}))";
1968 "(|,[yellow],{Birdie})", ["[yellow]", "[with_wings]"] => None;
1969 "(|,[yellow],{Birdie})", ["[yellow]", "bird"] => "(|,bird,[yellow])";
1970 "(|,[yellow],{Birdie})", ["[yellow]", "{Tweety}"] => "(|,[yellow],{Tweety})";
1971 "(|,[yellow],{Birdie},(&,flyer,{Birdie}))", ["flyer", "{Birdie}", "(&,flyer,{Birdie})"] => "(|,flyer,{Birdie},(&,flyer,{Birdie}))";
1972 "(|,[yellow],{Birdie},(&,flyer,{Birdie}))", ["{Tweety}", "{Birdie}", "(&,flyer,{Birdie})"] => "(|,(&,flyer,{Birdie}),{Birdie,Tweety})";
1973 "(|,acid,(/,neutralization,_,soda))", ["acid", "(/,reaction,_,base)"] => "(|,acid,(/,reaction,_,base))";
1974 "(|,acid,(\\,reaction,_,base))", ["acid", "(\\,neutralization,_,base)"] => "(|,acid,(\\,neutralization,_,base))";
1975 "(|,animal,gull)", ["animal", "robin"] => "(|,animal,robin)";
1976 "(|,base,(\\,reaction,acid,_))", ["base", "(/,reaction,acid,_)"] => "(|,base,(/,reaction,acid,_))";
1977 "(|,base,(\\,reaction,acid,_))", ["base", "soda"] => "(|,base,soda)";
1978 "(|,bird,(&,robin,tiger))", ["bird", "animal"] => "(|,animal,bird)";
1979 "(|,bird,[yellow])", ["bird", "flyer"] => "(|,bird,flyer)";
1980 "(|,bird,[yellow])", ["bird", "{Birdie}"] => "(|,bird,{Birdie})";
1981 "(|,bird,[yellow],{Birdie})", ["bird", "flyer", "{Birdie}"] => "(|,bird,flyer,{Birdie})";
1982 "(|,bird,[yellow],{Birdie})", ["bird", "{Tweety}", "{Birdie}"] => "(|,bird,{Birdie},{Tweety})";
1983 "(|,bird,{Birdie})", ["bird", "[with_wings]"] => "(|,bird,[with_wings])";
1984 "(|,bird,{Birdie})", ["bird", "flyer"] => "(|,bird,flyer)";
1985 "(|,bird,{Birdie})", ["bird", "{Tweety}"] => "(|,bird,{Tweety})";
1986 "(|,bird,{Tweety})", ["bird", "(|,bird,flyer)"] => "(|,bird,flyer)";
1987 "(|,chess,competition)", ["chess", "(|,chess,sport)"] => "(|,chess,sport)";
1988 "(|,flyer,[yellow])", ["flyer", "(&,flyer,{Birdie})"] => "(|,flyer,(&,flyer,{Birdie}))";
1989 "(|,flyer,[yellow],(&,flyer,{Birdie}))", ["flyer", "{Birdie}", "(&,flyer,{Birdie})"] => "(|,flyer,{Birdie},(&,flyer,{Birdie}))";
1990 "(|,flyer,[yellow],{Birdie})", ["flyer", "(&,flyer,{Birdie})", "{Birdie}"] => "(|,flyer,{Birdie},(&,flyer,{Birdie}))";
1991 "(|,flyer,[yellow],{Birdie})", ["flyer", "(|,flyer,{Tweety})", "{Birdie}"] => "(|,flyer,{Birdie},{Tweety})";
1992 "(|,key,(/,open,_,lock))", ["key", "(/,open,_,{lock1})"] => "(|,key,(/,open,_,{lock1}))";
1993 "(|,key,(/,open,_,lock))", ["key", "{key1}"] => "(|,key,{key1})";
1994 "(|,neutralization,(*,(\\,reaction,_,soda),base))", ["neutralization", "reaction"] => "(|,neutralization,reaction)";
1995 "(|,neutralization,(*,acid,soda))", ["neutralization", "(*,acid,(\\,neutralization,acid,_))"] => "(|,neutralization,(*,acid,(\\,neutralization,acid,_)))";
1996 "(|,neutralization,(*,acid,soda))", ["neutralization", "(*,acid,base)"] => "(|,neutralization,(*,acid,base))";
1997 "(|,neutralization,(*,acid,soda))", ["neutralization", "reaction"] => "(|,neutralization,reaction)";
1998 "(|,robin,[yellow],{Birdie})", ["robin", "(|,flyer,{Tweety})", "{Birdie}"] => "(|,flyer,robin,{Birdie},{Tweety})";
1999 "(|,soda,(\\,neutralization,acid,_))", ["(/,neutralization,acid,_)", "(\\,neutralization,acid,_)"] => "(|,(/,neutralization,acid,_),(\\,neutralization,acid,_))";
2000 "(|,tiger,(&,bird,robin))", ["tiger", "(|,animal,swimmer)"] => "(|,animal,swimmer,tiger)";
2001 "(|,{key1},(/,open,_,lock))", ["(/,open,_,{lock1})", "(/,open,_,lock)"] => "(|,(/,open,_,lock),(/,open,_,{lock1}))";
2002 "(|,{key1},(/,open,_,lock))", ["(|,key,(/,open,_,{lock1}))", "(/,open,_,lock)"] => "(|,key,(/,open,_,lock),(/,open,_,{lock1}))";
2003 "(|,{key1},(/,open,_,lock))", ["key", "(/,open,_,lock)"] => "(|,key,(/,open,_,lock))";
2004 "(~,(/,(*,tim,tom),tom,_),tim)", ["(/,(*,tim,tom),tom,_)", "(/,uncle,tom,_)"] => "(~,(/,(*,tim,tom),tom,_),(/,uncle,tom,_))";
2005 "(~,[strong],girl)", ["(~,boy,girl)", "girl"] => "(~,(~,boy,girl),girl)";
2006 "(~,[strong],girl)", ["boy", "girl"] => "(~,boy,girl)";
2007 "(~,boy,girl)", ["[strong]", "girl"] => "(~,[strong],girl)";
2008 "(~,boy,girl)", ["youth", "girl"] => "(~,youth,girl)";
2009 "(~,youth,girl)", ["(|,boy,girl)", "girl"] => "(~,(|,boy,girl),girl)";
2010 "[bright]", ["smart"] => "[smart]";
2011 "{Birdie}", ["Tweety"] => "{Tweety}";
2012 "{Mars,Pluto,Saturn,Venus}", ["Mars", "Venus"] => "{Mars,Venus}";
2013 }
2014 ok!()
2015 }
2016 }
2017
2018 mod statement {
2019 use super::*;
2020
2021 #[test]
2022 fn make_statement_relation() -> AResult {
2023 fn test(relation: &str, subject: Term, predicate: Term, expected: Option<Term>) {
2024 let out =
2025 Term::make_statement_relation(relation, subject.clone(), predicate.clone());
2026 assert_eq!(
2027 out,
2028 expected,
2029 "\"{relation}\", \"{subject}\", \"{predicate}\" => {} != {}",
2030 format_option_term(&out),
2031 format_option_term(&expected),
2032 );
2033 }
2034 macro_once! {
2035 macro test($($relation:tt, $subject:tt, $predicate:tt => $expected:tt;)*) {
2037 $( test($relation, term!($subject), term!($predicate), option_term!($expected)); )*
2038 }
2039 "-->", "(&,<bird --> fly>,<{Tweety} --> bird>)", "claimedByBob" => "<(&,<bird --> fly>,<{Tweety} --> bird>) --> claimedByBob>";
2041 "-->", "(&,bird,swimmer)", "(&,animal,swimmer)" => "<(&,bird,swimmer) --> (&,animal,swimmer)>";
2042 "-->", "(&,swan,swimmer)", "bird" => "<(&,swan,swimmer) --> bird>";
2043 "-->", "(*,(*,(*,0)))", "num" => "<(*,(*,(*,0))) --> num>";
2044 "-->", "(*,CAT,FISH)", "FOOD" => "<(*,CAT,FISH) --> FOOD>";
2045 "-->", "(*,bird,plant)", "?120" => "<(*,bird,plant) --> ?120>";
2046 "-->", "(-,swimmer,animal)", "(-,swimmer,bird)" => "<(-,swimmer,animal) --> (-,swimmer,bird)>";
2047 "-->", "(/,neutralization,_,base)", "?120" => "<(/,neutralization,_,base) --> ?120>";
2048 "-->", "(|,boy,girl)", "youth" => "<(|,boy,girl) --> youth>";
2049 "-->", "(~,boy,girl)", "[strong]" => "<(~,boy,girl) --> [strong]>";
2050 "-->", "(~,swimmer,swan)", "bird" => "<(~,swimmer,swan) --> bird>";
2051 "-->", "0", "(/,num,_)" => "<0 --> (/,num,_)>";
2052 "-->", "0", "num" => "<0 --> num>";
2053 "-->", "?120", "claimedByBob" => "<?120 --> claimedByBob>";
2054 "-->", "[smart]", "[bright]" => "<[smart] --> [bright]>";
2055 "-->", "acid", "(/,reaction,_,base)" => "<acid --> (/,reaction,_,base)>";
2056 "-->", "cat", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)" => "<cat --> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>";
2057 "-->", "neutralization", "(*,acid,base)" => "<neutralization --> (*,acid,base)>";
2058 "-->", "planetX", "{Mars,Pluto,Venus}" => "<planetX --> {Mars,Pluto,Venus}>";
2059 "-->", "planetX", "{Pluto,Saturn}" => "<planetX --> {Pluto,Saturn}>";
2060 "-->", "robin", "(&,bird,swimmer)" => "<robin --> (&,bird,swimmer)>";
2061 "-->", "robin", "(-,bird,swimmer)" => "<robin --> (-,bird,swimmer)>";
2062 "-->", "robin", "(|,bird,swimmer)" => "<robin --> (|,bird,swimmer)>";
2063 "-->", "robin", "[chirping]" => "<robin --> [chirping]>";
2064 "-->", "{?49}", "swimmer" => "<{?49} --> swimmer>";
2065 "-->", "{Tweety}", "[with_wings]" => "<{Tweety} --> [with_wings]>";
2066 "-->", "{Tweety}", "bird" => "<{Tweety} --> bird>";
2067 "-->", "{Tweety}", "{Birdie}" => "<{Tweety} --> {Birdie}>";
2068 "-->", "{key1}", "(/,open,_,{lock1})" => "<{key1} --> (/,open,_,{lock1})>";
2069 "--]", "raven", "black" => "<raven --> [black]>";
2070 "<->", "Birdie", "Tweety" => "<Birdie <-> Tweety>";
2071 "<->", "[bright]", "[smart]" => "<[bright] <-> [smart]>";
2072 "<->", "{Birdie}", "{Tweety}" => "<{Birdie} <-> {Tweety}>";
2073 "<=>", "<robin --> animal>", "<robin --> bird>" => "<<robin --> animal> <=> <robin --> bird>>";
2074 "<=>", "<robin --> bird>", "<robin --> [flying]>" => "<<robin --> bird> <=> <robin --> [flying]>>";
2075 "==>", "(&&,<robin --> [chirping]>,<robin --> [flying]>)", "<robin --> bird>" => "<(&&,<robin --> [chirping]>,<robin --> [flying]>) ==> <robin --> bird>>";
2076 "==>", "(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [with_wings]>)", "<robin --> bird>" => "<(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> bird>>";
2077 "==>", "(&&,<robin --> [flying]>,<robin --> [with_wings]>)", "<robin --> [living]>" => "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> [living]>>";
2078 "==>", "(&&,<robin --> bird>,<robin --> [flying]>)", "<robin --> [living]>" => "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> [living]>>";
2079 "==>", "(&&,<robin --> bird>,<robin --> [living]>)", "<robin --> animal>" => "<(&&,<robin --> bird>,<robin --> [living]>) ==> <robin --> animal>>";
2080 "==>", "(--,<robin --> [flying]>)", "<robin --> bird>" => "<(--,<robin --> [flying]>) ==> <robin --> bird>>";
2081 "==>", "(--,<robin --> bird>)", "<robin --> [flying]>" => "<(--,<robin --> bird>) ==> <robin --> [flying]>>";
2082 "==>", "<robin --> [flying]>", "<robin --> [with_beak]>" => "<<robin --> [flying]> ==> <robin --> [with_beak]>>";
2083 "==>", "<robin --> [flying]>", "<robin --> animal>" => "<<robin --> [flying]> ==> <robin --> animal>>";
2084 "==>", "<robin --> bird>", "(&&,<robin --> animal>,<robin --> [flying]>)" => "<<robin --> bird> ==> (&&,<robin --> animal>,<robin --> [flying]>)>";
2085 "==>", "<robin --> bird>", "<robin --> [flying]>" => "<<robin --> bird> ==> <robin --> [flying]>>";
2086 "==>", "<robin --> bird>", "<robin --> animal>" => "<<robin --> bird> ==> <robin --> animal>>";
2087 "{--", "Tweety", "bird" => "<{Tweety} --> bird>";
2088 "{-]", "Tweety", "yellow" => "<{Tweety} --> [yellow]>";
2089 }
2090 ok!()
2091 }
2092
2093 #[test]
2094 fn make_statement() -> AResult {
2095 fn test(template: Term, subject: Term, predicate: Term, expected: Option<Term>) {
2096 let out = Term::make_statement(&template, subject.clone(), predicate.clone());
2097 assert_eq!(
2098 out,
2099 expected,
2100 "\"{template}\", \"{subject}\", \"{predicate}\" => {} != {}",
2101 format_option_term(&out),
2102 format_option_term(&expected),
2103 );
2104 }
2105 macro_once! {
2106 macro test($($template:tt, $subject:tt, $predicate:tt => $expected:tt;)*) {
2108 $( test(term!($template), term!($subject), term!($predicate), option_term!($expected)); )*
2109 }
2110 "<(&&,<robin --> [chirping]>,<robin --> [flying]>) ==> <robin --> bird>>", "(&&,<robin --> bird>,<robin --> [flying]>)", "<robin --> bird>" => None;"<(&&,<robin --> [chirping]>,<robin --> [flying]>) ==> <robin --> bird>>", "<robin --> [chirping]>", "<robin --> bird>" => "<<robin --> [chirping]> ==> <robin --> bird>>";
2112 "<(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> bird>>", "(&&,<robin --> [chirping]>,<robin --> [flying]>)", "<robin --> bird>" => "<(&&,<robin --> [chirping]>,<robin --> [flying]>) ==> <robin --> bird>>";
2113 "<(&&,<robin --> [chirping]>,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> bird>>", "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)", "<robin --> bird>" => None;
2114 "<(&&,<robin --> [chirping]>,<robin --> [with_wings]>) ==> <robin --> bird>>", "(&&,<robin --> bird>,<robin --> [chirping]>)", "<robin --> bird>" => None;
2115 "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> [living]>>", "<robin --> [flying]>", "<robin --> [living]>" => "<<robin --> [flying]> ==> <robin --> [living]>>";
2116 "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> [living]>>", "<robin --> [with_wings]>", "<robin --> bird>" => "<<robin --> [with_wings]> ==> <robin --> bird>>";
2117 "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>", "(&&,<robin --> [flying]>,<robin --> [with_wings]>)", "(&&,<robin --> animal>,<robin --> bird>)" => "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> (&&,<robin --> animal>,<robin --> bird>)>";
2118 "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>", "(&&,<robin --> [flying]>,<robin --> [with_wings]>)", "(||,<robin --> animal>,<robin --> bird>)" => "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> (||,<robin --> animal>,<robin --> bird>)>";
2119 "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>", "<robin --> animal>", "<robin --> bird>" => "<<robin --> animal> ==> <robin --> bird>>";
2120 "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> [living]>>", "<robin --> [flying]>", "<robin --> [living]>" => "<<robin --> [flying]> ==> <robin --> [living]>>";
2121 "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> [living]>>", "<robin --> bird>", "<robin --> [living]>" => "<<robin --> bird> ==> <robin --> [living]>>";
2122 "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> animal>>", "<robin --> [flying]>", "<robin --> animal>" => "<<robin --> [flying]> ==> <robin --> animal>>";
2123 "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> animal>>", "<robin --> bird>", "<robin --> animal>" => "<<robin --> bird> ==> <robin --> animal>>";
2124 "<(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>", "(&&,<robin --> [flying]>,<robin --> [with_wings]>)", "<robin --> animal>" => "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>";
2125 "<(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>", "(&&,<robin --> bird>,<robin --> [flying]>)", "<robin --> animal>" => "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> animal>>";
2126 "<(&&,<robin --> bird>,<robin --> [living]>) ==> <robin --> animal>>", "(&&,<robin --> bird>,<robin --> [flying]>)", "<robin --> animal>" => "<(&&,<robin --> bird>,<robin --> [flying]>) ==> <robin --> animal>>";
2127 "<(&&,<robin --> bird>,<robin --> [living]>) ==> <robin --> animal>>", "(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>)", "<robin --> animal>" => "<(&&,<robin --> bird>,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> animal>>";
2128 "<(&&,<robin --> flyer>,<robin --> [chirping]>) ==> <robin --> bird>>", "(&&,<robin --> bird>,<robin --> flyer>)", "<robin --> bird>" => None;
2129 "<(&&,<robin --> flyer>,<robin --> [chirping]>,<(*,robin,worms) --> food>) ==> <robin --> bird>>", "(&&,<robin --> bird>,<robin --> flyer>,<(*,robin,worms) --> food>)", "<robin --> bird>" => None;
2130 "<(&&,<robin --> flyer>,<robin --> [chirping]>,<(*,robin,worms) --> food>) ==> <robin --> bird>>", "(&&,<robin --> flyer>,<(*,robin,worms) --> food>)", "<robin --> bird>" => "<(&&,<robin --> flyer>,<(*,robin,worms) --> food>) ==> <robin --> bird>>";
2131 "<(&&,<robin --> flyer>,<robin --> [chirping]>,<worms --> (/,food,robin,_)>) ==> <robin --> bird>>", "(&&,<robin --> bird>,<robin --> flyer>,<worms --> (/,food,robin,_)>)", "<robin --> bird>" => None;
2132 "<(&,bird,swimmer) --> (&,animal,swimmer)>", "bird", "animal" => "<bird --> animal>";
2133 "<(&,bird,swimmer) --> (&,animal,swimmer)>", "swimmer", "swimmer" => None;
2134 "<(&,chess,sport) --> competition>", "chess", "competition" => "<chess --> competition>";
2135 "<(&,robin,swan) --> (&,bird,swimmer)>", "(&,robin,swan)", "bird" => "<(&,robin,swan) --> bird>";
2136 "<(&,robin,swimmer) --> animal>", "(&,robin,swimmer)", "(&,animal,bird)" => "<(&,robin,swimmer) --> (&,animal,bird)>";
2137 "<(&,robin,swimmer) --> animal>", "(&,robin,swimmer)", "(|,animal,bird)" => "<(&,robin,swimmer) --> (|,animal,bird)>";
2138 "<(&,robin,{Tweety}) --> [with_wings]>", "(&,flyer,robin,{Tweety})", "(&,flyer,[with_wings])" => "<(&,flyer,robin,{Tweety}) --> (&,flyer,[with_wings])>";
2139 "<(&,robin,{Tweety}) --> [with_wings]>", "(&,robin,{Birdie},{Tweety})", "(&,[with_wings],{Birdie})" => "<(&,robin,{Birdie},{Tweety}) --> (&,[with_wings],{Birdie})>";
2140 "<(*,(*,(*,0))) --> num>", "(*,(*,(*,(/,num,_))))", "num" => "<(*,(*,(*,(/,num,_)))) --> num>";
2141 "<(*,(*,(*,0))) --> num>", "num", "(*,(*,(*,(/,num,_))))" => "<num --> (*,(*,(*,(/,num,_))))>";
2142 "<(*,(*,0)) --> (*,(*,(/,num,_)))>", "(*,(*,(*,0)))", "(*,(*,(*,(/,num,_))))" => "<(*,(*,(*,0))) --> (*,(*,(*,(/,num,_))))>";
2143 "<(*,(*,0)) --> (*,(*,(/,num,_)))>", "(*,(*,(/,num,_)))", "(*,(*,num))" => "<(*,(*,(/,num,_))) --> (*,(*,num))>";
2144 "<(*,(*,0)) --> (*,(*,(/,num,_)))>", "(*,(*,0))", "(&,(*,(*,num)),(*,(*,(/,num,_))))" => "<(*,(*,0)) --> (&,(*,(*,num)),(*,(*,(/,num,_))))>";
2145 "<(*,(*,0)) --> (*,(*,(/,num,_)))>", "(*,(*,0))", "(|,(*,(*,num)),(*,(*,(/,num,_))))" => "<(*,(*,0)) --> (|,(*,(*,num)),(*,(*,(/,num,_))))>";
2146 "<(*,(*,0)) --> (*,(*,(/,num,_)))>", "(*,(*,num))", "(*,(*,(/,num,_)))" => "<(*,(*,num)) --> (*,(*,(/,num,_)))>";
2147 "<(*,(*,0)) --> (*,(*,(/,num,_)))>", "(*,0)", "(*,(/,num,_))" => "<(*,0) --> (*,(/,num,_))>";
2148 "<(*,0) --> (*,(/,num,_))>", "(*,(*,0))", "(*,(*,(/,num,_)))" => "<(*,(*,0)) --> (*,(*,(/,num,_)))>";
2149 "<(*,0) --> (*,(/,num,_))>", "(*,(/,num,_))", "(*,num)" => "<(*,(/,num,_)) --> (*,num)>";
2150 "<(*,0) --> (*,(/,num,_))>", "(*,0)", "(&,(*,num),(*,(/,num,_)))" => "<(*,0) --> (&,(*,num),(*,(/,num,_)))>";
2151 "<(*,0) --> (*,(/,num,_))>", "(*,0)", "(|,(*,num),(*,(/,num,_)))" => "<(*,0) --> (|,(*,num),(*,(/,num,_)))>";
2152 "<(*,0) --> (*,(/,num,_))>", "(*,num)", "(*,(/,num,_))" => "<(*,num) --> (*,(/,num,_))>";
2153 "<(*,0) --> (*,(/,num,_))>", "0", "(/,num,_)" => "<0 --> (/,num,_)>";
2154 "<(*,0) --> (*,num)>", "(*,(*,0))", "(*,(*,num))" => "<(*,(*,0)) --> (*,(*,num))>";
2155 "<(*,0) --> (*,num)>", "(*,(/,num,_))", "(*,num)" => "<(*,(/,num,_)) --> (*,num)>";
2156 "<(*,0) --> (*,num)>", "(*,0)", "(&,(*,num),(*,(/,num,_)))" => "<(*,0) --> (&,(*,num),(*,(/,num,_)))>";
2157 "<(*,0) --> (*,num)>", "(*,0)", "(|,(*,num),(*,(/,num,_)))" => "<(*,0) --> (|,(*,num),(*,(/,num,_)))>";
2158 "<(*,0) --> (*,num)>", "(*,num)", "(*,(/,num,_))" => "<(*,num) --> (*,(/,num,_))>";
2159 "<(*,0) --> (*,num)>", "0", "num" => "<0 --> num>";
2160 "<(*,0) --> num>", "(/,(*,0),_)", "(/,num,_)" => "<(/,(*,0),_) --> (/,num,_)>";
2161 "<(*,a,b) --> (&,like,(*,(/,like,b,_),b))>", "(*,a,b)", "(&,like,(*,(/,like,b,_),b))" => "<(*,a,b) --> (&,like,(*,(/,like,b,_),b))>";
2162 "<(*,a,b) --> like>", "(*,(/,like,b,_),b)", "like" => "<(*,(/,like,b,_),b) --> like>";
2163 "<(*,a,b) --> like>", "(*,a,b)", "(&,like,(*,(/,like,b,_),b))" => "<(*,a,b) --> (&,like,(*,(/,like,b,_),b))>";
2164 "<(*,a,b) --> like>", "(*,a,b)", "(|,like,(*,(/,like,b,_),b))" => "<(*,a,b) --> (|,like,(*,(/,like,b,_),b))>";
2165 "<(*,a,b) --> like>", "like", "(*,(/,like,b,_),b)" => "<like --> (*,(/,like,b,_),b)>";
2166 "<(*,acid,base) --> reaction>", "neutralization", "reaction" => "<neutralization --> reaction>";
2167 "<(*,b,a) --> (*,b,(/,like,b,_))>", "a", "(/,like,b,_)" => "<a --> (/,like,b,_)>";
2168 "<(*,b,a) --> (*,b,(/,like,b,_))>", "b", "b" => None;
2169 "<(*,num) <-> (*,(/,num,_))>", "num", "(/,num,_)" => "<num <-> (/,num,_)>";
2170 "<(*,tim,tom) --> uncle>", "(/,(*,tim,tom),_,tom)", "(/,uncle,_,tom)" => "<(/,(*,tim,tom),_,tom) --> (/,uncle,_,tom)>";
2171 "<(-,swimmer,animal) --> (-,swimmer,bird)>", "bird", "animal" => "<bird --> animal>";
2172 "<(-,swimmer,animal) --> (-,swimmer,bird)>", "swimmer", "swimmer" => None;
2173 "<(--,<robin --> [flying]>) ==> <robin --> bird>>", "(--,<robin --> bird>)", "<robin --> [flying]>" => "<(--,<robin --> bird>) ==> <robin --> [flying]>>";
2174 "<(--,<robin --> bird>) ==> <robin --> [flying]>>", "(--,<robin --> [flying]>)", "<robin --> bird>" => "<(--,<robin --> [flying]>) ==> <robin --> bird>>";
2175 "<(/,(*,0),_) --> (/,num,_)>", "(*,(/,(*,0),_))", "(*,(/,num,_))" => "<(*,(/,(*,0),_)) --> (*,(/,num,_))>";
2176 "<(/,(*,tim,tom),_,tom) --> (/,uncle,_,tom)>", "(*,tim,tom)", "uncle" => "<(*,tim,tom) --> uncle>";
2177 "<(/,(*,tim,tom),_,tom) --> (/,uncle,_,tom)>", "tom", "tom" => None;
2178 "<(/,(*,tim,tom),tom,_) --> (/,uncle,tom,_)>", "(&,tim,(/,(*,tim,tom),tom,_))", "(/,uncle,tom,_)" => "<(&,tim,(/,(*,tim,tom),tom,_)) --> (/,uncle,tom,_)>";
2179 "<(/,(*,tim,tom),tom,_) --> (/,uncle,tom,_)>", "(/,(*,tim,tom),tom,_)", "tim" => "<(/,(*,tim,tom),tom,_) --> tim>";
2180 "<(/,(*,tim,tom),tom,_) --> (/,uncle,tom,_)>", "(|,tim,(/,(*,tim,tom),tom,_))", "(/,uncle,tom,_)" => "<(|,tim,(/,(*,tim,tom),tom,_)) --> (/,uncle,tom,_)>";
2181 "<(/,(*,tim,tom),tom,_) --> (/,uncle,tom,_)>", "(~,(/,(*,tim,tom),tom,_),tim)", "(/,uncle,tom,_)" => "<(~,(/,(*,tim,tom),tom,_),tim) --> (/,uncle,tom,_)>";
2182 "<(/,(*,tim,tom),tom,_) --> (/,uncle,tom,_)>", "tim", "(/,(*,tim,tom),tom,_)" => "<tim --> (/,(*,tim,tom),tom,_)>";
2183 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "(&,acid,(/,neutralization,_,base))", "(/,reaction,_,base)" => "<(&,acid,(/,neutralization,_,base)) --> (/,reaction,_,base)>";
2184 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "(/,neutralization,_,base)", "acid" => "<(/,neutralization,_,base) --> acid>";
2185 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "(|,acid,(/,neutralization,_,base))", "(/,reaction,_,base)" => "<(|,acid,(/,neutralization,_,base)) --> (/,reaction,_,base)>";
2186 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "acid", "(/,neutralization,_,base)" => "<acid --> (/,neutralization,_,base)>";
2187 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "base", "base" => None;
2188 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "neutralization", "reaction" => "<neutralization --> reaction>";
2189 "<(/,neutralization,_,base) --> ?1>", "(/,neutralization,_,base)", "(/,reaction,_,base)" => "<(/,neutralization,_,base) --> (/,reaction,_,base)>";
2190 "<(/,neutralization,_,base) --> ?1>", "(/,reaction,_,base)", "?1" => "<(/,reaction,_,base) --> ?1>";
2191 "<(/,neutralization,_,base) --> ?1>", "?1", "(/,reaction,_,base)" => "<?1 --> (/,reaction,_,base)>";
2192 "<(/,neutralization,acid,_) <-> (/,reaction,acid,_)>", "acid", "acid" => None;
2193 "<(/,num,_) --> num>", "(*,(/,num,_))", "(*,num)" => "<(*,(/,num,_)) --> (*,num)>";
2194 "<(/,open,_,lock) --> (&,key,(/,open,_,{lock1}))>", "(/,open,_,lock)", "(/,open,_,{lock1})" => "<(/,open,_,lock) --> (/,open,_,{lock1})>";
2195 "<(/,open,_,lock) --> (&,key,(/,open,_,{lock1}))>", "(/,open,_,lock)", "key" => "<(/,open,_,lock) --> key>";
2196 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "(/,open,_,lock)", "(&,key,(/,open,_,{lock1}))" => "<(/,open,_,lock) --> (&,key,(/,open,_,{lock1}))>";
2197 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "(/,open,_,lock)", "(|,key,(/,open,_,{lock1}))" => "<(/,open,_,lock) --> (|,key,(/,open,_,{lock1}))>";
2198 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "(/,open,_,{lock1})", "key" => "<(/,open,_,{lock1}) --> key>";
2199 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "key", "(/,open,_,{lock1})" => "<key --> (/,open,_,{lock1})>";
2200 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "open", "open" => None;
2201 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "{lock1}", "lock" => "<{lock1} --> lock>";
2202 "<(/,open,_,lock) --> key>", "(/,open,_,lock)", "(&,key,(/,open,_,{lock1}))" => "<(/,open,_,lock) --> (&,key,(/,open,_,{lock1}))>";
2203 "<(/,open,_,lock) --> key>", "(/,open,_,lock)", "(|,key,(/,open,_,{lock1}))" => "<(/,open,_,lock) --> (|,key,(/,open,_,{lock1}))>";
2204 "<(/,open,_,lock) --> key>", "(/,open,_,{lock1})", "key" => "<(/,open,_,{lock1}) --> key>";
2205 "<(/,open,_,lock) --> key>", "key", "(/,open,_,{lock1})" => "<key --> (/,open,_,{lock1})>";
2206 "<(/,reaction,acid,_) --> soda>", "(/,neutralization,acid,_)", "soda" => "<(/,neutralization,acid,_) --> soda>";
2207 "<(/,reaction,acid,_) --> soda>", "(/,reaction,acid,_)", "(&,soda,(/,neutralization,acid,_))" => "<(/,reaction,acid,_) --> (&,soda,(/,neutralization,acid,_))>";
2208 "<(/,reaction,acid,_) --> soda>", "(/,reaction,acid,_)", "(|,soda,(/,neutralization,acid,_))" => "<(/,reaction,acid,_) --> (|,soda,(/,neutralization,acid,_))>";
2209 "<(/,reaction,acid,_) --> soda>", "soda", "(/,neutralization,acid,_)" => "<soda --> (/,neutralization,acid,_)>";
2210 "<(|,acid,(/,neutralization,_,base)) --> (/,reaction,_,base)>", "(/,neutralization,_,base)", "(/,reaction,_,base)" => "<(/,neutralization,_,base) --> (/,reaction,_,base)>";
2211 "<(|,acid,(/,neutralization,_,base)) --> (/,reaction,_,base)>", "acid", "(/,reaction,_,base)" => "<acid --> (/,reaction,_,base)>";
2212 "<(|,bird,robin) --> animal>", "bird", "animal" => "<bird --> animal>";
2213 "<(|,bird,{Tweety}) --> (|,bird,flyer)>", "bird", "bird" => None;
2214 "<(|,bird,{Tweety}) --> (|,bird,flyer)>", "{Tweety}", "flyer" => "<{Tweety} --> flyer>";
2215 "<(|,bird,{Tweety}) --> (|,bird,{Birdie})>", "bird", "bird" => None;
2216 "<(|,bird,{Tweety}) --> (|,bird,{Birdie})>", "{Tweety}", "{Birdie}" => "<{Tweety} --> {Birdie}>";
2217 "<(|,boy,girl) --> (|,girl,youth)>", "(|,boy,girl)", "(|,girl,youth)" => "<(|,boy,girl) --> (|,girl,youth)>";
2218 "<(|,boy,girl) --> (|,girl,youth)>", "boy", "girl" => "<boy --> girl>";
2219 "<(|,boy,girl) --> (~,youth,girl)>", "(~,youth,girl)", "(|,boy,girl)" => "<(~,youth,girl) --> (|,boy,girl)>";
2220 "<(|,boy,girl) --> youth>", "(|,boy,girl)", "(~,youth,girl)" => "<(|,boy,girl) --> (~,youth,girl)>";
2221 "<(|,boy,girl) --> youth>", "(|,boy,girl)", "youth" => "<(|,boy,girl) --> youth>";
2222 "<(|,boy,girl) --> youth>", "(~,(|,boy,girl),girl)", "(~,youth,girl)" => "<(~,(|,boy,girl),girl) --> (~,youth,girl)>";
2223 "<(|,boy,girl) --> youth>", "youth", "(|,boy,girl)" => "<youth --> (|,boy,girl)>";
2224 "<(|,chess,sport) --> (|,chess,competition)>", "chess", "chess" => None;
2225 "<(|,chess,sport) --> competition>", "(|,chess,sport)", "(|,chess,competition)" => "<(|,chess,sport) --> (|,chess,competition)>";
2226 "<(|,robin,swan) --> (&,bird,swimmer)>", "(|,robin,swan)", "bird" => "<(|,robin,swan) --> bird>";
2227 "<(|,robin,swan) --> (|,bird,swimmer)>", "robin", "(|,bird,swimmer)" => "<robin --> (|,bird,swimmer)>";
2228 "<(|,robin,swimmer) --> bird>", "(|,robin,swimmer)", "(&,animal,bird)" => "<(|,robin,swimmer) --> (&,animal,bird)>";
2229 "<(|,robin,{Tweety}) --> [with_wings]>", "robin", "[with_wings]" => "<robin --> [with_wings]>";
2230 "<(|,robin,{Tweety}) --> [with_wings]>", "{Tweety}", "[with_wings]" => "<{Tweety} --> [with_wings]>";
2231 "<(~,boy,girl) --> (&,[strong],(~,youth,girl))>", "(~,boy,girl)", "(&,[strong],(~,youth,girl))" => "<(~,boy,girl) --> (&,[strong],(~,youth,girl))>";
2232 "<(~,boy,girl) --> (~,youth,girl)>", "boy", "(~,youth,girl)" => "<boy --> (~,youth,girl)>";
2233 "<(~,boy,girl) --> (~,youth,girl)>", "boy", "youth" => "<boy --> youth>";
2234 "<(~,boy,girl) --> (~,youth,girl)>", "girl", "(~,youth,girl)" => None;
2235 "<(~,boy,girl) --> (~,youth,girl)>", "girl", "girl" => None;
2236 "<(~,boy,girl) --> [strong]>", "(~,boy,girl)", "(&,[strong],(~,youth,girl))" => "<(~,boy,girl) --> (&,[strong],(~,youth,girl))>";
2237 "<(~,boy,girl) --> [strong]>", "(~,boy,girl)", "(|,[strong],(~,youth,girl))" => "<(~,boy,girl) --> (|,[strong],(~,youth,girl))>";
2238 "<(~,boy,girl) --> [strong]>", "(~,boy,girl)", "[strong]" => "<(~,boy,girl) --> [strong]>";
2239 "<(~,boy,girl) --> [strong]>", "[strong]", "(~,youth,girl)" => "<[strong] --> (~,youth,girl)>";
2240 "<(~,boy,girl) --> [strong]>", "boy", "[strong]" => "<boy --> [strong]>";
2241 "<0 --> (/,num,_)>", "(*,0)", "(*,(/,num,_))" => "<(*,0) --> (*,(/,num,_))>";
2242 "<0 --> (/,num,_)>", "(/,num,_)", "num" => "<(/,num,_) --> num>";
2243 "<0 --> (/,num,_)>", "0", "num" => "<0 --> num>";
2244 "<0 --> (/,num,_)>", "num", "(/,num,_)" => "<num --> (/,num,_)>";
2245 "<0 --> num>", "(*,0)", "(*,num)" => "<(*,0) --> (*,num)>";
2246 "<0 --> num>", "(/,num,_)", "num" => "<(/,num,_) --> num>";
2247 "<0 --> num>", "num", "(/,num,_)" => "<num --> (/,num,_)>";
2248 "<<robin --> [with_wings]> ==> <robin --> [living]>>", "<robin --> flyer>", "<robin --> [living]>" => "<<robin --> flyer> ==> <robin --> [living]>>";
2249 "<<robin --> [with_wings]> ==> <robin --> bird>>", "<robin --> [with_wings]>", "(&&,<robin --> bird>,<robin --> [living]>)" => "<<robin --> [with_wings]> ==> (&&,<robin --> bird>,<robin --> [living]>)>";
2250 "<<robin --> [with_wings]> ==> <robin --> bird>>", "<robin --> [with_wings]>", "(||,<robin --> bird>,<robin --> [living]>)" => "<<robin --> [with_wings]> ==> (||,<robin --> bird>,<robin --> [living]>)>";
2251 "<<robin --> [with_wings]> ==> <robin --> bird>>", "<robin --> flyer>", "<robin --> bird>" => "<<robin --> flyer> ==> <robin --> bird>>";
2252 "<?1 --> claimedByBob>", "(&,<bird --> fly>,<{Tweety} --> bird>)", "?1" => "<(&,<bird --> fly>,<{Tweety} --> bird>) --> ?1>";
2253 "<?1 --> claimedByBob>", "?1", "(&,<bird --> fly>,<{Tweety} --> bird>)" => "<?1 --> (&,<bird --> fly>,<{Tweety} --> bird>)>";
2254 "<?1 --> swimmer>", "?1", "animal" => "<?1 --> animal>";
2255 "<?1 --> swimmer>", "animal", "?1" => "<animal --> ?1>";
2256 "<?1 --> swimmer>", "animal", "swimmer" => "<animal --> swimmer>";
2257 "<Birdie <-> Tweety>", "Birdie", "Tweety" => "<Birdie <-> Tweety>";
2258 "<Birdie <-> Tweety>", "{Birdie}", "{Tweety}" => "<{Birdie} <-> {Tweety}>";
2259 "<CAT --> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>", "CAT", "(|,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))" => None;
2260 "<[bright] --> [smart]>", "[smart]", "[bright]" => "<[smart] --> [bright]>";
2261 "<[bright] <-> [smart]>", "bright", "smart" => "<bright <-> smart>";
2262 "<[with_wings] --> {Birdie}>", "[with_wings]", "{Tweety}" => "<[with_wings] --> {Tweety}>";
2263 "<[yellow] --> {Birdie}>", "(|,flyer,[yellow])", "(|,flyer,{Birdie})" => "<(|,flyer,[yellow]) --> (|,flyer,{Birdie})>";
2264 "<[yellow] <-> {Birdie}>", "(|,flyer,[yellow])", "(|,flyer,{Birdie})" => "<(|,flyer,[yellow]) <-> (|,flyer,{Birdie})>";
2265 "<[yellow] <-> {Birdie}>", "[yellow]", "{Tweety}" => "<[yellow] <-> {Tweety}>";
2266 "<a --> (/,like,b,_)>", "(*,a,b)", "(*,(/,like,b,_),b)" => "<(*,a,b) --> (*,(/,like,b,_),b)>";
2267 "<a --> (/,like,b,_)>", "(*,b,a)", "(*,b,(/,like,b,_))" => "<(*,b,a) --> (*,b,(/,like,b,_))>";
2268 "<a --> (/,like,b,_)>", "(/,like,_,(/,like,b,_))", "(/,like,_,a)" => "<(/,like,_,(/,like,b,_)) --> (/,like,_,a)>";
2269 "<acid --> (/,reaction,_,base)>", "(&,acid,(/,neutralization,_,base))", "(/,reaction,_,base)" => "<(&,acid,(/,neutralization,_,base)) --> (/,reaction,_,base)>";
2270 "<acid --> (/,reaction,_,base)>", "(/,neutralization,_,base)", "acid" => "<(/,neutralization,_,base) --> acid>";
2271 "<acid --> (/,reaction,_,base)>", "(|,acid,(/,neutralization,_,base))", "(/,reaction,_,base)" => "<(|,acid,(/,neutralization,_,base)) --> (/,reaction,_,base)>";
2272 "<acid --> (/,reaction,_,base)>", "acid", "(/,neutralization,_,base)" => "<acid --> (/,neutralization,_,base)>";
2273 "<b --> (/,like,_,a)>", "(/,like,(/,like,_,a),_)", "(/,like,b,_)" => "<(/,like,(/,like,_,a),_) --> (/,like,b,_)>";
2274 "<bird --> (&,animal,swimmer)>", "bird", "animal" => "<bird --> animal>";
2275 "<bird --> animal>", "(&,bird,robin)", "animal" => "<(&,bird,robin) --> animal>";
2276 "<bird --> animal>", "(|,bird,robin)", "animal" => "<(|,bird,robin) --> animal>";
2277 "<bird --> animal>", "bird", "robin" => "<bird --> robin>";
2278 "<bird --> swimmer>", "bird", "(&,animal,swimmer)" => "<bird --> (&,animal,swimmer)>";
2279 "<bird --> swimmer>", "bird", "(|,animal,swimmer)" => "<bird --> (|,animal,swimmer)>";
2280 "<bird --> {Birdie}>", "bird", "(|,bird,{Birdie})" => None;
2281 "<boy --> [strong]>", "(~,boy,girl)", "(~,[strong],girl)" => "<(~,boy,girl) --> (~,[strong],girl)>";
2282 "<boy --> youth>", "(|,boy,girl)", "(|,girl,youth)" => "<(|,boy,girl) --> (|,girl,youth)>";
2283 "<boy --> youth>", "(~,boy,girl)", "(~,youth,girl)" => "<(~,boy,girl) --> (~,youth,girl)>";
2284 "<bright <-> smart>", "[bright]", "[smart]" => "<[bright] <-> [smart]>";
2285 "<cat --> (&,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))>", "cat", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)" => "<cat --> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>";
2286 "<cat --> (&,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))>", "cat", "CAT" => "<cat --> CAT>";
2287 "<cat --> CAT>", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)", "CAT" => "<(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish) --> CAT>";
2288 "<cat --> CAT>", "CAT", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)" => "<CAT --> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>";
2289 "<cat --> CAT>", "cat", "(&,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))" => "<cat --> (&,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))>";
2290 "<cat --> CAT>", "cat", "(|,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))" => "<cat --> (|,CAT,(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish))>";
2291 "<chess --> competition>", "(~,sport,chess)", "competition" => "<(~,sport,chess) --> competition>";
2292 "<chess --> competition>", "chess", "(|,chess,competition)" => None;
2293 "<flyer <-> [with_wings]>", "(|,flyer,{Birdie})", "(|,[with_wings],{Birdie})" => "<(|,flyer,{Birdie}) <-> (|,[with_wings],{Birdie})>";
2294 "<neutralization --> (*,acid,base)>", "neutralization", "reaction" => "<neutralization --> reaction>";
2295 "<neutralization --> reaction>", "(/,neutralization,_,base)", "(/,reaction,_,base)" => "<(/,neutralization,_,base) --> (/,reaction,_,base)>";
2296 "<neutralization <-> reaction>", "(/,neutralization,_,base)", "(/,reaction,_,base)" => "<(/,neutralization,_,base) <-> (/,reaction,_,base)>";
2297 "<num <-> (/,num,_)>", "(*,num)", "(*,(/,num,_))" => "<(*,num) <-> (*,(/,num,_))>";
2298 "<num <-> (/,num,_)>", "(/,num,_)", "(/,(/,num,_),_)" => "<(/,num,_) <-> (/,(/,num,_),_)>";
2299 "<planetX --> {Mars,Pluto,Saturn,Venus}>", "{Mars,Pluto,Saturn,Venus}", "{Mars,Pluto,Venus}" => "<{Mars,Pluto,Saturn,Venus} --> {Mars,Pluto,Venus}>";
2300 "<planetX --> {Mars,Pluto,Saturn,Venus}>", "{Mars,Pluto,Venus}", "{Mars,Pluto,Saturn,Venus}" => "<{Mars,Pluto,Venus} --> {Mars,Pluto,Saturn,Venus}>";
2301 "<planetX --> {Mars,Pluto,Venus}>", "planetX", "{Mars,Pluto,Saturn,Venus}" => "<planetX --> {Mars,Pluto,Saturn,Venus}>";
2302 "<planetX --> {Mars,Pluto,Venus}>", "planetX", "{Mars,Venus}" => "<planetX --> {Mars,Venus}>";
2303 "<planetX --> {Mars,Pluto,Venus}>", "planetX", "{Pluto}" => "<planetX --> {Pluto}>";
2304 "<planetX --> {Mars,Pluto,Venus}>", "{Mars,Pluto,Venus}", "{Pluto,Saturn}" => "<{Mars,Pluto,Venus} --> {Pluto,Saturn}>";
2305 "<planetX --> {Mars,Pluto,Venus}>", "{Pluto,Saturn}", "{Mars,Pluto,Venus}" => "<{Pluto,Saturn} --> {Mars,Pluto,Venus}>";
2306 "<planetX --> {Mars,Venus}>", "planetX", "{Mars,Pluto,Saturn,Venus}" => "<planetX --> {Mars,Pluto,Saturn,Venus}>";
2307 "<planetX --> {Mars,Venus}>", "{Mars,Venus}", "{Pluto,Saturn}" => "<{Mars,Venus} --> {Pluto,Saturn}>";
2308 "<planetX --> {Pluto,Saturn}>", "planetX", "{Mars,Venus}" => "<planetX --> {Mars,Venus}>";
2309 "<planetX --> {Pluto,Saturn}>", "planetX", "{Pluto}" => "<planetX --> {Pluto}>";
2310 "<planetX --> {Pluto,Saturn}>", "{Mars,Pluto,Saturn,Venus}", "{Pluto,Saturn}" => "<{Mars,Pluto,Saturn,Venus} --> {Pluto,Saturn}>";
2311 "<planetX --> {Pluto,Saturn}>", "{Mars,Pluto,Venus}", "{Pluto,Saturn}" => "<{Mars,Pluto,Venus} --> {Pluto,Saturn}>";
2312 "<planetX --> {Pluto,Saturn}>", "{Pluto,Saturn}", "{Mars,Pluto,Saturn,Venus}" => "<{Pluto,Saturn} --> {Mars,Pluto,Saturn,Venus}>";
2313 "<planetX --> {Pluto,Saturn}>", "{Pluto,Saturn}", "{Mars,Pluto,Venus}" => "<{Pluto,Saturn} --> {Mars,Pluto,Venus}>";
2314 "<robin --> (-,bird,swimmer)>", "robin", "bird" => "<robin --> bird>";
2315 "<robin --> (|,bird,swimmer)>", "(&,robin,swan)", "(|,bird,swimmer)" => "<(&,robin,swan) --> (|,bird,swimmer)>";
2316 "<robin --> (|,bird,swimmer)>", "(|,robin,swan)", "(|,bird,swimmer)" => "<(|,robin,swan) --> (|,bird,swimmer)>";
2317 "<robin --> (|,bird,swimmer)>", "robin", "swan" => "<robin --> swan>";
2318 "<robin --> [with_wings]>", "(&,flyer,robin)", "(&,flyer,[with_wings])" => "<(&,flyer,robin) --> (&,flyer,[with_wings])>";
2319 "<robin --> [with_wings]>", "(&,robin,{Birdie})", "[with_wings]" => "<(&,robin,{Birdie}) --> [with_wings]>";
2320 "<robin --> [with_wings]>", "(|,flyer,robin)", "(|,flyer,[with_wings])" => "<(|,flyer,robin) --> (|,flyer,[with_wings])>";
2321 "<robin --> [with_wings]>", "(|,robin,{Birdie})", "(|,[with_wings],{Birdie})" => "<(|,robin,{Birdie}) --> (|,[with_wings],{Birdie})>";
2322 "<robin --> [with_wings]>", "(|,robin,{Birdie})", "[with_wings]" => "<(|,robin,{Birdie}) --> [with_wings]>";
2323 "<robin --> [with_wings]>", "robin", "(|,[with_wings],{Birdie})" => "<robin --> (|,[with_wings],{Birdie})>";
2324 "<robin --> [with_wings]>", "robin", "(|,flyer,[with_wings])" => "<robin --> (|,flyer,[with_wings])>";
2325 "<robin --> [with_wings]>", "robin", "flyer" => "<robin --> flyer>";
2326 "<robin --> [with_wings]>", "robin", "{Birdie}" => "<robin --> {Birdie}>";
2327 "<robin --> [with_wings]>", "{Birdie}", "robin" => "<{Birdie} --> robin>";
2328 "<soda --> base>", "(/,reaction,acid,_)", "soda" => "<(/,reaction,acid,_) --> soda>";
2329 "<soda --> base>", "soda", "(/,reaction,acid,_)" => "<soda --> (/,reaction,acid,_)>";
2330 "<swan --> (&,bird,swimmer)>", "(&,robin,swan)", "(&,bird,swimmer)" => "<(&,robin,swan) --> (&,bird,swimmer)>";
2331 "<swan --> (&,bird,swimmer)>", "(|,robin,swan)", "(&,bird,swimmer)" => "<(|,robin,swan) --> (&,bird,swimmer)>";
2332 "<swan --> swimmer>", "(&,swan,swimmer)", "swimmer" => None;
2333 "<swan --> swimmer>", "(~,swimmer,swan)", "swimmer" => None;
2334 "<tiger --> animal>", "(&,robin,tiger)", "(&,animal,robin)" => "<(&,robin,tiger) --> (&,animal,robin)>";
2335 "<tim --> (/,uncle,_,tom)>", "(/,uncle,_,tom)", "(/,uncle,tom,_)" => "<(/,uncle,_,tom) --> (/,uncle,tom,_)>";
2336 "<tim --> (/,uncle,tom,_)>", "(&,tim,(/,(*,tim,tom),tom,_))", "(/,uncle,tom,_)" => "<(&,tim,(/,(*,tim,tom),tom,_)) --> (/,uncle,tom,_)>";
2337 "<tim --> (/,uncle,tom,_)>", "(/,(*,tim,tom),tom,_)", "tim" => "<(/,(*,tim,tom),tom,_) --> tim>";
2338 "<tim --> (/,uncle,tom,_)>", "(|,tim,(/,(*,tim,tom),tom,_))", "(/,uncle,tom,_)" => "<(|,tim,(/,(*,tim,tom),tom,_)) --> (/,uncle,tom,_)>";
2339 "<tim --> (/,uncle,tom,_)>", "(~,(/,(*,tim,tom),tom,_),tim)", "(/,uncle,tom,_)" => "<(~,(/,(*,tim,tom),tom,_),tim) --> (/,uncle,tom,_)>";
2340 "<tim --> (/,uncle,tom,_)>", "tim", "(/,(*,tim,tom),tom,_)" => "<tim --> (/,(*,tim,tom),tom,_)>";
2341 "<{?1} --> swimmer>", "robin", "{?1}" => "<robin --> {?1}>";
2342 "<{?1} --> swimmer>", "{?1}", "bird" => "<{?1} --> bird>";
2343 "<{Birdie} --> [with_wings]>", "{Tweety}", "[with_wings]" => "<{Tweety} --> [with_wings]>";
2344 "<{Birdie} --> [yellow]>", "(&,flyer,{Birdie})", "(&,flyer,[yellow])" => "<(&,flyer,{Birdie}) --> (&,flyer,[yellow])>";
2345 "<{Birdie} --> [yellow]>", "(|,flyer,{Birdie})", "(|,flyer,[yellow])" => "<(|,flyer,{Birdie}) --> (|,flyer,[yellow])>";
2346 "<{Birdie} --> [yellow]>", "{Birdie}", "(|,[yellow],{Birdie})" => None;
2347 "<{Birdie} --> [yellow]>", "{Birdie}", "(|,flyer,[yellow])" => "<{Birdie} --> (|,flyer,[yellow])>";
2348 "<{Birdie} --> flyer>", "(&,flyer,{Birdie})", "flyer" => None;
2349 "<{Birdie} --> flyer>", "{Tweety}", "flyer" => "<{Tweety} --> flyer>";
2350 "<{Birdie} <-> {Tweety}>", "Birdie", "Tweety" => "<Birdie <-> Tweety>";
2351 "<{Birdie} <-> {Tweety}>", "{Birdie}", "{Tweety}" => "<{Birdie} <-> {Tweety}>";
2352 "<{Birdie} <-> {Tweety}>", "{Tweety}", "bird" => "<bird <-> {Tweety}>";
2353 "<{Mars,Pluto,Saturn,Venus} --> {Mars,Pluto,Venus}>", "{Pluto}", "{Mars,Pluto,Venus}" => "<{Pluto} --> {Mars,Pluto,Venus}>";
2354 "<{Tweety} --> (&,[with_wings],{Birdie})>", "{Tweety}", "[with_wings]" => "<{Tweety} --> [with_wings]>";
2355 "<{Tweety} --> (&,[with_wings],{Birdie})>", "{Tweety}", "{Birdie}" => "<{Tweety} --> {Birdie}>";
2356 "<{Tweety} --> (&,bird,flyer)>", "{Tweety}", "bird" => "<{Tweety} --> bird>";
2357 "<{Tweety} --> (&,bird,{Birdie})>", "{Tweety}", "bird" => "<{Tweety} --> bird>";
2358 "<{Tweety} --> (&,bird,{Birdie})>", "{Tweety}", "{Birdie}" => "<{Tweety} --> {Birdie}>";
2359 "<{Tweety} --> (&,flyer,(|,[yellow],{Birdie}))>", "{Tweety}", "(|,[yellow],{Birdie})" => "<{Tweety} --> (|,[yellow],{Birdie})>";
2360 "<{Tweety} --> (&,flyer,(|,[yellow],{Birdie}))>", "{Tweety}", "flyer" => "<{Tweety} --> flyer>";
2361 "<{Tweety} --> (&,flyer,[with_wings])>", "{Tweety}", "[with_wings]" => "<{Tweety} --> [with_wings]>";
2362 "<{Tweety} --> (&,flyer,[with_wings])>", "{Tweety}", "flyer" => "<{Tweety} --> flyer>";
2363 "<{Tweety} --> (|,[with_wings],{Birdie})>", "(&,flyer,[yellow])", "(|,[with_wings],{Birdie})" => "<(&,flyer,[yellow]) --> (|,[with_wings],{Birdie})>";
2364 "<{Tweety} --> (|,[with_wings],{Birdie})>", "(|,[with_wings],{Birdie})", "(&,flyer,[yellow])" => "<(|,[with_wings],{Birdie}) --> (&,flyer,[yellow])>";
2365 "<{Tweety} --> (|,[with_wings],{Birdie})>", "{Tweety}", "(&,flyer,[yellow],(|,[with_wings],{Birdie}))" => "<{Tweety} --> (&,flyer,[yellow],(|,[with_wings],{Birdie}))>";
2366 "<{Tweety} --> (|,[with_wings],{Birdie})>", "{Tweety}", "(|,[with_wings],{Birdie},(&,flyer,[yellow]))" => "<{Tweety} --> (|,[with_wings],{Birdie},(&,flyer,[yellow]))>";
2367 "<{Tweety} --> (|,bird,flyer)>", "(|,bird,flyer)", "(|,bird,{Birdie})" => "<(|,bird,flyer) --> (|,bird,{Birdie})>";
2368 "<{Tweety} --> (|,bird,flyer)>", "(|,bird,{Birdie})", "(|,bird,flyer)" => "<(|,bird,{Birdie}) --> (|,bird,flyer)>";
2369 "<{Tweety} --> (|,bird,flyer)>", "{Tweety}", "(&,(|,bird,flyer),(|,bird,{Birdie}))" => "<{Tweety} --> (&,(|,bird,flyer),(|,bird,{Birdie}))>";
2370 "<{Tweety} --> (|,bird,flyer)>", "{Tweety}", "(|,bird,flyer,{Birdie})" => "<{Tweety} --> (|,bird,flyer,{Birdie})>";
2371 "<{Tweety} --> (|,flyer,[yellow])>", "bird", "(|,flyer,[yellow])" => "<bird --> (|,flyer,[yellow])>";
2372 "<{Tweety} --> [with_wings]>", "(&,flyer,{Birdie})", "[with_wings]" => "<(&,flyer,{Birdie}) --> [with_wings]>";
2373 "<{Tweety} --> [with_wings]>", "(|,flyer,{Birdie})", "[with_wings]" => "<(|,flyer,{Birdie}) --> [with_wings]>";
2374 "<{Tweety} --> [with_wings]>", "[with_wings]", "(&,flyer,{Birdie})" => "<[with_wings] --> (&,flyer,{Birdie})>";
2375 "<{Tweety} --> [with_wings]>", "[with_wings]", "(|,flyer,{Birdie})" => "<[with_wings] --> (|,flyer,{Birdie})>";
2376 "<{Tweety} --> [with_wings]>", "[with_wings]", "flyer" => "<[with_wings] --> flyer>";
2377 "<{Tweety} --> [with_wings]>", "flyer", "[with_wings]" => "<flyer --> [with_wings]>";
2378 "<{Tweety} --> [with_wings]>", "robin", "{Tweety}" => "<robin --> {Tweety}>";
2379 "<{Tweety} --> [with_wings]>", "{Birdie,Tweety}", "(|,[with_wings],{Birdie})" => "<{Birdie,Tweety} --> (|,[with_wings],{Birdie})>";
2380 "<{Tweety} --> [with_wings]>", "{Tweety}", "(&,[with_wings],(|,flyer,{Birdie}))" => "<{Tweety} --> (&,[with_wings],(|,flyer,{Birdie}))>";
2381 "<{Tweety} --> [with_wings]>", "{Tweety}", "(&,flyer,[with_wings])" => "<{Tweety} --> (&,flyer,[with_wings])>";
2382 "<{Tweety} --> [with_wings]>", "{Tweety}", "(&,flyer,[with_wings],{Birdie})" => "<{Tweety} --> (&,flyer,[with_wings],{Birdie})>";
2383 "<{Tweety} --> [with_wings]>", "{Tweety}", "(|,[with_wings],(&,flyer,{Birdie}))" => "<{Tweety} --> (|,[with_wings],(&,flyer,{Birdie}))>";
2384 "<{Tweety} --> [with_wings]>", "{Tweety}", "(|,[with_wings],{Birdie})" => "<{Tweety} --> (|,[with_wings],{Birdie})>";
2385 "<{Tweety} --> [with_wings]>", "{Tweety}", "(|,flyer,[with_wings],{Birdie})" => "<{Tweety} --> (|,flyer,[with_wings],{Birdie})>";
2386 "<{Tweety} --> [with_wings]>", "{Tweety}", "robin" => "<{Tweety} --> robin>";
2387 "<{Tweety} --> bird>", "bird", "flyer" => "<bird --> flyer>";
2388 "<{Tweety} --> bird>", "bird", "{Birdie}" => "<bird --> {Birdie}>";
2389 "<{Tweety} --> bird>", "{Tweety}", "(&,bird,flyer)" => "<{Tweety} --> (&,bird,flyer)>";
2390 "<{Tweety} --> bird>", "{Tweety}", "(&,bird,{Birdie})" => "<{Tweety} --> (&,bird,{Birdie})>";
2391 "<{Tweety} --> bird>", "{Tweety}", "(|,bird,flyer)" => "<{Tweety} --> (|,bird,flyer)>";
2392 "<{Tweety} --> bird>", "{Tweety}", "(|,bird,{Birdie})" => "<{Tweety} --> (|,bird,{Birdie})>";
2393 "<{Tweety} --> flyer>", "(&,[with_wings],{Birdie})", "flyer" => "<(&,[with_wings],{Birdie}) --> flyer>";
2394 "<{Tweety} --> flyer>", "(|,[with_wings],{Birdie})", "flyer" => "<(|,[with_wings],{Birdie}) --> flyer>";
2395 "<{Tweety} --> flyer>", "[with_wings]", "flyer" => "<[with_wings] --> flyer>";
2396 "<{Tweety} --> flyer>", "flyer", "(&,[with_wings],{Birdie})" => "<flyer --> (&,[with_wings],{Birdie})>";
2397 "<{Tweety} --> flyer>", "flyer", "(|,[with_wings],{Birdie})" => "<flyer --> (|,[with_wings],{Birdie})>";
2398 "<{Tweety} --> flyer>", "flyer", "[with_wings]" => "<flyer --> [with_wings]>";
2399 "<{Tweety} --> flyer>", "{Tweety}", "(&,flyer,(|,[with_wings],{Birdie}))" => "<{Tweety} --> (&,flyer,(|,[with_wings],{Birdie}))>";
2400 "<{Tweety} --> flyer>", "{Tweety}", "(&,flyer,[with_wings])" => "<{Tweety} --> (&,flyer,[with_wings])>";
2401 "<{Tweety} --> flyer>", "{Tweety}", "(&,flyer,[with_wings],{Birdie})" => "<{Tweety} --> (&,flyer,[with_wings],{Birdie})>";
2402 "<{Tweety} --> flyer>", "{Tweety}", "(|,flyer,(&,[with_wings],{Birdie}))" => "<{Tweety} --> (|,flyer,(&,[with_wings],{Birdie}))>";
2403 "<{Tweety} --> flyer>", "{Tweety}", "(|,flyer,[with_wings])" => "<{Tweety} --> (|,flyer,[with_wings])>";
2404 "<{Tweety} --> flyer>", "{Tweety}", "(|,flyer,[with_wings],{Birdie})" => "<{Tweety} --> (|,flyer,[with_wings],{Birdie})>";
2405 "<{Tweety} --> {Birdie}>", "(|,bird,{Tweety})", "(|,bird,{Birdie})" => "<(|,bird,{Tweety}) --> (|,bird,{Birdie})>";
2406 "<{Tweety} --> {Birdie}>", "[with_wings]", "{Birdie}" => "<[with_wings] --> {Birdie}>";
2407 "<{Tweety} --> {Birdie}>", "bird", "{Birdie}" => "<bird --> {Birdie}>";
2408 "<{Tweety} --> {Birdie}>", "{Birdie}", "[with_wings]" => "<{Birdie} --> [with_wings]>";
2409 "<{Tweety} --> {Birdie}>", "{Birdie}", "bird" => "<{Birdie} --> bird>";
2410 "<{Tweety} --> {Birdie}>", "{Tweety}", "(&,[with_wings],{Birdie})" => "<{Tweety} --> (&,[with_wings],{Birdie})>";
2411 "<{Tweety} --> {Birdie}>", "{Tweety}", "(&,bird,{Birdie})" => "<{Tweety} --> (&,bird,{Birdie})>";
2412 "<{Tweety} --> {Birdie}>", "{Tweety}", "(|,[with_wings],{Birdie})" => "<{Tweety} --> (|,[with_wings],{Birdie})>";
2413 "<{Tweety} --> {Birdie}>", "{Tweety}", "(|,bird,{Birdie})" => "<{Tweety} --> (|,bird,{Birdie})>";
2414 "<{key1} --> (&,key,(/,open,_,{lock1}))>", "{key1}", "(/,open,_,{lock1})" => "<{key1} --> (/,open,_,{lock1})>";
2415 "<{key1} --> (&,key,(/,open,_,{lock1}))>", "{key1}", "key" => "<{key1} --> key>";
2416 "<{key1} --> (/,open,_,{lock1})>", "(/,open,_,{lock1})", "key" => "<(/,open,_,{lock1}) --> key>";
2417 "<{key1} --> (/,open,_,{lock1})>", "key", "(/,open,_,{lock1})" => "<key --> (/,open,_,{lock1})>";
2418 "<{key1} --> (/,open,_,{lock1})>", "{key1}", "(&,key,(/,open,_,{lock1}))" => "<{key1} --> (&,key,(/,open,_,{lock1}))>";
2419 "<{key1} --> (/,open,_,{lock1})>", "{key1}", "(|,key,(/,open,_,{lock1}))" => "<{key1} --> (|,key,(/,open,_,{lock1}))>";
2420 "<{key1} --> (|,key,(/,open,_,{lock1}))>", "{key1}", "(/,open,_,{lock1})" => "<{key1} --> (/,open,_,{lock1})>";
2421 "<{key1} --> (|,key,(/,open,_,{lock1}))>", "{key1}", "(|,key,(/,open,_,{lock1}))" => "<{key1} --> (|,key,(/,open,_,{lock1}))>";
2422 "<{key1} --> key>", "(/,open,_,{lock1})", "key" => "<(/,open,_,{lock1}) --> key>";
2423 "<{key1} --> key>", "key", "(/,open,_,{lock1})" => "<key --> (/,open,_,{lock1})>";
2424 "<{key1} --> key>", "{key1}", "(&,key,(/,open,_,{lock1}))" => "<{key1} --> (&,key,(/,open,_,{lock1}))>";
2425 "<{key1} --> key>", "{key1}", "(/,open,_,{lock1})" => "<{key1} --> (/,open,_,{lock1})>";
2426 "<{key1} --> key>", "{key1}", "(|,key,(/,open,_,{lock1}))" => "<{key1} --> (|,key,(/,open,_,{lock1}))>";
2427 "<{lock1} --> (&,lock,(/,open,{key1},_))>", "{lock1}", "lock" => "<{lock1} --> lock>";
2428 "<{lock1} --> (|,lock,(/,open,{key1},_))>", "(/,open,_,(|,lock,(/,open,{key1},_)))", "(/,open,_,{lock1})" => "<(/,open,_,(|,lock,(/,open,{key1},_))) --> (/,open,_,{lock1})>";
2429 "<{lock1} --> lock>", "(/,open,_,lock)", "(/,open,_,{lock1})" => "<(/,open,_,lock) --> (/,open,_,{lock1})>";
2430 "<{lock1} --> lock>", "(/,open,{key1},_)", "lock" => "<(/,open,{key1},_) --> lock>";
2431 "<{lock1} --> lock>", "lock", "(/,open,{key1},_)" => "<lock --> (/,open,{key1},_)>";
2432 "<{lock1} --> lock>", "{lock1}", "(&,lock,(/,open,{key1},_))" => "<{lock1} --> (&,lock,(/,open,{key1},_))>";
2433 "<{lock1} --> lock>", "{lock1}", "(|,lock,(/,open,{key1},_))" => "<{lock1} --> (|,lock,(/,open,{key1},_))>";
2434 }
2435 ok!()
2436 }
2437
2438 #[test]
2439 fn make_statement_symmetric() -> AResult {
2440 fn test(template: Term, subject: Term, predicate: Term, expected: Option<Term>) {
2441 let out =
2442 Term::make_statement_symmetric(&template, subject.clone(), predicate.clone());
2443 assert_eq!(
2444 out,
2445 expected,
2446 "\"{template}\", \"{subject}\", \"{predicate}\" => {} != {}",
2447 format_option_term(&out),
2448 format_option_term(&expected),
2449 );
2450 }
2451 macro_once! {
2452 macro test($($template:tt, $subject:tt, $predicate:tt => $expected:tt;)*) {
2454 $( test(term!($template), term!($subject), term!($predicate), option_term!($expected)); )*
2455 }
2456 "<(&&,<robin --> [flying]>,<robin --> [with_wings]>) ==> <robin --> bird>>", "<robin --> [living]>", "<robin --> bird>" => "<<robin --> bird> <=> <robin --> [living]>>";
2457 "<(&,bird,[yellow]) --> (&,bird,{Birdie})>", "(&,bird,[yellow])", "{Tweety}" => "<{Tweety} <-> (&,bird,[yellow])>";
2458 "<(&,robin,swan) --> (&,robin,(|,bird,swimmer))>", "bird", "(&,robin,(|,bird,swimmer))" => "<bird <-> (&,robin,(|,bird,swimmer))>";
2459 "<(&,robin,swan) --> bird>", "swimmer", "bird" => "<bird <-> swimmer>";
2460 "<(&,swan,swimmer) --> bird>", "(&,swimmer,(|,bird,robin))", "bird" => "<bird <-> (&,swimmer,(|,bird,robin))>";
2461 "<(*,(*,(*,0))) --> num>", "(*,(*,(*,0)))", "0" => "<0 <-> (*,(*,(*,0)))>";
2462 "<(*,b,a) --> like>", "(*,b,(/,like,_,b))", "like" => "<like <-> (*,b,(/,like,_,b))>";
2463 "<(/,neutralization,_,(/,reaction,acid,_)) --> (/,neutralization,_,base)>", "(/,reaction,_,(/,reaction,acid,_))", "(/,neutralization,_,base)" => "<(/,neutralization,_,base) <-> (/,reaction,_,(/,reaction,acid,_))>";
2464 "<(/,neutralization,_,base) --> (/,(*,acid,base),_,base)>", "(/,neutralization,_,(/,reaction,acid,_))", "(/,(*,acid,base),_,base)" => "<(/,neutralization,_,(/,reaction,acid,_)) <-> (/,(*,acid,base),_,base)>";
2465 "<(/,neutralization,_,base) --> (/,reaction,_,base)>", "(/,neutralization,_,base)", "acid" => "<acid <-> (/,neutralization,_,base)>";
2466 "<(/,neutralization,_,base) --> ?1>", "(/,(*,acid,base),_,base)", "?1" => "<?1 <-> (/,(*,acid,base),_,base)>";
2467 "<(/,neutralization,_,base) --> ?1>", "(/,neutralization,_,(/,reaction,acid,_))", "?1" => "<?1 <-> (/,neutralization,_,(/,reaction,acid,_))>";
2468 "<(/,neutralization,_,base) --> ?1>", "(/,reaction,_,base)", "?1" => "<?1 <-> (/,reaction,_,base)>";
2469 "<(/,open,_,lock) --> (/,open,_,{lock1})>", "(/,open,_,lock)", "{key1}" => "<{key1} <-> (/,open,_,lock)>";
2470 "<(/,reaction,(/,reaction,_,base),_) --> (/,reaction,acid,_)>", "(/,reaction,(/,reaction,_,base),_)", "base" => "<base <-> (/,reaction,(/,reaction,_,base),_)>";
2471 "<(\\,neutralization,_,base) --> acid>", "(/,reaction,_,base)", "acid" => "<acid <-> (/,reaction,_,base)>";
2472 "<(\\,neutralization,acid,_) --> (/,reaction,(/,reaction,_,base),_)>", "base", "(/,reaction,(/,reaction,_,base),_)" => "<base <-> (/,reaction,(/,reaction,_,base),_)>";
2473 "<(\\,neutralization,acid,_) --> (\\,reaction,acid,_)>", "(\\,neutralization,acid,_)", "(\\,reaction,acid,_)" => "<(\\,neutralization,acid,_) <-> (\\,reaction,acid,_)>";
2474 "<(\\,neutralization,acid,_) --> ?1>", "(/,reaction,(/,reaction,_,base),_)", "?1" => "<?1 <-> (/,reaction,(/,reaction,_,base),_)>";
2475 "<(\\,neutralization,acid,_) --> ?1>", "base", "?1" => "<?1 <-> base>";
2476 "<(\\,neutralization,acid,_) --> base>", "(/,reaction,(/,reaction,_,base),_)", "base" => "<base <-> (/,reaction,(/,reaction,_,base),_)>";
2477 "<(|,boy,girl) --> youth>", "(|,girl,[strong])", "youth" => "<youth <-> (|,girl,[strong])>";
2478 "<(|,robin,swan) --> (|,animal,robin)>", "(&,bird,swimmer)", "(|,animal,robin)" => "<(&,bird,swimmer) <-> (|,animal,robin)>";
2479 "<(|,robin,swan) --> (|,animal,robin)>", "(|,bird,robin)", "(|,animal,robin)" => "<(|,animal,robin) <-> (|,bird,robin)>";
2480 "<0 --> num>", "(/,num,_)", "num" => "<num <-> (/,num,_)>";
2481 "<?1 --> claimedByBob>", "?1", "(&,<bird --> fly>,<{Tweety} --> bird>)" => "<?1 <-> (&,<bird --> fly>,<{Tweety} --> bird>)>";
2482 "<?1 --> swimmer>", "?1", "animal" => "<?1 <-> animal>";
2483 "<[bright] --> [smart]>", "[bright]", "[smart]" => "<[bright] <-> [smart]>";
2484 "<bird --> (|,robin,swimmer)>", "bird", "(|,robin,swan)" => "<bird <-> (|,robin,swan)>";
2485 "<bird --> animal>", "bird", "robin" => "<bird <-> robin>";
2486 "<bird --> {Birdie}>", "bird", "[yellow]" => "<bird <-> [yellow]>";
2487 "<bird --> {Birdie}>", "bird", "{Tweety}" => "<bird <-> {Tweety}>";
2488 "<cat --> CAT>", "(/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)", "CAT" => "<CAT <-> (/,(/,REPRESENT,_,<(*,CAT,FISH) --> FOOD>),_,eat,fish)>";
2489 "<planetX --> {Mars,Pluto,Saturn,Venus}>", "{Mars,Pluto,Venus}", "{Mars,Pluto,Saturn,Venus}" => "<{Mars,Pluto,Venus} <-> {Mars,Pluto,Saturn,Venus}>";
2490 "<planetX --> {Mars,Pluto,Saturn,Venus}>", "{Pluto,Saturn}", "{Mars,Pluto,Saturn,Venus}" => "<{Pluto,Saturn} <-> {Mars,Pluto,Saturn,Venus}>";
2491 "<planetX --> {Mars,Pluto,Venus}>", "{Mars,Venus}", "{Mars,Pluto,Venus}" => "<{Mars,Venus} <-> {Mars,Pluto,Venus}>";
2492 "<planetX --> {Mars,Venus}>", "{Mars,Pluto,Venus}", "{Mars,Venus}" => "<{Mars,Venus} <-> {Mars,Pluto,Venus}>";
2493 "<planetX --> {Mars,Venus}>", "{Pluto,Saturn}", "{Mars,Venus}" => "<{Mars,Venus} <-> {Pluto,Saturn}>";
2494 "<planetX --> {Pluto,Saturn}>", "{Mars,Pluto,Saturn,Venus}", "{Pluto,Saturn}" => "<{Pluto,Saturn} <-> {Mars,Pluto,Saturn,Venus}>";
2495 "<robin --> (&,bird,swimmer)>", "robin", "swan" => "<robin <-> swan>";
2496 "<robin --> (|,bird,swimmer)>", "robin", "swan" => "<robin <-> swan>";
2497 "<robin --> [chirping]>", "robin", "{Tweety}" => "<robin <-> {Tweety}>";
2498 "<robin --> [with_wings]>", "robin", "bird" => "<bird <-> robin>";
2499 "<swan --> animal>", "(|,bird,robin)", "animal" => "<animal <-> (|,bird,robin)>";
2500 "<tim --> (/,uncle,_,tom)>", "(/,uncle,tom,_)", "(/,uncle,_,tom)" => "<(/,uncle,tom,_) <-> (/,uncle,_,tom)>";
2501 "<tim --> (/,uncle,tom,_)>", "tim", "(/,(*,tim,tom),tom,_)" => "<tim <-> (/,(*,tim,tom),tom,_)>";
2502 "<{Birdie} --> [yellow]>", "bird", "[yellow]" => "<bird <-> [yellow]>";
2503 "<{Birdie} --> {Tweety}>", "{Birdie}", "{Tweety}" => "<{Birdie} <-> {Tweety}>";
2504 "<{Tweety} --> (&,[yellow],{Birdie})>", "bird", "(&,[yellow],{Birdie})" => "<bird <-> (&,[yellow],{Birdie})>";
2505 "<{Tweety} --> (&,bird,[yellow])>", "{Birdie}", "(&,bird,[yellow])" => "<{Birdie} <-> (&,bird,[yellow])>";
2506 "<{Tweety} --> (&,bird,{Birdie})>", "(|,bird,[yellow])", "(&,bird,{Birdie})" => "<(&,bird,{Birdie}) <-> (|,bird,[yellow])>";
2507 "<{Tweety} --> (|,bird,[yellow])>", "{Birdie}", "(|,bird,[yellow])" => "<{Birdie} <-> (|,bird,[yellow])>";
2508 "<{Tweety} --> [chirping]>", "{Tweety}", "robin" => "<robin <-> {Tweety}>";
2509 "<{Tweety} --> [yellow]>", "{Birdie}", "[yellow]" => "<[yellow] <-> {Birdie}>";
2510 "<{Tweety} --> bird>", "[with_wings]", "bird" => "<bird <-> [with_wings]>";
2511 "<{Tweety} --> bird>", "flyer", "bird" => "<bird <-> flyer>";
2512 "<{Tweety} --> bird>", "{Tweety}", "bird" => "<bird <-> {Tweety}>";
2513 "<{Tweety} --> {Birdie}>", "(&,bird,[yellow])", "{Birdie}" => "<{Birdie} <-> (&,bird,[yellow])>";
2514 "<{Tweety} --> {Birdie}>", "bird", "{Birdie}" => "<bird <-> {Birdie}>";
2515 "<{Tweety} --> {Birdie}>", "{Tweety}", "[yellow]" => "<[yellow] <-> {Tweety}>";
2516 "<{Tweety} --> {Birdie}>", "{Tweety}", "bird" => "<bird <-> {Tweety}>";
2517 "<{key1} --> key>", "(/,open,_,{lock1})", "key" => "<key <-> (/,open,_,{lock1})>";
2518 "<{lock1} --> (/,open,{key1},_)>", "lock", "(/,open,{key1},_)" => "<lock <-> (/,open,{key1},_)>";
2519 }
2520 ok!()
2521 }
2522 }
2523}