1use crate::ast::domains::{
2 attrs::{MSetAttr, PartitionAttr, PermutationAttr, SetAttr},
3 ground::{FieldGround, GroundDomain},
4 int_val::IntVal,
5 range::Range,
6 unresolved::{FieldUnresolved, UnresolvedDomain},
7};
8use crate::ast::{
9 DeclarationPtr, DomainOpError, Expression, Field, FuncAttr, Literal, Moo, Reference, RelAttr,
10 ReturnType, SequenceAttr, Typeable,
11};
12use itertools::Itertools;
13use polyquine::Quine;
14use serde::{Deserialize, Serialize};
15use std::fmt::{Display, Formatter};
16use std::thread_local;
17use uniplate::Uniplate;
18
19pub type Int = i32;
21
22pub const OXIDE_INT_MIN: Int = Int::MIN + 1;
27
28pub const OXIDE_INT_MAX: Int = Int::MAX;
30
31pub type DomainPtr = Moo<Domain>;
32
33impl DomainPtr {
34 pub fn resolve(&self) -> Result<Moo<GroundDomain>, DomainOpError> {
35 self.as_ref().resolve()
36 }
37
38 pub fn union(&self, other: &DomainPtr) -> Result<DomainPtr, DomainOpError> {
41 self.as_ref().union(other.as_ref()).map(DomainPtr::new)
42 }
43
44 pub fn intersect(&self, other: &DomainPtr) -> Result<DomainPtr, DomainOpError> {
47 self.as_ref().intersect(other.as_ref()).map(DomainPtr::new)
48 }
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
52#[biplate(to=DomainPtr)]
53#[biplate(to=GroundDomain)]
54#[biplate(to=UnresolvedDomain)]
55#[biplate(to=Expression)]
56#[biplate(to=Reference)]
57#[biplate(to=IntVal)]
58#[path_prefix(conjure_cp::ast)]
59pub enum Domain {
61 Ground(Moo<GroundDomain>),
63 Unresolved(Moo<UnresolvedDomain>),
65}
66
67pub trait HasDomain {
69 fn domain_of(&self) -> DomainPtr;
71}
72
73impl<T: HasDomain> Typeable for T {
74 fn return_type(&self) -> ReturnType {
75 self.domain_of().return_type()
76 }
77}
78
79thread_local! {
82 static BOOL_DOMAIN: DomainPtr =
83 Moo::new(Domain::Ground(Moo::new(GroundDomain::Bool)));
84}
85
86impl Domain {
87 pub fn bool() -> DomainPtr {
90 BOOL_DOMAIN.with(Clone::clone)
91 }
92
93 pub fn empty(ty: ReturnType) -> DomainPtr {
96 Moo::new(Domain::Ground(Moo::new(GroundDomain::Empty(ty))))
97 }
98
99 pub fn int<T>(ranges: Vec<T>) -> DomainPtr
103 where
104 T: Into<Range<IntVal>> + TryInto<Range<Int>> + Clone,
105 {
106 if let Ok(int_rngs) = ranges
107 .iter()
108 .cloned()
109 .map(TryInto::try_into)
110 .collect::<Result<Vec<_>, _>>()
111 {
112 return Domain::int_ground(int_rngs);
113 }
114 let unresolved_rngs: Vec<Range<IntVal>> = ranges.into_iter().map(Into::into).collect();
115 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Int(
116 unresolved_rngs,
117 ))))
118 }
119
120 pub fn int_from_values(values: Expression) -> DomainPtr {
125 if let Some(ranges) = int_ranges_from_constant_collection(&values) {
129 return Domain::int_ground(ranges);
130 }
131
132 Moo::new(Domain::Unresolved(Moo::new(
133 UnresolvedDomain::IntFromValues(Moo::new(values)),
134 )))
135 }
136
137 pub fn int_ground(ranges: Vec<Range<Int>>) -> DomainPtr {
139 let rngs = Range::squeeze(&ranges);
140 Moo::new(Domain::Ground(Moo::new(GroundDomain::Int(rngs))))
141 }
142
143 pub fn set<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
147 where
148 T: Into<SetAttr<IntVal>> + TryInto<SetAttr<Int>> + Clone,
149 {
150 if let Domain::Ground(gd) = inner_dom.as_ref()
151 && let Ok(int_attr) = attr.clone().try_into()
152 {
153 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Set(
154 int_attr,
155 gd.clone(),
156 ))));
157 }
158 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Set(
159 attr.into(),
160 inner_dom,
161 ))))
162 }
163
164 pub fn mset<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
166 where
167 T: Into<MSetAttr<IntVal>> + TryInto<MSetAttr<Int>> + Clone,
168 {
169 if let Domain::Ground(gd) = inner_dom.as_ref()
170 && let Ok(int_attr) = attr.clone().try_into()
171 {
172 return Moo::new(Domain::Ground(Moo::new(GroundDomain::MSet(
173 int_attr,
174 gd.clone(),
175 ))));
176 }
177 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::MSet(
178 attr.into(),
179 inner_dom,
180 ))))
181 }
182
183 pub fn matrix(inner_dom: DomainPtr, idx_doms: Vec<DomainPtr>) -> DomainPtr {
187 if let Domain::Ground(gd) = inner_dom.as_ref()
188 && let Some(idx_gds) = as_grounds(&idx_doms)
189 {
190 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Matrix(
191 gd.clone(),
192 idx_gds,
193 ))));
194 }
195 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Matrix(
196 inner_dom, idx_doms,
197 ))))
198 }
199
200 pub fn tuple(inner_doms: Vec<DomainPtr>) -> DomainPtr {
204 if let Some(inner_gds) = as_grounds(&inner_doms) {
205 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Tuple(inner_gds))));
206 }
207 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Tuple(
208 inner_doms,
209 ))))
210 }
211
212 pub fn record(entries: Vec<Field<DomainPtr>>) -> DomainPtr {
216 if let Ok(entries_gds) = entries.iter().cloned().map(TryInto::try_into).try_collect() {
217 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Record(entries_gds))));
218 }
219 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Record(
220 entries,
221 ))))
222 }
223
224 pub fn reference(ptr: DeclarationPtr) -> Option<DomainPtr> {
226 let _ = ptr.as_domain_letting()?;
227 Some(Moo::new(Domain::Unresolved(Moo::new(
228 UnresolvedDomain::Reference(Reference::new(ptr)),
229 ))))
230 }
231
232 pub fn partition<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
234 where
235 T: Into<PartitionAttr<IntVal>> + TryInto<PartitionAttr<Int>> + Clone,
236 {
237 if let Domain::Ground(gd) = inner_dom.as_ref()
238 && let Ok(int_attr) = attr.clone().try_into()
239 {
240 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Partition(
241 int_attr,
242 gd.clone(),
243 ))));
244 }
245 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Partition(
246 attr.into(),
247 inner_dom,
248 ))))
249 }
250
251 pub fn permutation<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
253 where
254 T: Into<PermutationAttr<IntVal>> + TryInto<PermutationAttr<Int>> + Clone,
255 {
256 if let Domain::Ground(gd) = inner_dom.as_ref()
257 && let Ok(int_attr) = attr.clone().try_into()
258 {
259 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Permutation(
260 int_attr,
261 gd.clone(),
262 ))));
263 }
264 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Permutation(
265 attr.into(),
266 inner_dom,
267 ))))
268 }
269
270 pub fn function<T>(attrs: T, dom: DomainPtr, cdom: DomainPtr) -> DomainPtr
272 where
273 T: Into<FuncAttr<IntVal>> + TryInto<FuncAttr<Int>> + Clone,
274 {
275 if let Ok(attrs_gd) = attrs.clone().try_into()
276 && let Some(dom_gd) = dom.as_ground()
277 && let Some(cdom_gd) = cdom.as_ground()
278 {
279 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Function(
280 attrs_gd,
281 Moo::new(dom_gd.clone()),
282 Moo::new(cdom_gd.clone()),
283 ))));
284 }
285
286 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Function(
287 attrs.into(),
288 dom,
289 cdom,
290 ))))
291 }
292
293 pub fn variant(entries: Vec<Field<DomainPtr>>) -> DomainPtr {
297 if let Ok(entries_gds) = entries.iter().cloned().map(TryInto::try_into).try_collect() {
298 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Variant(entries_gds))));
299 }
300 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Variant(
301 entries,
302 ))))
303 }
304
305 pub fn relation<T>(attrs: T, inner_doms: Vec<DomainPtr>) -> DomainPtr
309 where
310 T: Into<RelAttr<IntVal>> + TryInto<RelAttr<Int>> + Clone,
311 {
312 if let Ok(attrs_gd) = attrs.clone().try_into()
313 && let Some(doms_gd) = as_grounds(&inner_doms)
314 {
315 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Relation(
316 attrs_gd, doms_gd,
317 ))));
318 }
319
320 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Relation(
321 attrs.into(),
322 inner_doms,
323 ))))
324 }
325
326 pub fn sequence<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
328 where
329 T: Into<SequenceAttr<IntVal>> + TryInto<SequenceAttr<Int>> + Clone,
330 {
331 if let Domain::Ground(gd) = inner_dom.as_ref()
332 && let Ok(int_attr) = attr.clone().try_into()
333 {
334 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Sequence(
335 int_attr,
336 gd.clone(),
337 ))));
338 }
339 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Sequence(
340 attr.into(),
341 inner_dom,
342 ))))
343 }
344
345 pub fn resolve(&self) -> Result<Moo<GroundDomain>, DomainOpError> {
350 match self {
351 Domain::Ground(gd) => Ok(gd.clone()),
352 Domain::Unresolved(ud) => ud.resolve().map(Moo::new),
353 }
354 }
355
356 pub fn as_ground(&self) -> Option<&GroundDomain> {
360 match self {
361 Domain::Ground(gd) => Some(gd.as_ref()),
362 _ => None,
363 }
364 }
365
366 pub fn as_ground_mut(&mut self) -> Option<&mut GroundDomain> {
369 match self {
370 Domain::Ground(gd) => Some(Moo::<GroundDomain>::make_mut(gd)),
371 _ => None,
372 }
373 }
374
375 pub fn as_unresolved(&self) -> Option<&UnresolvedDomain> {
377 match self {
378 Domain::Unresolved(ud) => Some(ud.as_ref()),
379 _ => None,
380 }
381 }
382
383 pub fn as_unresolved_mut(&mut self) -> Option<&mut UnresolvedDomain> {
385 match self {
386 Domain::Unresolved(ud) => Some(Moo::<UnresolvedDomain>::make_mut(ud)),
387 _ => None,
388 }
389 }
390
391 pub fn as_dom_empty(&self) -> Option<&ReturnType> {
393 if let Some(GroundDomain::Empty(ty)) = self.as_ground() {
394 return Some(ty);
395 }
396 None
397 }
398
399 pub fn as_dom_empty_mut(&mut self) -> Option<&mut ReturnType> {
401 if let Some(GroundDomain::Empty(ty)) = self.as_ground_mut() {
402 return Some(ty);
403 }
404 None
405 }
406
407 pub fn is_bool(&self) -> bool {
409 self.return_type() == ReturnType::Bool
410 }
411
412 pub fn is_int(&self) -> bool {
414 self.return_type() == ReturnType::Int
415 }
416
417 pub fn as_int(&self) -> Option<Vec<Range<IntVal>>> {
420 if let Some(GroundDomain::Int(rngs)) = self.as_ground() {
421 return Some(rngs.iter().cloned().map(|r| r.into()).collect());
422 }
423 if let Some(UnresolvedDomain::Int(rngs)) = self.as_unresolved() {
424 return Some(rngs.clone());
425 }
426 None
427 }
428
429 pub fn as_int_mut(&mut self) -> Option<&mut Vec<Range<IntVal>>> {
432 if let Some(GroundDomain::Int(rngs_gds)) = self.as_ground() {
438 let rngs: Vec<Range<IntVal>> = rngs_gds.iter().cloned().map(|r| r.into()).collect();
439 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Int(rngs)))
440 }
441
442 if let Some(UnresolvedDomain::Int(rngs)) = self.as_unresolved_mut() {
443 return Some(rngs);
444 }
445 None
446 }
447
448 pub fn as_int_ground(&self) -> Option<&Vec<Range<Int>>> {
450 if let Some(GroundDomain::Int(rngs)) = self.as_ground() {
451 return Some(rngs);
452 }
453 None
454 }
455
456 pub fn as_int_ground_mut(&mut self) -> Option<&mut Vec<Range<Int>>> {
458 if let Some(GroundDomain::Int(rngs)) = self.as_ground_mut() {
459 return Some(rngs);
460 }
461 None
462 }
463
464 pub fn as_matrix(&self) -> Option<(DomainPtr, Vec<DomainPtr>)> {
467 if let Some(GroundDomain::Matrix(inner_dom_gd, idx_doms_gds)) = self.as_ground() {
468 let idx_doms: Vec<DomainPtr> = idx_doms_gds.iter().cloned().map(|d| d.into()).collect();
469 let inner_dom: DomainPtr = inner_dom_gd.clone().into();
470 return Some((inner_dom, idx_doms));
471 }
472 if let Some(UnresolvedDomain::Matrix(inner_dom, idx_doms)) = self.as_unresolved() {
473 return Some((inner_dom.clone(), idx_doms.clone()));
474 }
475 None
476 }
477
478 pub fn as_matrix_mut(&mut self) -> Option<(&mut DomainPtr, &mut Vec<DomainPtr>)> {
482 if let Some(GroundDomain::Matrix(inner_dom_gd, idx_doms_gds)) = self.as_ground() {
485 let inner_dom: DomainPtr = inner_dom_gd.clone().into();
486 let idx_doms: Vec<DomainPtr> = idx_doms_gds.iter().cloned().map(|d| d.into()).collect();
487 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Matrix(inner_dom, idx_doms)));
488 }
489
490 if let Some(UnresolvedDomain::Matrix(inner_dom, idx_doms)) = self.as_unresolved_mut() {
491 return Some((inner_dom, idx_doms));
492 }
493 None
494 }
495
496 pub fn as_matrix_ground(&self) -> Option<(&Moo<GroundDomain>, &Vec<Moo<GroundDomain>>)> {
498 if let Some(GroundDomain::Matrix(inner_dom, idx_doms)) = self.as_ground() {
499 return Some((inner_dom, idx_doms));
500 }
501 None
502 }
503
504 pub fn as_matrix_ground_mut(
506 &mut self,
507 ) -> Option<(&mut Moo<GroundDomain>, &mut Vec<Moo<GroundDomain>>)> {
508 if let Some(GroundDomain::Matrix(inner_dom, idx_doms)) = self.as_ground_mut() {
509 return Some((inner_dom, idx_doms));
510 }
511 None
512 }
513
514 pub fn as_set(&self) -> Option<(SetAttr<IntVal>, DomainPtr)> {
516 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground() {
517 return Some((attr.clone().into(), inner_dom.clone().into()));
518 }
519 if let Some(UnresolvedDomain::Set(attr, inner_dom)) = self.as_unresolved() {
520 return Some((attr.clone(), inner_dom.clone()));
521 }
522 None
523 }
524
525 pub fn as_set_mut(&mut self) -> Option<(&mut SetAttr<IntVal>, &mut DomainPtr)> {
528 if let Some(GroundDomain::Set(attr_gd, inner_dom_gd)) = self.as_ground() {
529 let attr: SetAttr<IntVal> = attr_gd.clone().into();
530 let inner_dom = inner_dom_gd.clone().into();
531 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Set(attr, inner_dom)));
532 }
533
534 if let Some(UnresolvedDomain::Set(attr, inner_dom)) = self.as_unresolved_mut() {
535 return Some((attr, inner_dom));
536 }
537 None
538 }
539
540 pub fn as_set_ground(&self) -> Option<(&SetAttr<Int>, &Moo<GroundDomain>)> {
542 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground() {
543 return Some((attr, inner_dom));
544 }
545 None
546 }
547
548 pub fn as_set_ground_mut(&mut self) -> Option<(&mut SetAttr<Int>, &mut Moo<GroundDomain>)> {
550 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground_mut() {
551 return Some((attr, inner_dom));
552 }
553 None
554 }
555
556 pub fn representation_preference(&self) -> Option<&str> {
563 if let Some(GroundDomain::Set(attr, _)) = self.as_ground() {
564 return attr.representation.as_deref();
565 }
566 if let Some(UnresolvedDomain::Set(attr, _)) = self.as_unresolved() {
567 return attr.representation.as_deref();
568 }
569 if let Some(GroundDomain::MSet(attr, _)) = self.as_ground() {
570 return attr.representation.as_deref();
571 }
572 if let Some(UnresolvedDomain::MSet(attr, _)) = self.as_unresolved() {
573 return attr.representation.as_deref();
574 }
575 if let Some(GroundDomain::Sequence(attr, _)) = self.as_ground() {
576 return attr.representation.as_deref();
577 }
578 if let Some(UnresolvedDomain::Sequence(attr, _)) = self.as_unresolved() {
579 return attr.representation.as_deref();
580 }
581 None
582 }
583
584 pub fn has_representation_preference(&self) -> bool {
586 if self.representation_preference().is_some() {
587 return true;
588 }
589 match self {
590 Domain::Ground(gd) => gd.has_representation_preference(),
591 Domain::Unresolved(ud) => ud.has_representation_preference(),
592 }
593 }
594
595 pub fn as_type_string(&self) -> String {
598 match self {
599 Domain::Ground(gd) => gd.as_type_string(),
600 Domain::Unresolved(ud) => ud.as_type_string(),
601 }
602 }
603
604 pub fn as_mset(&self) -> Option<(MSetAttr<IntVal>, DomainPtr)> {
606 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground() {
607 return Some((attr.clone().into(), inner_dom.clone().into()));
608 }
609 if let Some(UnresolvedDomain::MSet(attr, inner_dom)) = self.as_unresolved() {
610 return Some((attr.clone(), inner_dom.clone()));
611 }
612 None
613 }
614
615 pub fn as_mset_mut(&mut self) -> Option<(&mut MSetAttr<IntVal>, &mut DomainPtr)> {
618 if let Some(GroundDomain::MSet(attr_gd, inner_dom_gd)) = self.as_ground() {
619 let attr: MSetAttr<IntVal> = attr_gd.clone().into();
620 let inner_dom = inner_dom_gd.clone().into();
621 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::MSet(attr, inner_dom)));
622 }
623
624 if let Some(UnresolvedDomain::MSet(attr, inner_dom)) = self.as_unresolved_mut() {
625 return Some((attr, inner_dom));
626 }
627 None
628 }
629
630 pub fn as_mset_ground(&self) -> Option<(&MSetAttr<Int>, &Moo<GroundDomain>)> {
632 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground() {
633 return Some((attr, inner_dom));
634 }
635 None
636 }
637
638 pub fn as_mset_ground_mut(&mut self) -> Option<(&mut MSetAttr<Int>, &mut Moo<GroundDomain>)> {
640 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground_mut() {
641 return Some((attr, inner_dom));
642 }
643 None
644 }
645
646 pub fn as_tuple(&self) -> Option<Vec<DomainPtr>> {
648 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground() {
649 return Some(inner_doms.iter().cloned().map(|d| d.into()).collect());
650 }
651 if let Some(UnresolvedDomain::Tuple(inner_doms)) = self.as_unresolved() {
652 return Some(inner_doms.clone());
653 }
654 None
655 }
656
657 pub fn as_tuple_mut(&mut self) -> Option<&mut Vec<DomainPtr>> {
660 if let Some(GroundDomain::Tuple(inner_doms_gds)) = self.as_ground() {
661 let inner_doms: Vec<DomainPtr> =
662 inner_doms_gds.iter().cloned().map(|d| d.into()).collect();
663 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Tuple(inner_doms)));
664 }
665
666 if let Some(UnresolvedDomain::Tuple(inner_doms)) = self.as_unresolved_mut() {
667 return Some(inner_doms);
668 }
669 None
670 }
671
672 pub fn as_tuple_ground(&self) -> Option<&Vec<Moo<GroundDomain>>> {
674 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground() {
675 return Some(inner_doms);
676 }
677 None
678 }
679
680 pub fn as_tuple_ground_mut(&mut self) -> Option<&mut Vec<Moo<GroundDomain>>> {
682 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground_mut() {
683 return Some(inner_doms);
684 }
685 None
686 }
687
688 pub fn as_record(&self) -> Option<Vec<FieldUnresolved>> {
690 if let Some(GroundDomain::Record(record_entries)) = self.as_ground() {
691 return Some(record_entries.iter().cloned().map(|r| r.into()).collect());
692 }
693 if let Some(UnresolvedDomain::Record(record_entries)) = self.as_unresolved() {
694 return Some(record_entries.clone());
695 }
696 None
697 }
698
699 pub fn as_record_ground(&self) -> Option<&Vec<FieldGround>> {
701 if let Some(GroundDomain::Record(entries)) = self.as_ground() {
702 return Some(entries);
703 }
704 None
705 }
706
707 pub fn as_record_mut(&mut self) -> Option<&mut Vec<FieldUnresolved>> {
710 if let Some(GroundDomain::Record(entries_gds)) = self.as_ground() {
711 let entries: Vec<FieldUnresolved> =
712 entries_gds.iter().cloned().map(|r| r.into()).collect();
713 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Record(entries)));
714 }
715
716 if let Some(UnresolvedDomain::Record(entries_gds)) = self.as_unresolved_mut() {
717 return Some(entries_gds);
718 }
719 None
720 }
721
722 pub fn as_record_ground_mut(&mut self) -> Option<&mut Vec<FieldGround>> {
724 if let Some(GroundDomain::Record(entries)) = self.as_ground_mut() {
725 return Some(entries);
726 }
727 None
728 }
729
730 pub fn as_sequence(&self) -> Option<(SequenceAttr<IntVal>, Moo<Domain>)> {
732 if let Some(GroundDomain::Sequence(attrs, dom)) = self.as_ground() {
733 return Some((attrs.clone().into(), dom.clone().into()));
734 }
735 if let Some(UnresolvedDomain::Sequence(attrs, dom)) = self.as_unresolved() {
736 return Some((attrs.clone(), dom.clone()));
737 }
738 None
739 }
740
741 pub fn as_sequence_mut(&mut self) -> Option<(&mut SequenceAttr<IntVal>, &mut Moo<Domain>)> {
745 if let Some(GroundDomain::Sequence(attrs, dom)) = self.as_ground() {
746 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Sequence(
747 attrs.clone().into(),
748 dom.clone().into(),
749 )));
750 }
751
752 if let Some(UnresolvedDomain::Sequence(attrs, dom)) = self.as_unresolved_mut() {
753 return Some((attrs, dom));
754 }
755 None
756 }
757
758 pub fn as_function(&self) -> Option<(FuncAttr<IntVal>, Moo<Domain>, Moo<Domain>)> {
760 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
761 return Some((
762 attrs.clone().into(),
763 dom.clone().into(),
764 codom.clone().into(),
765 ));
766 }
767 if let Some(UnresolvedDomain::Function(attrs, dom, codom)) = self.as_unresolved() {
768 return Some((attrs.clone(), dom.clone(), codom.clone()));
769 }
770 None
771 }
772
773 pub fn as_function_mut(
777 &mut self,
778 ) -> Option<(&mut FuncAttr<IntVal>, &mut Moo<Domain>, &mut Moo<Domain>)> {
779 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
780 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Function(
781 attrs.clone().into(),
782 dom.clone().into(),
783 codom.clone().into(),
784 )));
785 }
786
787 if let Some(UnresolvedDomain::Function(attrs, dom, codom)) = self.as_unresolved_mut() {
788 return Some((attrs, dom, codom));
789 }
790 None
791 }
792
793 pub fn as_function_ground(
795 &self,
796 ) -> Option<(&FuncAttr, &Moo<GroundDomain>, &Moo<GroundDomain>)> {
797 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
798 return Some((attrs, dom, codom));
799 }
800 None
801 }
802
803 pub fn as_function_ground_mut(
805 &mut self,
806 ) -> Option<(
807 &mut FuncAttr,
808 &mut Moo<GroundDomain>,
809 &mut Moo<GroundDomain>,
810 )> {
811 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground_mut() {
812 return Some((attrs, dom, codom));
813 }
814 None
815 }
816
817 pub fn as_partition(&self) -> Option<(PartitionAttr<IntVal>, Moo<Domain>)> {
819 if let Some(GroundDomain::Partition(attrs, doms)) = self.as_ground() {
820 return Some((attrs.clone().into(), doms.clone().into()));
821 }
822 if let Some(UnresolvedDomain::Partition(attrs, doms)) = self.as_unresolved() {
823 return Some((attrs.clone(), doms.clone()));
824 }
825 None
826 }
827
828 pub fn as_partition_mut(&mut self) -> Option<(&mut PartitionAttr<IntVal>, &mut DomainPtr)> {
831 if let Some(GroundDomain::Partition(attr_gd, inner_dom_gd)) = self.as_ground() {
832 let attr: PartitionAttr<IntVal> = attr_gd.clone().into();
833 let inner_dom = inner_dom_gd.clone().into();
834 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Partition(attr, inner_dom)));
835 }
836
837 if let Some(UnresolvedDomain::Partition(attr, inner_dom)) = self.as_unresolved_mut() {
838 return Some((attr, inner_dom));
839 }
840 None
841 }
842
843 pub fn as_partition_ground(&self) -> Option<(&PartitionAttr<Int>, &Moo<GroundDomain>)> {
845 if let Some(GroundDomain::Partition(attr, inner_dom)) = self.as_ground() {
846 return Some((attr, inner_dom));
847 }
848 None
849 }
850
851 pub fn as_partition_ground_mut(
853 &mut self,
854 ) -> Option<(&mut PartitionAttr<Int>, &mut Moo<GroundDomain>)> {
855 if let Some(GroundDomain::Partition(attr, inner_dom)) = self.as_ground_mut() {
856 return Some((attr, inner_dom));
857 }
858 None
859 }
860
861 pub fn as_permutation(&self) -> Option<(PermutationAttr<IntVal>, Moo<Domain>)> {
863 if let Some(GroundDomain::Permutation(attrs, doms)) = self.as_ground() {
864 return Some((attrs.clone().into(), doms.clone().into()));
865 }
866 if let Some(UnresolvedDomain::Permutation(attrs, doms)) = self.as_unresolved() {
867 return Some((attrs.clone(), doms.clone()));
868 }
869 None
870 }
871
872 pub fn as_permutation_mut(&mut self) -> Option<(&mut PermutationAttr<IntVal>, &mut DomainPtr)> {
875 if let Some(GroundDomain::Permutation(attr_gd, inner_dom_gd)) = self.as_ground() {
876 let attr: PermutationAttr<IntVal> = attr_gd.clone().into();
877 let inner_dom = inner_dom_gd.clone().into();
878 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Permutation(attr, inner_dom)));
879 }
880
881 if let Some(UnresolvedDomain::Permutation(attr, inner_dom)) = self.as_unresolved_mut() {
882 return Some((attr, inner_dom));
883 }
884 None
885 }
886
887 pub fn as_permutation_ground(&self) -> Option<(&PermutationAttr<Int>, &Moo<GroundDomain>)> {
889 if let Some(GroundDomain::Permutation(attr, inner_dom)) = self.as_ground() {
890 return Some((attr, inner_dom));
891 }
892 None
893 }
894
895 pub fn as_permutation_ground_mut(
897 &mut self,
898 ) -> Option<(&mut PermutationAttr<Int>, &mut Moo<GroundDomain>)> {
899 if let Some(GroundDomain::Permutation(attr, inner_dom)) = self.as_ground_mut() {
900 return Some((attr, inner_dom));
901 }
902 None
903 }
904
905 pub fn as_variant(&self) -> Option<Vec<FieldUnresolved>> {
907 if let Some(GroundDomain::Variant(entries)) = self.as_ground() {
908 return Some(entries.iter().cloned().map(|r| r.into()).collect());
909 }
910 if let Some(UnresolvedDomain::Variant(entries)) = self.as_unresolved() {
911 return Some(entries.clone());
912 }
913 None
914 }
915
916 pub fn as_variant_ground(&self) -> Option<&Vec<FieldGround>> {
918 if let Some(GroundDomain::Variant(entries)) = self.as_ground() {
919 return Some(entries);
920 }
921 None
922 }
923
924 pub fn as_variant_mut(&mut self) -> Option<&mut Vec<FieldUnresolved>> {
927 if let Some(GroundDomain::Variant(entries_gds)) = self.as_ground() {
928 let entries: Vec<FieldUnresolved> =
929 entries_gds.iter().cloned().map(|r| r.into()).collect();
930 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Variant(entries)));
931 }
932
933 if let Some(UnresolvedDomain::Variant(entries_gds)) = self.as_unresolved_mut() {
934 return Some(entries_gds);
935 }
936 None
937 }
938
939 pub fn as_variant_ground_mut(&mut self) -> Option<&mut Vec<FieldGround>> {
941 if let Some(GroundDomain::Variant(entries)) = self.as_ground_mut() {
942 return Some(entries);
943 }
944 None
945 }
946
947 pub fn as_relation(&self) -> Option<(RelAttr<IntVal>, Vec<Moo<Domain>>)> {
949 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
950 return Some((
951 attrs.clone().into(),
952 doms.iter().cloned().map(|d| d.into()).collect(),
953 ));
954 }
955 if let Some(UnresolvedDomain::Relation(attrs, doms)) = self.as_unresolved() {
956 return Some((attrs.clone(), doms.clone()));
957 }
958 None
959 }
960
961 pub fn as_relation_mut(&mut self) -> Option<(&mut RelAttr<IntVal>, &mut Vec<Moo<Domain>>)> {
965 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
966 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Relation(
967 attrs.clone().into(),
968 doms.iter().cloned().map(|d| d.into()).collect(),
969 )));
970 }
971
972 if let Some(UnresolvedDomain::Relation(attrs, doms)) = self.as_unresolved_mut() {
973 return Some((attrs, doms));
974 }
975 None
976 }
977
978 pub fn as_relation_ground(&self) -> Option<(&RelAttr, &Vec<Moo<GroundDomain>>)> {
980 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
981 return Some((attrs, doms));
982 }
983 None
984 }
985
986 pub fn as_relation_ground_mut(
988 &mut self,
989 ) -> Option<(&mut RelAttr, &mut Vec<Moo<GroundDomain>>)> {
990 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground_mut() {
991 return Some((attrs, doms));
992 }
993 None
994 }
995
996 pub fn union(&self, other: &Domain) -> Result<Domain, DomainOpError> {
1001 if let Domain::Unresolved(domain) = self
1002 && let UnresolvedDomain::Reference(reference) = domain.as_ref()
1003 {
1004 let referenced_domain = reference.domain().unwrap_or_else(|| {
1005 crate::bug!("domain reference should point to a domain letting: {reference}")
1006 });
1007 return referenced_domain.as_ref().union(other);
1008 }
1009
1010 if let Domain::Unresolved(domain) = other
1011 && let UnresolvedDomain::Reference(reference) = domain.as_ref()
1012 {
1013 let referenced_domain = reference.domain().unwrap_or_else(|| {
1014 crate::bug!("domain reference should point to a domain letting: {reference}")
1015 });
1016 return self.union(referenced_domain.as_ref());
1017 }
1018
1019 match (self, other) {
1020 (Domain::Ground(a), Domain::Ground(b)) => Ok(Domain::Ground(Moo::new(a.union(b)?))),
1021 (Domain::Unresolved(a), Domain::Unresolved(b)) => {
1022 Ok(Domain::Unresolved(Moo::new(a.union_unresolved(b)?)))
1023 }
1024 (Domain::Unresolved(u), Domain::Ground(g))
1025 | (Domain::Ground(g), Domain::Unresolved(u)) => {
1026 if let GroundDomain::Empty(ty) = g.as_ref() {
1027 return if *ty == u.return_type() {
1028 Ok(Domain::Unresolved(u.clone()))
1029 } else {
1030 Err(DomainOpError::WrongType)
1031 };
1032 }
1033
1034 let ground_as_unresolved =
1035 UnresolvedDomain::from_ground(g).ok_or(DomainOpError::WrongType)?;
1036 Ok(Domain::Unresolved(Moo::new(
1037 u.union_unresolved(&ground_as_unresolved)?,
1038 )))
1039 }
1040 }
1041 }
1042
1043 pub fn intersect(&self, other: &Domain) -> Result<Domain, DomainOpError> {
1045 match (self, other) {
1046 (Domain::Ground(a), Domain::Ground(b)) => {
1047 a.intersect(b).map(|res| Domain::Ground(Moo::new(res)))
1048 }
1049 _ => Err(DomainOpError::NotGround),
1050 }
1051 }
1052
1053 pub fn values(&self) -> Result<impl Iterator<Item = Literal>, DomainOpError> {
1055 if let Some(gd) = self.as_ground() {
1056 return gd.values();
1057 }
1058 Err(DomainOpError::NotGround)
1059 }
1060
1061 pub fn length(&self) -> Result<u64, DomainOpError> {
1063 if let Some(gd) = self.as_ground() {
1064 return gd.length();
1065 }
1066 Err(DomainOpError::NotGround)
1067 }
1068 pub fn length_signed(&self) -> Result<i32, DomainOpError> {
1074 let gd = self.as_ground().ok_or(DomainOpError::NotGround)?;
1075 let len = gd.length()?;
1076 len.try_into().map_err(|_| DomainOpError::TooLarge)
1077 }
1078
1079 pub fn from_literal_vec(vals: &[Literal]) -> Result<DomainPtr, DomainOpError> {
1081 GroundDomain::from_literal_vec(vals).map(DomainPtr::from)
1082 }
1083
1084 pub fn contains(&self, lit: &Literal) -> Result<bool, DomainOpError> {
1086 if let Some(gd) = self.as_ground() {
1087 return gd.contains(lit);
1088 }
1089 Err(DomainOpError::NotGround)
1090 }
1091
1092 pub fn element_domain(&self) -> Option<DomainPtr> {
1093 match self {
1094 Domain::Ground(gd) => gd.element_domain().map(DomainPtr::from),
1095 Domain::Unresolved(ud) => ud.element_domain(),
1096 }
1097 }
1098}
1099
1100impl Typeable for Domain {
1101 fn return_type(&self) -> ReturnType {
1102 match self {
1103 Domain::Ground(dom) => dom.return_type(),
1104 Domain::Unresolved(dom) => dom.return_type(),
1105 }
1106 }
1107}
1108
1109impl Display for Domain {
1110 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1111 match &self {
1112 Domain::Ground(gd) => gd.fmt(f),
1113 Domain::Unresolved(ud) => ud.fmt(f),
1114 }
1115 }
1116}
1117
1118fn as_grounds(doms: &[DomainPtr]) -> Option<Vec<Moo<GroundDomain>>> {
1119 doms.iter()
1120 .map(|idx| match idx.as_ref() {
1121 Domain::Ground(idx_gd) => Some(idx_gd.clone()),
1122 _ => None,
1123 })
1124 .collect()
1125}
1126
1127#[cfg(test)]
1128mod tests {
1129 use super::*;
1130 use crate::ast::Name;
1131 use crate::{domain_int, range};
1132
1133 #[test]
1134 fn unresolved_int_domain_resolve_squeezes_ranges() {
1135 let domain = UnresolvedDomain::Int(vec![
1136 Range::Single(IntVal::Const(5)),
1137 Range::Bounded(IntVal::Const(3), IntVal::Const(7)),
1138 Range::Bounded(IntVal::Const(5), IntVal::Const(3)),
1139 Range::Single(IntVal::Const(7)),
1140 ]);
1141
1142 assert_eq!(
1143 domain.resolve(),
1144 Ok(GroundDomain::Int(vec![Range::Bounded(3, 7)]))
1145 );
1146 }
1147
1148 #[test]
1149 fn union_dereferences_domain_lettings() {
1150 let declaration = DeclarationPtr::new_domain_letting(
1151 Name::user("Alias"),
1152 Domain::int(vec![Range::Bounded(1, 3)]),
1153 );
1154 let alias = Domain::reference(declaration).unwrap();
1155
1156 assert_eq!(
1157 alias
1158 .union(&Domain::int(vec![Range::Bounded(5, 7)]))
1159 .unwrap()
1160 .resolve(),
1161 Ok(Moo::new(GroundDomain::Int(vec![
1162 Range::Bounded(1, 3),
1163 Range::Bounded(5, 7),
1164 ])))
1165 );
1166 }
1167
1168 #[test]
1169 fn union_preserves_symbolic_domain_bounds() {
1170 let upper_bound =
1171 DeclarationPtr::new_given(Name::user("n"), Domain::int(vec![Range::Bounded(1, 10)]));
1172 let symbolic_upper = IntVal::new_ref(&Reference::new(upper_bound)).unwrap();
1173 let symbolic_domain = Domain::int(vec![Range::Bounded(
1174 IntVal::Const(1),
1175 symbolic_upper.clone(),
1176 )]);
1177 let declaration = DeclarationPtr::new_domain_letting(Name::user("Alias"), symbolic_domain);
1178 let alias = Domain::reference(declaration).unwrap();
1179
1180 let union = alias.union(&Domain::int(vec![Range::Single(20)])).unwrap();
1181
1182 assert_eq!(
1183 union.as_int(),
1184 Some(vec![
1185 Range::Bounded(IntVal::Const(1), symbolic_upper),
1186 Range::Single(IntVal::Const(20)),
1187 ])
1188 );
1189 assert_eq!(union.resolve(), Err(DomainOpError::NotGround));
1190 }
1191
1192 #[test]
1193 fn test_negative_product() {
1194 let d1 = Domain::int(vec![Range::Bounded(-2, 1)]);
1195 let d2 = Domain::int(vec![Range::Bounded(-2, 1)]);
1196 let res = d1
1197 .as_ground()
1198 .unwrap()
1199 .apply_i32(|a, b| Some(a * b), d2.as_ground().unwrap())
1200 .unwrap();
1201
1202 assert!(matches!(res, GroundDomain::Int(_)));
1203 if let GroundDomain::Int(ranges) = res {
1204 assert!(!ranges.contains(&Range::Bounded(-4, 4)));
1205 }
1206 }
1207
1208 #[test]
1209 fn test_negative_div() {
1210 let d1 = GroundDomain::Int(vec![Range::Bounded(-2, 1)]);
1211 let d2 = GroundDomain::Int(vec![Range::Bounded(-2, 1)]);
1212 let res = d1
1213 .apply_i32(|a, b| if b != 0 { Some(a / b) } else { None }, &d2)
1214 .unwrap();
1215
1216 assert!(matches!(res, GroundDomain::Int(_)));
1217 if let GroundDomain::Int(ranges) = res {
1218 assert!(!ranges.contains(&Range::Bounded(-4, 4)));
1219 }
1220 }
1221
1222 #[test]
1223 fn test_length_basic() {
1224 assert_eq!(Domain::empty(ReturnType::Int).length(), Ok(0));
1225 assert_eq!(Domain::bool().length(), Ok(2));
1226 assert_eq!(domain_int!(1..3, 5, 7..9).length(), Ok(7));
1227 assert_eq!(
1228 domain_int!(1..2, 5..).length(),
1229 Err(DomainOpError::Unbounded)
1230 );
1231 }
1232 #[test]
1233 fn test_length_set_basic() {
1234 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..3));
1236 assert_eq!(s.length(), Ok(8));
1237
1238 let s = Domain::set(SetAttr::new_size(2), domain_int!(1..3));
1240 assert_eq!(s.length(), Ok(3));
1241
1242 let s = Domain::set(SetAttr::new_min_max_size(1, 2), domain_int!(1..3));
1244 assert_eq!(s.length(), Ok(6));
1245
1246 let s = Domain::set(SetAttr::new_min_size(1), domain_int!(1..3));
1248 assert_eq!(s.length(), Ok(7));
1249
1250 let s = Domain::set(SetAttr::new_max_size(2), domain_int!(1..3));
1252 assert_eq!(s.length(), Ok(7));
1253 }
1254
1255 #[test]
1256 fn test_set_representation_preference_display() {
1257 let s = Domain::set(
1258 SetAttr::new_max_size(3).with_representation("packed"),
1259 domain_int!(1..4),
1260 );
1261 assert_eq!(
1262 s.to_string(),
1263 "set (representation packed, maxSize 3) of int(1..4)"
1264 );
1265 assert_eq!(s.as_type_string(), "set (representation packed) of int");
1266 assert_eq!(s.representation_preference(), Some("packed"));
1267
1268 let nested = Domain::set(
1269 SetAttr::<IntVal>::default().with_representation("explicit"),
1270 Domain::set(
1271 SetAttr::<IntVal>::default().with_representation("occurrence"),
1272 domain_int!(1..2),
1273 ),
1274 );
1275 assert_eq!(
1276 nested.to_string(),
1277 "set (representation explicit) of set (representation occurrence) of int(1..2)"
1278 );
1279 assert_eq!(
1280 nested.as_type_string(),
1281 "set (representation explicit) of set (representation occurrence) of int"
1282 );
1283 }
1284
1285 #[test]
1286 fn test_mset_representation_preference_survives_nesting() {
1287 let mset = Domain::mset(
1288 MSetAttr::new_max_size(IntVal::Const(6)).with_representation("repetition"),
1289 domain_int!(1..9),
1290 );
1291 let nested = Domain::matrix(
1292 Domain::record(vec![Field {
1293 name: Name::user("before"),
1294 value: mset.clone(),
1295 }]),
1296 vec![domain_int!(1..2)],
1297 );
1298
1299 assert_eq!(mset.representation_preference(), Some("repetition"));
1300 assert_eq!(
1301 mset.as_type_string(),
1302 "mset (representation repetition) of int"
1303 );
1304 assert_eq!(
1305 mset.to_string(),
1306 "mset (representation repetition, maxSize 6) of int(1..9)"
1307 );
1308 assert!(nested.has_representation_preference());
1309 assert_eq!(
1310 nested.to_string(),
1311 "matrix indexed by [int(1..2)] of record {before: mset (representation repetition, maxSize 6) of int(1..9)}"
1312 );
1313 }
1314
1315 #[test]
1316 fn test_length_set_nested() {
1317 let s2 = Domain::set(
1324 SetAttr::new_max_size(2),
1325 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..2)),
1327 );
1328 assert_eq!(s2.length(), Ok(11));
1329 }
1330
1331 #[test]
1332 fn test_length_set_unbounded_inner() {
1333 let s2_bad = Domain::set(
1335 SetAttr::new_max_size(2),
1336 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..)),
1337 );
1338 assert_eq!(s2_bad.length(), Err(DomainOpError::Unbounded));
1339 }
1340
1341 #[test]
1342 fn test_length_set_overflow() {
1343 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..20));
1344 assert!(s.length().is_ok());
1345
1346 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..63));
1348 assert_eq!(s.length(), Err(DomainOpError::TooLarge));
1349 }
1350
1351 #[test]
1352 fn test_length_tuple() {
1353 let t = Domain::tuple(vec![domain_int!(1..3), Domain::bool()]);
1355 assert_eq!(t.length(), Ok(6));
1356 }
1357
1358 #[test]
1359 fn test_length_record() {
1360 let t = Domain::record(vec![
1362 Field {
1363 name: Name::user("a"),
1364 value: domain_int!(1..3),
1365 },
1366 Field {
1367 name: Name::user("b"),
1368 value: Domain::bool(),
1369 },
1370 ]);
1371 assert_eq!(t.length(), Ok(6));
1372 }
1373
1374 #[test]
1375 fn test_length_matrix_basic() {
1376 let m = Domain::matrix(Domain::bool(), vec![domain_int!(1..3)]);
1378 assert_eq!(m.length(), Ok(8));
1379
1380 let m = Domain::matrix(domain_int!(1..3), vec![domain_int!(1..2)]);
1382 assert_eq!(m.length(), Ok(9));
1383 }
1384
1385 #[test]
1386 fn test_length_matrix_2d() {
1387 let m = Domain::matrix(Domain::bool(), vec![domain_int!(1..2), domain_int!(1..3)]);
1389 assert_eq!(m.length(), Ok(64));
1390 }
1391
1392 #[test]
1393 fn test_length_matrix_of_sets() {
1394 let m = Domain::matrix(
1396 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..2)),
1397 vec![domain_int!(1..3)],
1398 );
1399 assert_eq!(m.length(), Ok(64));
1400 }
1401}
1402
1403fn int_ranges_from_constant_collection(values: &Expression) -> Option<Vec<Range<Int>>> {
1405 let values = crate::ast::eval::generator_values_from_expr(values)?;
1406 let mut ranges = Vec::with_capacity(values.len());
1407 for value in values {
1408 let crate::ast::Literal::Int(value) = value else {
1409 return None;
1410 };
1411 ranges.push(Range::Single(value));
1412 }
1413 Some(ranges)
1414}