1use crate::prelude::*;
2use std::fmt;
3
4#[derive(Clone)]
5pub struct AndFact {
6 pub facts: Vec<AtomicFact>,
7 pub line_file: LineFile,
8}
9
10impl AndFact {
11 pub fn new(facts: Vec<AtomicFact>, line_file: LineFile) -> Self {
12 AndFact { facts, line_file }
13 }
14 pub fn line_file(&self) -> LineFile {
15 self.line_file.clone()
16 }
17}
18
19#[derive(Clone)]
20pub struct ChainFact {
21 pub objs: Vec<Obj>,
22 pub prop_names: Vec<IdentifierOrIdentifierWithMod>,
23 pub line_file: LineFile,
24}
25
26impl ChainFact {
27 pub fn new(
28 objs: Vec<Obj>,
29 prop_names: Vec<IdentifierOrIdentifierWithMod>,
30 line_file: LineFile,
31 ) -> Self {
32 ChainFact {
33 objs,
34 prop_names,
35 line_file,
36 }
37 }
38 pub fn line_file(&self) -> LineFile {
39 self.line_file.clone()
40 }
41
42 pub fn facts(&self) -> Result<Vec<AtomicFact>, RuntimeErrorStruct> {
43 if self.objs.len() != self.prop_names.len() + 1 {
44 return Err(RuntimeErrorStruct::new_with_msg_previous_error(
45 format!(
46 "the number of objects ({}) is not equal to the number of property names ({}) + 1",
47 self.objs.len(),
48 self.prop_names.len(),
49 ),
50 None,
51 ));
52 }
53
54 let mut facts = Vec::with_capacity(self.prop_names.len());
55 for (i, _) in self.prop_names.iter().enumerate() {
56 let prop_name = self.prop_names[i].clone();
57 let left_obj = self.objs[i].clone();
58 let right_obj = self.objs[i + 1].clone();
59 let atomic_fact = AtomicFact::to_atomic_fact(
60 prop_name,
61 true,
62 vec![left_obj, right_obj],
63 self.line_file.clone(),
64 );
65 facts.push(atomic_fact?);
66 }
67 Ok(facts)
68 }
69}
70
71#[derive(Clone)]
72pub enum ChainAtomicFact {
73 AtomicFact(AtomicFact),
74 ChainFact(ChainFact),
75}
76
77impl fmt::Display for ChainAtomicFact {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 match self {
80 ChainAtomicFact::AtomicFact(a) => write!(f, "{}", a),
81 ChainAtomicFact::ChainFact(c) => write!(f, "{}", c),
82 }
83 }
84}
85
86#[derive(Clone)]
87pub enum AndChainAtomicFact {
88 AtomicFact(AtomicFact),
89 AndFact(AndFact),
90 ChainFact(ChainFact),
91}
92
93impl AndChainAtomicFact {
94 pub fn line_file(&self) -> LineFile {
95 match self {
96 AndChainAtomicFact::AtomicFact(a) => a.line_file(),
97 AndChainAtomicFact::AndFact(a) => a.line_file(),
98 AndChainAtomicFact::ChainFact(c) => c.line_file(),
99 }
100 }
101
102 pub fn replace_bound_identifier(self, from: &str, to: &str) -> Self {
103 if from == to {
104 return self;
105 }
106 match self {
107 AndChainAtomicFact::AtomicFact(a) => {
108 AndChainAtomicFact::AtomicFact(a.replace_bound_identifier(from, to))
109 }
110 AndChainAtomicFact::AndFact(af) => AndChainAtomicFact::AndFact(AndFact {
111 facts: af
112 .facts
113 .into_iter()
114 .map(|x| x.replace_bound_identifier(from, to))
115 .collect(),
116 line_file: af.line_file,
117 }),
118 AndChainAtomicFact::ChainFact(cf) => AndChainAtomicFact::ChainFact(ChainFact {
119 objs: cf
120 .objs
121 .into_iter()
122 .map(|o| Obj::replace_bound_identifier(o, from, to))
123 .collect(),
124 prop_names: cf.prop_names,
125 line_file: cf.line_file,
126 }),
127 }
128 }
129}
130
131impl fmt::Display for AndFact {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(
134 f,
135 "{}",
136 vec_to_string_with_sep(&self.facts, format!(" {} ", AND))
137 )
138 }
139}
140
141impl AndFact {
142 pub fn key(&self) -> String {
143 vec_to_string_with_sep(
144 &self.facts.iter().map(|a| a.key()).collect::<Vec<_>>(),
145 format!(" {} ", AND),
146 )
147 }
148
149 pub fn get_args_from_fact(&self) -> Vec<Obj> {
150 let mut result: Vec<Obj> = Vec::new();
151 for atomic_fact in self.facts.iter() {
152 let args_from_atomic_fact = atomic_fact.get_args_from_fact();
153 for arg in args_from_atomic_fact {
154 result.push(arg);
155 }
156 }
157 result
158 }
159}
160
161impl fmt::Display for ChainFact {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 let mut s = self.objs[0].to_string();
164 for (i, obj) in self.objs[1..].iter().enumerate() {
165 if is_comparison_str(&self.prop_names[i].to_string()) {
166 s.push_str(&format!(" {} {}", self.prop_names[i], obj));
167 } else {
168 s.push_str(&format!(" {}{} {}", FACT_PREFIX, self.prop_names[i], obj));
169 }
170 }
171 write!(f, "{}", s)
172 }
173}
174
175impl ChainFact {
176 pub fn key(&self) -> String {
177 vec_to_string_with_sep(
178 &self
179 .prop_names
180 .iter()
181 .map(|p| p.to_string())
182 .collect::<Vec<_>>(),
183 format!(" {} ", AND),
184 )
185 }
186
187 pub fn get_args_from_fact(&self) -> Vec<Obj> {
188 let mut result: Vec<Obj> = Vec::new();
189 for obj in self.objs.iter() {
190 result.push(obj.clone());
191 }
192 result
193 }
194}
195
196impl fmt::Display for AndChainAtomicFact {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 match self {
199 AndChainAtomicFact::AtomicFact(a) => write!(f, "{}", a),
200 AndChainAtomicFact::AndFact(a) => write!(f, "{}", a),
201 AndChainAtomicFact::ChainFact(c) => write!(f, "{}", c),
202 }
203 }
204}
205
206impl AndChainAtomicFact {
207 pub fn key(&self) -> String {
208 match self {
209 AndChainAtomicFact::AtomicFact(a) => a.key(),
210 AndChainAtomicFact::AndFact(a) => a.key(),
211 AndChainAtomicFact::ChainFact(c) => c.key(),
212 }
213 }
214
215 pub fn to_fact(&self) -> Fact {
216 match self {
217 AndChainAtomicFact::AtomicFact(atomic_fact) => Fact::AtomicFact(atomic_fact.clone()),
218 AndChainAtomicFact::AndFact(and_fact) => Fact::AndFact(and_fact.clone()),
219 AndChainAtomicFact::ChainFact(chain_fact) => Fact::ChainFact(chain_fact.clone()),
220 }
221 }
222
223 pub fn to_exist_or_and_chain_atomic_fact(&self) -> crate::fact::ExistOrAndChainAtomicFact {
224 match self {
225 AndChainAtomicFact::AtomicFact(atomic_fact) => {
226 crate::fact::ExistOrAndChainAtomicFact::AtomicFact(atomic_fact.clone())
227 }
228 AndChainAtomicFact::AndFact(and_fact) => {
229 crate::fact::ExistOrAndChainAtomicFact::AndFact(and_fact.clone())
230 }
231 AndChainAtomicFact::ChainFact(chain_fact) => {
232 crate::fact::ExistOrAndChainAtomicFact::ChainFact(chain_fact.clone())
233 }
234 }
235 }
236}
237
238impl AndChainAtomicFact {
239 pub fn get_args_from_fact(&self) -> Vec<Obj> {
240 match self {
241 AndChainAtomicFact::AtomicFact(atomic_fact) => atomic_fact.get_args_from_fact(),
242 AndChainAtomicFact::AndFact(and_fact) => and_fact.get_args_from_fact(),
243 AndChainAtomicFact::ChainFact(chain_fact) => chain_fact.get_args_from_fact(),
244 }
245 }
246}