1use std::fmt::{Display, Formatter};
2use std::iter::zip;
3
4use crate::ast::domains::attrs::MSetAttr;
5use crate::ast::domains::attrs::PartitionAttr;
6use crate::ast::domains::attrs::SetAttr;
7use crate::ast::domains::ground::FieldGround;
8use crate::ast::records::Field;
9use crate::ast::{
10 DomainOpError, Expression, FuncAttr, Moo, Reference, RelAttr, ReturnType, SequenceAttr,
11 Typeable,
12 domains::{DomainPtr, GroundDomain, int_val::IntVal, range::Range},
13 pretty::pretty_vec,
14};
15use crate::bug;
16
17use funcmap::{FuncMap, TryFuncMap};
18use itertools::Itertools;
19use polyquine::Quine;
20use serde::{Deserialize, Serialize};
21use uniplate::Uniplate;
22
23pub(super) type FieldUnresolved = Field<DomainPtr>;
24
25impl From<FieldGround> for FieldUnresolved {
26 fn from(v: FieldGround) -> Self {
27 v.func_map(DomainPtr::from)
28 }
29}
30
31impl TryFrom<FieldUnresolved> for FieldGround {
32 type Error = DomainOpError;
33 fn try_from(v: FieldUnresolved) -> Result<Self, Self::Error> {
34 v.try_func_map(DomainPtr::try_into)
35 }
36}
37
38#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
39#[path_prefix(conjure_cp::ast)]
40#[biplate(to=Expression)]
41#[biplate(to=Reference)]
42#[biplate(to=IntVal)]
43#[biplate(to=DomainPtr)]
44pub enum UnresolvedDomain {
45 Int(Vec<Range<IntVal>>),
46 Set(SetAttr<IntVal>, DomainPtr),
48 MSet(MSetAttr<IntVal>, DomainPtr),
49 Matrix(DomainPtr, Vec<DomainPtr>),
51 Tuple(Vec<DomainPtr>),
53 Sequence(SequenceAttr<IntVal>, DomainPtr),
54 #[polyquine_skip]
56 Reference(Reference),
57 Record(Vec<FieldUnresolved>),
59 Function(FuncAttr<IntVal>, DomainPtr, DomainPtr),
61 Variant(Vec<FieldUnresolved>),
63 Relation(RelAttr<IntVal>, Vec<DomainPtr>),
65 Partition(PartitionAttr<IntVal>, DomainPtr),
66}
67
68impl UnresolvedDomain {
69 pub fn resolve(&self) -> Result<GroundDomain, DomainOpError> {
70 match self {
71 UnresolvedDomain::Int(rngs) => rngs
72 .iter()
73 .map(Range::<IntVal>::resolve)
74 .collect::<Result<_, _>>()
75 .map(GroundDomain::Int),
76 UnresolvedDomain::Set(attr, inner) => {
77 Ok(GroundDomain::Set(attr.resolve()?, inner.resolve()?))
78 }
79 UnresolvedDomain::MSet(attr, inner) => {
80 Ok(GroundDomain::MSet(attr.resolve()?, inner.resolve()?))
81 }
82 UnresolvedDomain::Partition(attr, inner) => {
83 Ok(GroundDomain::Partition(attr.resolve()?, inner.resolve()?))
84 }
85 UnresolvedDomain::Matrix(inner, idx_doms) => {
86 let inner_gd = inner.resolve()?;
87 idx_doms
88 .iter()
89 .map(DomainPtr::resolve)
90 .collect::<Result<_, _>>()
91 .map(|idx| GroundDomain::Matrix(inner_gd, idx))
92 }
93 UnresolvedDomain::Sequence(attr, inner) => {
94 Ok(GroundDomain::Sequence(attr.resolve()?, inner.resolve()?))
95 }
96 UnresolvedDomain::Tuple(inners) => inners
97 .iter()
98 .map(DomainPtr::resolve)
99 .collect::<Result<_, _>>()
100 .map(GroundDomain::Tuple),
101 UnresolvedDomain::Record(entries) => entries
102 .iter()
103 .map(|f| {
104 f.value.resolve().map(|gd| FieldGround {
105 name: f.name.clone(),
106 value: gd,
107 })
108 })
109 .collect::<Result<_, _>>()
110 .map(GroundDomain::Record),
111 UnresolvedDomain::Reference(re) => re
112 .ptr
113 .as_domain_letting()
114 .unwrap_or_else(|| {
115 bug!("Reference domain should point to domain letting, but got {re}")
116 })
117 .resolve()
118 .map(Moo::unwrap_or_clone),
119 UnresolvedDomain::Function(attr, dom, cdom) => Ok(GroundDomain::Function(
120 attr.resolve()?,
121 dom.resolve()?,
122 cdom.resolve()?,
123 )),
124 UnresolvedDomain::Variant(entries) => entries
125 .iter()
126 .map(|f| {
127 f.value.resolve().map(|gd| FieldGround {
128 name: f.name.clone(),
129 value: gd,
130 })
131 })
132 .collect::<Result<_, _>>()
133 .map(GroundDomain::Variant),
134 UnresolvedDomain::Relation(attr, inners) => {
135 let resolved_attr = attr.resolve()?;
136 inners
137 .iter()
138 .map(DomainPtr::resolve)
139 .collect::<Result<_, _>>()
140 .map(|items| GroundDomain::Relation(resolved_attr, items))
141 }
142 }
143 }
144
145 pub(super) fn union_unresolved(
146 &self,
147 other: &UnresolvedDomain,
148 ) -> Result<UnresolvedDomain, DomainOpError> {
149 match (self, other) {
150 (UnresolvedDomain::Int(lhs), UnresolvedDomain::Int(rhs)) => {
151 let merged = lhs.iter().chain(rhs.iter()).cloned().collect_vec();
152 Ok(UnresolvedDomain::Int(merged))
153 }
154 (UnresolvedDomain::Int(_), _) | (_, UnresolvedDomain::Int(_)) => {
155 Err(DomainOpError::WrongType)
156 }
157 (UnresolvedDomain::Set(_, in1), UnresolvedDomain::Set(_, in2)) => {
158 Ok(UnresolvedDomain::Set(SetAttr::default(), in1.union(in2)?))
159 }
160 (UnresolvedDomain::Set(_, _), _) | (_, UnresolvedDomain::Set(_, _)) => {
161 Err(DomainOpError::WrongType)
162 }
163 (UnresolvedDomain::MSet(_, in1), UnresolvedDomain::MSet(_, in2)) => {
164 Ok(UnresolvedDomain::MSet(MSetAttr::default(), in1.union(in2)?))
165 }
166 (UnresolvedDomain::MSet(_, _), _) | (_, UnresolvedDomain::MSet(_, _)) => {
167 Err(DomainOpError::WrongType)
168 }
169 (UnresolvedDomain::Matrix(in1, idx1), UnresolvedDomain::Matrix(in2, idx2))
170 if idx1 == idx2 =>
171 {
172 Ok(UnresolvedDomain::Matrix(in1.union(in2)?, idx1.clone()))
173 }
174 (UnresolvedDomain::Matrix(_, _), _) | (_, UnresolvedDomain::Matrix(_, _)) => {
175 Err(DomainOpError::WrongType)
176 }
177 (UnresolvedDomain::Tuple(lhs), UnresolvedDomain::Tuple(rhs))
178 if lhs.len() == rhs.len() =>
179 {
180 let mut merged = Vec::new();
181 for (l, r) in zip(lhs, rhs) {
182 merged.push(l.union(r)?)
183 }
184 Ok(UnresolvedDomain::Tuple(merged))
185 }
186 (UnresolvedDomain::Tuple(_), _) | (_, UnresolvedDomain::Tuple(_)) => {
187 Err(DomainOpError::WrongType)
188 }
189 (UnresolvedDomain::Relation(_, in1s), UnresolvedDomain::Relation(_, in2s)) => {
190 let mut inners = Vec::new();
191 for (in1, in2) in in1s.iter().zip(in2s.iter()) {
192 inners.push(in1.union(in2)?)
193 }
194 Ok(UnresolvedDomain::Relation(RelAttr::default(), inners))
195 }
196 (UnresolvedDomain::Relation(_, _), _) | (_, UnresolvedDomain::Relation(_, _)) => {
197 Err(DomainOpError::WrongType)
198 }
199 (UnresolvedDomain::Reference(_), _) | (_, UnresolvedDomain::Reference(_)) => {
201 Err(DomainOpError::NotGround)
202 }
203 #[allow(unreachable_patterns)]
205 (UnresolvedDomain::Record(_), _) | (_, UnresolvedDomain::Record(_)) => {
206 Err(DomainOpError::WrongType)
207 }
208 #[allow(unreachable_patterns)]
209 (UnresolvedDomain::Function(_, _, _), _) | (_, UnresolvedDomain::Function(_, _, _)) => {
210 Err(DomainOpError::WrongType)
211 }
212 #[allow(unreachable_patterns)]
213 (UnresolvedDomain::Partition(_, _), _) | (_, UnresolvedDomain::Partition(_, _)) => {
214 Err(DomainOpError::WrongType)
215 }
216 #[allow(unreachable_patterns)]
217 (UnresolvedDomain::Variant(_), _) | (_, UnresolvedDomain::Variant(_)) => {
218 Err(DomainOpError::WrongType)
219 }
220 #[allow(unreachable_patterns)]
221 (UnresolvedDomain::Sequence(_, _), _) | (_, UnresolvedDomain::Sequence(_, _)) => {
222 Err(DomainOpError::WrongType)
223 }
224 }
225 }
226
227 pub fn element_domain(&self) -> Option<DomainPtr> {
228 match self {
229 UnresolvedDomain::Set(_, inner_dom) => Some(inner_dom.clone()),
230 UnresolvedDomain::Sequence(_, inner_dom) => Some(inner_dom.clone()),
231 UnresolvedDomain::Matrix(_, _) => {
232 todo!("Unwrap one dimension of the domain")
233 }
234 _ => None,
235 }
236 }
237}
238
239impl Typeable for UnresolvedDomain {
240 fn return_type(&self) -> ReturnType {
241 match self {
242 UnresolvedDomain::Reference(re) => re.return_type(),
243 UnresolvedDomain::Int(_) => ReturnType::Int,
244 UnresolvedDomain::Set(_attr, inner) => ReturnType::Set(Box::new(inner.return_type())),
245 UnresolvedDomain::MSet(_attr, inner) => ReturnType::MSet(Box::new(inner.return_type())),
246 UnresolvedDomain::Partition(_, inner) => {
247 ReturnType::Partition(Box::new(inner.return_type()))
248 }
249 UnresolvedDomain::Sequence(_attr, inner) => {
250 ReturnType::Sequence(Box::new(inner.return_type()))
251 }
252 UnresolvedDomain::Matrix(inner, _idx) => {
253 ReturnType::Matrix(Box::new(inner.return_type()))
254 }
255 UnresolvedDomain::Tuple(inners) => {
256 let mut inner_types = Vec::new();
257 for inner in inners {
258 inner_types.push(inner.return_type());
259 }
260 ReturnType::Tuple(inner_types)
261 }
262 UnresolvedDomain::Record(entries) => {
263 let mut entry_types = Vec::new();
264 for entry in entries {
265 entry_types.push(entry.clone().func_map(|x| x.return_type()));
266 }
267 ReturnType::Record(entry_types)
268 }
269 UnresolvedDomain::Variant(entries) => {
270 let mut entry_types = Vec::new();
271 for entry in entries {
272 entry_types.push(entry.clone().func_map(|x| x.return_type()));
273 }
274 ReturnType::Variant(entry_types)
275 }
276 UnresolvedDomain::Function(_, dom, cdom) => {
277 ReturnType::Function(Box::new(dom.return_type()), Box::new(cdom.return_type()))
278 }
279 UnresolvedDomain::Relation(_, inners) => {
280 let mut inner_types = Vec::new();
281 for inner in inners {
282 inner_types.push(inner.return_type());
283 }
284 ReturnType::Relation(inner_types)
285 }
286 }
287 }
288}
289
290impl Display for FieldUnresolved {
291 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
292 write!(f, "{}: {}", self.name, self.value)
293 }
294}
295
296impl Display for UnresolvedDomain {
297 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
298 match &self {
299 UnresolvedDomain::Reference(re) => write!(f, "{re}"),
300 UnresolvedDomain::Int(ranges) => {
301 if ranges.iter().all(Range::is_lower_or_upper_bounded) {
302 let rngs: String = ranges.iter().map(|r| format!("{r}")).join(", ");
303 write!(f, "int({})", rngs)
304 } else {
305 write!(f, "int")
306 }
307 }
308 UnresolvedDomain::Set(attrs, inner_dom) => write!(f, "set {attrs} of {inner_dom}"),
309 UnresolvedDomain::MSet(attrs, inner_dom) => write!(f, "mset {attrs} of {inner_dom}"),
310 UnresolvedDomain::Partition(attrs, inner_dom) => {
311 write!(f, "partition {attrs} from {inner_dom}")
312 }
313 UnresolvedDomain::Sequence(attrs, inner_dom) => {
314 write!(f, "sequence {attrs} of {inner_dom}")
315 }
316 UnresolvedDomain::Matrix(value_domain, index_domains) => {
317 write!(
318 f,
319 "matrix indexed by {} of {value_domain}",
320 pretty_vec(&index_domains.iter().collect_vec())
321 )
322 }
323 UnresolvedDomain::Tuple(domains) => {
324 write!(f, "tuple ({})", &domains.iter().join(","))
325 }
326 UnresolvedDomain::Record(entries) => {
327 let inners = entries.iter().map(|t| format!("{}", t)).join(", ");
328 write!(f, "record {{{inners}}}",)
329 }
330 UnresolvedDomain::Variant(entries) => {
331 let inners = entries.iter().map(|t| format!("{}", t)).join(", ");
332 write!(f, "variant {{{inners}}}",)
333 }
334 UnresolvedDomain::Function(attribute, domain, codomain) => {
335 write!(f, "function {} {} --> {} ", attribute, domain, codomain)
336 }
337 UnresolvedDomain::Relation(attrs, domains) => {
338 write!(f, "relation {} of ({})", attrs, domains.iter().join(" * "))
339 }
340 }
341 }
342}