1use crate::core::logic_variable::Var;
2use crate::core::structure::Structure;
3use crate::core::substitution::Substitution;
4use crate::core::value::Value;
5use std::any::Any;
6use std::fmt::{Debug, Formatter, Result};
7use std::sync::Arc;
8
9#[derive(Clone, PartialEq)]
10pub struct Pair {
11 pub first: Value,
12 pub second: Value,
13}
14
15impl Debug for Pair {
16 fn fmt(&self, f: &mut Formatter) -> Result {
17 if !f.alternate() {
18 write!(f, "(")?;
19 }
20
21 if self.second.downcast_ref::<()>().is_some() {
22 write!(f, "{:?}", self.first)?;
23 } else if let Some(next) = self.second.downcast_ref::<Pair>() {
24 write!(f, "{:?} {:#?}", self.first, next)?;
25 } else {
26 write!(f, "{:?} . {:?}", self.first, self.second)?;
27 }
28
29 if !f.alternate() {
30 write!(f, ")")?;
31 }
32
33 Ok(())
34 }
35}
36
37impl Structure for Pair {
38 fn occurs<'s>(&self, x: &Var, s: &Substitution<'s>) -> bool {
39 s.occurs(x, &self.first) || s.occurs(x, &self.second)
40 }
41
42 fn unify<'s>(&self, v: &Value, s: Substitution<'s>) -> Option<Substitution<'s>> {
43 let other = v.downcast_ref::<Self>()?;
44 s.unify(&self.first, &other.first)
45 .and_then(|s| s.unify(&self.second, &other.second))
46 }
47
48 fn walk_star(self: Arc<Self>, s: &Substitution<'_>) -> Value {
49 (s.walk_star(&self.first), s.walk_star(&self.second)).into()
50 }
51
52 fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s> {
53 s.reify_s(&self.first).reify_s(&self.second)
54 }
55
56 fn as_any(&self) -> &dyn Any {
57 self
58 }
59
60 fn eqv(&self, other: &Value) -> bool {
61 other
62 .downcast_ref::<Self>()
63 .map(|v| v == self)
64 .unwrap_or(false)
65 }
66}
67
68impl From<(Value, Value)> for Pair {
69 fn from(pair: (Value, Value)) -> Self {
70 Pair {
71 first: pair.0,
72 second: pair.1,
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn pairs_print_two_values_in_parentheses_separated_by_dot() {
83 let first = Value::new(());
84 let second = Value::new(2);
85 let pair = Pair { first, second };
86
87 let repr = format!("{:?}", pair);
88
89 assert_eq!(repr, "(() . 2)")
90 }
91
92 #[test]
93 fn pairs_print_only_first_value_in_parentheses_if_second_is_nil() {
94 let first = Value::new(1);
95 let second = Value::new(());
96 let pair = Pair { first, second };
97
98 let repr = format!("{:?}", pair);
99
100 assert_eq!(repr, "(1)")
101 }
102
103 #[test]
104 fn pairs_print_as_list_if_second_is_pair() {
105 let a = Value::new(1);
106 let b = Value::new(2);
107 let c = Value::new(3);
108 let pair = Pair {
109 first: a,
110 second: Value::new(Pair {
111 first: b,
112 second: c,
113 }),
114 };
115
116 let repr = format!("{:?}", pair);
117
118 assert_eq!(repr, "(1 2 . 3)")
119 }
120
121 #[test]
122 fn pairs_print_alternate_omits_parentheses() {
123 let first = Value::new(());
124 let second = Value::new(2);
125 let pair = Pair { first, second };
126
127 let repr = format!("{:#?}", pair);
128
129 assert_eq!(repr, "() . 2")
130 }
131}