1use crate::ast::domains::attrs::MSetAttr;
2use crate::ast::domains::attrs::PartitionAttr;
3use crate::ast::domains::attrs::SetAttr;
4use crate::ast::{
5 DeclarationKind, DomainOpError, Expression, FieldEntryGround, FuncAttr, Literal, Metadata, Moo,
6 Reference, RelAttr, SequenceAttr, Typeable,
7 domains::{
8 GroundDomain,
9 domain::{DomainPtr, Int},
10 range::Range,
11 },
12};
13use crate::{bug, domain_int, matrix_expr, range};
14use conjure_cp_core::ast::pretty::pretty_vec;
15use conjure_cp_core::ast::{Name, ReturnType, eval_constant};
16use itertools::Itertools;
17use polyquine::Quine;
18use serde::{Deserialize, Serialize};
19use std::fmt::{Display, Formatter};
20use std::iter::zip;
21use std::ops::Deref;
22use uniplate::Uniplate;
23
24#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
25#[path_prefix(conjure_cp::ast)]
26#[biplate(to=Expression)]
27#[biplate(to=Reference)]
28pub enum IntVal {
29 Const(Int),
30 #[polyquine_skip]
31 Reference(Reference),
32 Expr(Moo<Expression>),
33}
34
35impl From<Int> for IntVal {
36 fn from(value: Int) -> Self {
37 Self::Const(value)
38 }
39}
40
41impl TryInto<Int> for IntVal {
42 type Error = DomainOpError;
43
44 fn try_into(self) -> Result<Int, Self::Error> {
45 match self {
46 IntVal::Const(val) => Ok(val),
47 _ => Err(DomainOpError::NotGround),
48 }
49 }
50}
51
52impl From<Range<Int>> for Range<IntVal> {
53 fn from(value: Range<Int>) -> Self {
54 match value {
55 Range::Single(x) => Range::Single(x.into()),
56 Range::Bounded(l, r) => Range::Bounded(l.into(), r.into()),
57 Range::UnboundedL(r) => Range::UnboundedL(r.into()),
58 Range::UnboundedR(l) => Range::UnboundedR(l.into()),
59 Range::Unbounded => Range::Unbounded,
60 }
61 }
62}
63
64impl TryInto<Range<Int>> for Range<IntVal> {
65 type Error = DomainOpError;
66
67 fn try_into(self) -> Result<Range<Int>, Self::Error> {
68 match self {
69 Range::Single(x) => Ok(Range::Single(x.try_into()?)),
70 Range::Bounded(l, r) => Ok(Range::Bounded(l.try_into()?, r.try_into()?)),
71 Range::UnboundedL(r) => Ok(Range::UnboundedL(r.try_into()?)),
72 Range::UnboundedR(l) => Ok(Range::UnboundedR(l.try_into()?)),
73 Range::Unbounded => Ok(Range::Unbounded),
74 }
75 }
76}
77
78impl From<SetAttr<Int>> for SetAttr<IntVal> {
79 fn from(value: SetAttr<Int>) -> Self {
80 SetAttr {
81 size: value.size.into(),
82 }
83 }
84}
85
86impl TryInto<SetAttr<Int>> for SetAttr<IntVal> {
87 type Error = DomainOpError;
88
89 fn try_into(self) -> Result<SetAttr<Int>, Self::Error> {
90 let size: Range<Int> = self.size.try_into()?;
91 Ok(SetAttr { size })
92 }
93}
94
95impl From<MSetAttr<Int>> for MSetAttr<IntVal> {
96 fn from(value: MSetAttr<Int>) -> Self {
97 MSetAttr {
98 size: value.size.into(),
99 occurrence: value.occurrence.into(),
100 }
101 }
102}
103
104impl TryInto<MSetAttr<Int>> for MSetAttr<IntVal> {
105 type Error = DomainOpError;
106
107 fn try_into(self) -> Result<MSetAttr<Int>, Self::Error> {
108 let size: Range<Int> = self.size.try_into()?;
109 let occurrence: Range<Int> = self.occurrence.try_into()?;
110 Ok(MSetAttr { size, occurrence })
111 }
112}
113
114impl From<FuncAttr<Int>> for FuncAttr<IntVal> {
115 fn from(value: FuncAttr<Int>) -> Self {
116 FuncAttr {
117 size: value.size.into(),
118 partiality: value.partiality,
119 jectivity: value.jectivity,
120 }
121 }
122}
123
124impl TryInto<FuncAttr<Int>> for FuncAttr<IntVal> {
125 type Error = DomainOpError;
126
127 fn try_into(self) -> Result<FuncAttr<Int>, Self::Error> {
128 let size: Range<Int> = self.size.try_into()?;
129 Ok(FuncAttr {
130 size,
131 jectivity: self.jectivity,
132 partiality: self.partiality,
133 })
134 }
135}
136
137impl From<RelAttr<Int>> for RelAttr<IntVal> {
138 fn from(value: RelAttr<Int>) -> Self {
139 RelAttr {
140 size: value.size.into(),
141 binary: value.binary,
142 }
143 }
144}
145
146impl TryInto<RelAttr<Int>> for RelAttr<IntVal> {
147 type Error = DomainOpError;
148
149 fn try_into(self) -> Result<RelAttr<Int>, Self::Error> {
150 let size: Range<Int> = self.size.try_into()?;
151 Ok(RelAttr {
152 size,
153 binary: self.binary,
154 })
155 }
156}
157
158impl From<PartitionAttr<Int>> for PartitionAttr<IntVal> {
159 fn from(value: PartitionAttr<Int>) -> Self {
160 PartitionAttr {
161 num_parts: value.num_parts.into(),
162 part_len: value.part_len.into(),
163 is_regular: value.is_regular,
164 }
165 }
166}
167
168impl TryInto<PartitionAttr<Int>> for PartitionAttr<IntVal> {
169 type Error = DomainOpError;
170
171 fn try_into(self) -> Result<PartitionAttr<Int>, Self::Error> {
172 let num_parts: Range<Int> = self.num_parts.try_into()?;
173 let part_len: Range<Int> = self.part_len.try_into()?;
174 let is_regular: bool = self.is_regular;
175 Ok(PartitionAttr {
176 num_parts,
177 part_len,
178 is_regular,
179 })
180 }
181}
182
183impl From<SequenceAttr<Int>> for SequenceAttr<IntVal> {
184 fn from(value: SequenceAttr<Int>) -> Self {
185 SequenceAttr {
186 size: value.size.into(),
187 jectivity: value.jectivity,
188 }
189 }
190}
191
192impl TryInto<SequenceAttr<Int>> for SequenceAttr<IntVal> {
193 type Error = DomainOpError;
194
195 fn try_into(self) -> Result<SequenceAttr<Int>, Self::Error> {
196 let size: Range<Int> = self.size.try_into()?;
197 Ok(SequenceAttr {
198 size,
199 jectivity: self.jectivity,
200 })
201 }
202}
203
204impl Display for IntVal {
205 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
206 match self {
207 IntVal::Const(val) => write!(f, "{val}"),
208 IntVal::Reference(re) => write!(f, "{re}"),
209 IntVal::Expr(expr) => write!(f, "({expr})"),
210 }
211 }
212}
213
214impl IntVal {
215 pub fn new_ref(re: &Reference) -> Option<IntVal> {
216 match re.ptr.kind().deref() {
217 DeclarationKind::ValueLetting(expr, _)
218 | DeclarationKind::TemporaryValueLetting(expr)
219 | DeclarationKind::QuantifiedExpr(expr) => match expr.return_type() {
220 ReturnType::Int => Some(IntVal::Reference(re.clone())),
221 _ => None,
222 },
223 DeclarationKind::Given(dom) => match dom.return_type() {
224 ReturnType::Int => Some(IntVal::Reference(re.clone())),
225 _ => None,
226 },
227 DeclarationKind::Quantified(inner) => match inner.domain().return_type() {
228 ReturnType::Int => Some(IntVal::Reference(re.clone())),
229 _ => None,
230 },
231 DeclarationKind::Find(var) => match var.return_type() {
232 ReturnType::Int => Some(IntVal::Reference(re.clone())),
233 _ => None,
234 },
235 DeclarationKind::DomainLetting(_) | DeclarationKind::Field(_) => None,
236 }
237 }
238
239 pub fn new_expr(value: Moo<Expression>) -> Option<IntVal> {
240 if value.return_type() != ReturnType::Int {
241 return None;
242 }
243 Some(IntVal::Expr(value))
244 }
245
246 pub fn resolve(&self) -> Option<Int> {
247 match self {
248 IntVal::Const(value) => Some(*value),
249 IntVal::Expr(expr) => eval_expr_to_int(expr),
250 IntVal::Reference(re) => match re.ptr.kind().deref() {
251 DeclarationKind::ValueLetting(expr, _)
252 | DeclarationKind::TemporaryValueLetting(expr) => eval_expr_to_int(expr),
253 DeclarationKind::Given(_) => None,
255 DeclarationKind::Quantified(inner) => {
256 if let Some(generator) = inner.generator()
257 && let Some(expr) = generator.as_value_letting()
258 {
259 eval_expr_to_int(&expr)
260 } else {
261 None
262 }
263 }
264 DeclarationKind::QuantifiedExpr(_) => None,
266 DeclarationKind::Find(_) => None,
268 DeclarationKind::DomainLetting(_) | DeclarationKind::Field(_) => bug!(
269 "Expected integer expression, given, or letting inside int domain; Got: {re}"
270 ),
271 },
272 }
273 }
274}
275
276fn eval_expr_to_int(expr: &Expression) -> Option<Int> {
277 match eval_constant(expr)? {
278 Literal::Int(v) => Some(v),
279 _ => bug!("Expected integer expression, got: {expr}"),
280 }
281}
282
283impl From<IntVal> for Expression {
284 fn from(value: IntVal) -> Self {
285 match value {
286 IntVal::Const(val) => val.into(),
287 IntVal::Reference(re) => re.into(),
288 IntVal::Expr(expr) => expr.as_ref().clone(),
289 }
290 }
291}
292
293impl From<IntVal> for Moo<Expression> {
294 fn from(value: IntVal) -> Self {
295 match value {
296 IntVal::Const(val) => Moo::new(val.into()),
297 IntVal::Reference(re) => Moo::new(re.into()),
298 IntVal::Expr(expr) => expr,
299 }
300 }
301}
302
303impl std::ops::Neg for IntVal {
304 type Output = IntVal;
305
306 fn neg(self) -> Self::Output {
307 match self {
308 IntVal::Const(val) => IntVal::Const(-val),
309 IntVal::Reference(_) | IntVal::Expr(_) => {
310 IntVal::Expr(Moo::new(Expression::Neg(Metadata::new(), self.into())))
311 }
312 }
313 }
314}
315
316impl<T> std::ops::Add<T> for IntVal
317where
318 T: Into<Expression>,
319{
320 type Output = IntVal;
321
322 fn add(self, rhs: T) -> Self::Output {
323 let lhs: Expression = self.into();
324 let rhs: Expression = rhs.into();
325 let sum = matrix_expr!(lhs, rhs; domain_int!(1..));
326 IntVal::Expr(Moo::new(Expression::Sum(Metadata::new(), Moo::new(sum))))
327 }
328}
329
330impl Range<IntVal> {
331 pub fn resolve(&self) -> Option<Range<Int>> {
332 match self {
333 Range::Single(x) => Some(Range::Single(x.resolve()?)),
334 Range::Bounded(l, r) => Some(Range::Bounded(l.resolve()?, r.resolve()?)),
335 Range::UnboundedL(r) => Some(Range::UnboundedL(r.resolve()?)),
336 Range::UnboundedR(l) => Some(Range::UnboundedR(l.resolve()?)),
337 Range::Unbounded => Some(Range::Unbounded),
338 }
339 }
340}
341
342impl SetAttr<IntVal> {
343 pub fn resolve(&self) -> Option<SetAttr<Int>> {
344 Some(SetAttr {
345 size: self.size.resolve()?,
346 })
347 }
348}
349
350impl SequenceAttr<IntVal> {
351 pub fn resolve(&self) -> Option<SequenceAttr<Int>> {
352 Some(SequenceAttr {
353 size: self.size.resolve()?,
354 jectivity: self.jectivity.clone(),
355 })
356 }
357}
358
359impl MSetAttr<IntVal> {
360 pub fn resolve(&self) -> Option<MSetAttr<Int>> {
361 Some(MSetAttr {
362 size: self.size.resolve()?,
363 occurrence: self.occurrence.resolve()?,
364 })
365 }
366}
367
368impl PartitionAttr<IntVal> {
369 pub fn resolve(&self) -> Option<PartitionAttr<Int>> {
370 Some(PartitionAttr {
371 num_parts: self.num_parts.resolve()?,
372 part_len: self.part_len.resolve()?,
373 is_regular: self.is_regular,
374 })
375 }
376}
377
378impl FuncAttr<IntVal> {
379 pub fn resolve(&self) -> Option<FuncAttr<Int>> {
380 Some(FuncAttr {
381 size: self.size.resolve()?,
382 partiality: self.partiality.clone(),
383 jectivity: self.jectivity.clone(),
384 })
385 }
386}
387
388impl RelAttr<IntVal> {
389 pub fn resolve(&self) -> Option<RelAttr<Int>> {
390 Some(RelAttr {
391 size: self.size.resolve()?,
392 binary: self.binary.clone(),
393 })
394 }
395}
396
397#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Uniplate, Quine)]
398#[path_prefix(conjure_cp::ast)]
399pub struct FieldEntry {
400 pub name: Name,
401 pub domain: DomainPtr,
402}
403
404impl FieldEntry {
405 pub fn resolve(self) -> Option<FieldEntryGround> {
406 Some(FieldEntryGround {
407 name: self.name,
408 domain: self.domain.resolve()?,
409 })
410 }
411}
412
413#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
414#[path_prefix(conjure_cp::ast)]
415#[biplate(to=Expression)]
416#[biplate(to=Reference)]
417#[biplate(to=IntVal)]
418#[biplate(to=DomainPtr)]
419#[biplate(to=FieldEntry)]
420pub enum UnresolvedDomain {
421 Int(Vec<Range<IntVal>>),
422 Set(SetAttr<IntVal>, DomainPtr),
424 MSet(MSetAttr<IntVal>, DomainPtr),
425 Matrix(DomainPtr, Vec<DomainPtr>),
427 Tuple(Vec<DomainPtr>),
429 Sequence(SequenceAttr<IntVal>, DomainPtr),
430 #[polyquine_skip]
432 Reference(Reference),
433 Record(Vec<FieldEntry>),
435 Function(FuncAttr<IntVal>, DomainPtr, DomainPtr),
437 Variant(Vec<FieldEntry>),
439 Relation(RelAttr<IntVal>, Vec<DomainPtr>),
441 Partition(PartitionAttr<IntVal>, DomainPtr),
442}
443
444impl UnresolvedDomain {
445 pub fn resolve(&self) -> Option<GroundDomain> {
446 match self {
447 UnresolvedDomain::Int(rngs) => rngs
448 .iter()
449 .map(Range::<IntVal>::resolve)
450 .collect::<Option<_>>()
451 .map(GroundDomain::Int),
452 UnresolvedDomain::Set(attr, inner) => {
453 Some(GroundDomain::Set(attr.resolve()?, inner.resolve()?))
454 }
455 UnresolvedDomain::MSet(attr, inner) => {
456 Some(GroundDomain::MSet(attr.resolve()?, inner.resolve()?))
457 }
458 UnresolvedDomain::Partition(attr, inner) => {
459 Some(GroundDomain::Partition(attr.resolve()?, inner.resolve()?))
460 }
461 UnresolvedDomain::Matrix(inner, idx_doms) => {
462 let inner_gd = inner.resolve()?;
463 idx_doms
464 .iter()
465 .map(DomainPtr::resolve)
466 .collect::<Option<_>>()
467 .map(|idx| GroundDomain::Matrix(inner_gd, idx))
468 }
469 UnresolvedDomain::Sequence(attr, inner) => {
470 Some(GroundDomain::Sequence(attr.resolve()?, inner.resolve()?))
471 }
472 UnresolvedDomain::Tuple(inners) => inners
473 .iter()
474 .map(DomainPtr::resolve)
475 .collect::<Option<_>>()
476 .map(GroundDomain::Tuple),
477 UnresolvedDomain::Record(entries) => entries
478 .iter()
479 .map(|f| {
480 f.domain.resolve().map(|gd| FieldEntryGround {
481 name: f.name.clone(),
482 domain: gd,
483 })
484 })
485 .collect::<Option<_>>()
486 .map(GroundDomain::Record),
487 UnresolvedDomain::Reference(re) => re
488 .ptr
489 .as_domain_letting()
490 .unwrap_or_else(|| {
491 bug!("Reference domain should point to domain letting, but got {re}")
492 })
493 .resolve()
494 .map(Moo::unwrap_or_clone),
495 UnresolvedDomain::Function(attr, dom, cdom) => {
496 if let Some(attr_gd) = attr.resolve()
497 && let Some(dom_gd) = dom.resolve()
498 && let Some(cdom_gd) = cdom.resolve()
499 {
500 return Some(GroundDomain::Function(attr_gd, dom_gd, cdom_gd));
501 }
502 None
503 }
504 UnresolvedDomain::Variant(entries) => entries
505 .iter()
506 .map(|f| {
507 f.domain.resolve().map(|gd| FieldEntryGround {
508 name: f.name.clone(),
509 domain: gd,
510 })
511 })
512 .collect::<Option<_>>()
513 .map(GroundDomain::Variant),
514 UnresolvedDomain::Relation(attr, inners) => {
515 let resolved_attr = attr.resolve()?;
516 inners
517 .iter()
518 .map(DomainPtr::resolve)
519 .collect::<Option<_>>()
520 .map(|items| GroundDomain::Relation(resolved_attr, items))
521 }
522 }
523 }
524
525 pub(super) fn union_unresolved(
526 &self,
527 other: &UnresolvedDomain,
528 ) -> Result<UnresolvedDomain, DomainOpError> {
529 match (self, other) {
530 (UnresolvedDomain::Int(lhs), UnresolvedDomain::Int(rhs)) => {
531 let merged = lhs.iter().chain(rhs.iter()).cloned().collect_vec();
532 Ok(UnresolvedDomain::Int(merged))
533 }
534 (UnresolvedDomain::Int(_), _) | (_, UnresolvedDomain::Int(_)) => {
535 Err(DomainOpError::WrongType)
536 }
537 (UnresolvedDomain::Set(_, in1), UnresolvedDomain::Set(_, in2)) => {
538 Ok(UnresolvedDomain::Set(SetAttr::default(), in1.union(in2)?))
539 }
540 (UnresolvedDomain::Set(_, _), _) | (_, UnresolvedDomain::Set(_, _)) => {
541 Err(DomainOpError::WrongType)
542 }
543 (UnresolvedDomain::MSet(_, in1), UnresolvedDomain::MSet(_, in2)) => {
544 Ok(UnresolvedDomain::MSet(MSetAttr::default(), in1.union(in2)?))
545 }
546 (UnresolvedDomain::MSet(_, _), _) | (_, UnresolvedDomain::MSet(_, _)) => {
547 Err(DomainOpError::WrongType)
548 }
549 (UnresolvedDomain::Matrix(in1, idx1), UnresolvedDomain::Matrix(in2, idx2))
550 if idx1 == idx2 =>
551 {
552 Ok(UnresolvedDomain::Matrix(in1.union(in2)?, idx1.clone()))
553 }
554 (UnresolvedDomain::Matrix(_, _), _) | (_, UnresolvedDomain::Matrix(_, _)) => {
555 Err(DomainOpError::WrongType)
556 }
557 (UnresolvedDomain::Tuple(lhs), UnresolvedDomain::Tuple(rhs))
558 if lhs.len() == rhs.len() =>
559 {
560 let mut merged = Vec::new();
561 for (l, r) in zip(lhs, rhs) {
562 merged.push(l.union(r)?)
563 }
564 Ok(UnresolvedDomain::Tuple(merged))
565 }
566 (UnresolvedDomain::Tuple(_), _) | (_, UnresolvedDomain::Tuple(_)) => {
567 Err(DomainOpError::WrongType)
568 }
569 (UnresolvedDomain::Relation(_, in1s), UnresolvedDomain::Relation(_, in2s)) => {
570 let mut inners = Vec::new();
571 for (in1, in2) in in1s.iter().zip(in2s.iter()) {
572 inners.push(in1.union(in2)?)
573 }
574 Ok(UnresolvedDomain::Relation(RelAttr::default(), inners))
575 }
576 (UnresolvedDomain::Relation(_, _), _) | (_, UnresolvedDomain::Relation(_, _)) => {
577 Err(DomainOpError::WrongType)
578 }
579 (UnresolvedDomain::Reference(_), _) | (_, UnresolvedDomain::Reference(_)) => {
581 Err(DomainOpError::NotGround)
582 }
583 #[allow(unreachable_patterns)] (UnresolvedDomain::Record(_), _) | (_, UnresolvedDomain::Record(_)) => {
586 Err(DomainOpError::WrongType)
587 }
588 #[allow(unreachable_patterns)]
589 (UnresolvedDomain::Function(_, _, _), _) | (_, UnresolvedDomain::Function(_, _, _)) => {
591 Err(DomainOpError::WrongType)
592 }
593 #[allow(unreachable_patterns)]
594 (UnresolvedDomain::Partition(_, _), _) | (_, UnresolvedDomain::Partition(_, _)) => {
596 Err(DomainOpError::WrongType)
597 }
598 #[allow(unreachable_patterns)]
599 (UnresolvedDomain::Variant(_), _) | (_, UnresolvedDomain::Variant(_)) => {
600 Err(DomainOpError::WrongType)
601 }
602 #[allow(unreachable_patterns)]
603 (UnresolvedDomain::Sequence(_, _), _) | (_, UnresolvedDomain::Sequence(_, _)) => {
604 Err(DomainOpError::WrongType)
605 }
606 }
607 }
608
609 pub fn element_domain(&self) -> Option<DomainPtr> {
610 match self {
611 UnresolvedDomain::Set(_, inner_dom) => Some(inner_dom.clone()),
612 UnresolvedDomain::Sequence(_, inner_dom) => Some(inner_dom.clone()),
613 UnresolvedDomain::Matrix(_, _) => {
614 todo!("Unwrap one dimension of the domain")
615 }
616 _ => None,
617 }
618 }
619}
620
621impl Typeable for UnresolvedDomain {
622 fn return_type(&self) -> ReturnType {
623 match self {
624 UnresolvedDomain::Reference(re) => re.return_type(),
625 UnresolvedDomain::Int(_) => ReturnType::Int,
626 UnresolvedDomain::Set(_attr, inner) => ReturnType::Set(Box::new(inner.return_type())),
627 UnresolvedDomain::MSet(_attr, inner) => ReturnType::MSet(Box::new(inner.return_type())),
628 UnresolvedDomain::Partition(_, inner) => {
629 ReturnType::Partition(Box::new(inner.return_type()))
630 }
631 UnresolvedDomain::Sequence(_attr, inner) => {
632 ReturnType::Sequence(Box::new(inner.return_type()))
633 }
634 UnresolvedDomain::Matrix(inner, _idx) => {
635 ReturnType::Matrix(Box::new(inner.return_type()))
636 }
637 UnresolvedDomain::Tuple(inners) => {
638 let mut inner_types = Vec::new();
639 for inner in inners {
640 inner_types.push(inner.return_type());
641 }
642 ReturnType::Tuple(inner_types)
643 }
644 UnresolvedDomain::Record(entries) => {
645 let mut entry_types = Vec::new();
646 for entry in entries {
647 entry_types.push(entry.domain.return_type());
648 }
649 ReturnType::Record(entry_types)
650 }
651 UnresolvedDomain::Function(_, dom, cdom) => {
652 ReturnType::Function(Box::new(dom.return_type()), Box::new(cdom.return_type()))
653 }
654 UnresolvedDomain::Variant(entries) => {
655 let mut entry_types = Vec::new();
656 for entry in entries {
657 entry_types.push(entry.domain.return_type());
658 }
659 ReturnType::Variant(entry_types)
660 }
661 UnresolvedDomain::Relation(_, inners) => {
662 let mut inner_types = Vec::new();
663 for inner in inners {
664 inner_types.push(inner.return_type());
665 }
666 ReturnType::Relation(inner_types)
667 }
668 }
669 }
670}
671
672impl Display for UnresolvedDomain {
673 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
674 match &self {
675 UnresolvedDomain::Reference(re) => write!(f, "{re}"),
676 UnresolvedDomain::Int(ranges) => {
677 if ranges.iter().all(Range::is_lower_or_upper_bounded) {
678 let rngs: String = ranges.iter().map(|r| format!("{r}")).join(", ");
679 write!(f, "int({})", rngs)
680 } else {
681 write!(f, "int")
682 }
683 }
684 UnresolvedDomain::Set(attrs, inner_dom) => write!(f, "set {attrs} of {inner_dom}"),
685 UnresolvedDomain::MSet(attrs, inner_dom) => write!(f, "mset {attrs} of {inner_dom}"),
686 UnresolvedDomain::Partition(attrs, inner_dom) => {
687 write!(f, "partition {attrs} from {inner_dom}")
688 }
689 UnresolvedDomain::Sequence(attrs, inner_dom) => {
690 write!(f, "sequence {attrs} of {inner_dom}")
691 }
692 UnresolvedDomain::Matrix(value_domain, index_domains) => {
693 write!(
694 f,
695 "matrix indexed by {} of {value_domain}",
696 pretty_vec(&index_domains.iter().collect_vec())
697 )
698 }
699 UnresolvedDomain::Tuple(domains) => {
700 write!(f, "tuple ({})", &domains.iter().join(","))
701 }
702 UnresolvedDomain::Record(entries) => {
703 write!(
704 f,
705 "record {{{}}}",
706 entries
707 .iter()
708 .map(|entry| format!("{}: {}", entry.name, entry.domain))
709 .join(", ")
710 )
711 }
712 UnresolvedDomain::Function(attribute, domain, codomain) => {
713 write!(f, "function {} {} --> {} ", attribute, domain, codomain)
714 }
715 UnresolvedDomain::Variant(entries) => {
716 write!(
717 f,
718 "variant {{{}}}",
719 entries
720 .iter()
721 .map(|entry| format!("{}: {}", entry.name, entry.domain))
722 .join(", ")
723 )
724 }
725 UnresolvedDomain::Relation(attrs, domains) => {
726 write!(f, "relation {} of ({})", attrs, domains.iter().join(" * "))
727 }
728 }
729 }
730}