1use super::attrs::SetAttr;
2use super::ground::GroundDomain;
3use super::range::Range;
4use super::unresolved::{IntVal, UnresolvedDomain};
5use crate::ast::domains::attrs::{MSetAttr, PartitionAttr};
6use crate::ast::{
7 DeclarationPtr, DomainOpError, Expression, FieldEntry, FieldEntryGround, FuncAttr, Literal,
8 Moo, Reference, RelAttr, ReturnType, SequenceAttr, Typeable,
9};
10use itertools::Itertools;
11use polyquine::Quine;
12use serde::{Deserialize, Serialize};
13use std::fmt::{Display, Formatter};
14use std::thread_local;
15use uniplate::Uniplate;
16
17pub type Int = i32;
19
20pub type DomainPtr = Moo<Domain>;
21
22impl DomainPtr {
23 pub fn resolve(&self) -> Option<Moo<GroundDomain>> {
24 self.as_ref().resolve()
25 }
26
27 pub fn union(&self, other: &DomainPtr) -> Result<DomainPtr, DomainOpError> {
30 self.as_ref().union(other.as_ref()).map(DomainPtr::new)
31 }
32
33 pub fn intersect(&self, other: &DomainPtr) -> Result<DomainPtr, DomainOpError> {
36 self.as_ref().intersect(other.as_ref()).map(DomainPtr::new)
37 }
38}
39
40impl From<Moo<GroundDomain>> for DomainPtr {
41 fn from(value: Moo<GroundDomain>) -> Self {
42 Moo::new(Domain::Ground(value))
43 }
44}
45
46impl From<Moo<UnresolvedDomain>> for DomainPtr {
47 fn from(value: Moo<UnresolvedDomain>) -> Self {
48 Moo::new(Domain::Unresolved(value))
49 }
50}
51
52impl From<GroundDomain> for DomainPtr {
53 fn from(value: GroundDomain) -> Self {
54 Moo::new(Domain::Ground(Moo::new(value)))
55 }
56}
57
58impl From<UnresolvedDomain> for DomainPtr {
59 fn from(value: UnresolvedDomain) -> Self {
60 Moo::new(Domain::Unresolved(Moo::new(value)))
61 }
62}
63
64#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
65#[biplate(to=DomainPtr)]
66#[biplate(to=GroundDomain)]
67#[biplate(to=UnresolvedDomain)]
68#[biplate(to=Expression)]
69#[biplate(to=Reference)]
70#[biplate(to=FieldEntry)]
71#[biplate(to=IntVal)]
72#[path_prefix(conjure_cp::ast)]
73pub enum Domain {
74 Ground(Moo<GroundDomain>),
76 Unresolved(Moo<UnresolvedDomain>),
78}
79
80pub trait HasDomain {
82 fn domain_of(&self) -> DomainPtr;
84}
85
86impl<T: HasDomain> Typeable for T {
87 fn return_type(&self) -> ReturnType {
88 self.domain_of().return_type()
89 }
90}
91
92thread_local! {
95 static BOOL_DOMAIN: DomainPtr =
96 Moo::new(Domain::Ground(Moo::new(GroundDomain::Bool)));
97}
98
99impl Domain {
100 pub fn bool() -> DomainPtr {
103 BOOL_DOMAIN.with(Clone::clone)
104 }
105
106 pub fn empty(ty: ReturnType) -> DomainPtr {
109 Moo::new(Domain::Ground(Moo::new(GroundDomain::Empty(ty))))
110 }
111
112 pub fn int<T>(ranges: Vec<T>) -> DomainPtr
116 where
117 T: Into<Range<IntVal>> + TryInto<Range<Int>> + Clone,
118 {
119 if let Ok(int_rngs) = ranges
120 .iter()
121 .cloned()
122 .map(TryInto::try_into)
123 .collect::<Result<Vec<_>, _>>()
124 {
125 return Domain::int_ground(int_rngs);
126 }
127 let unresolved_rngs: Vec<Range<IntVal>> = ranges.into_iter().map(Into::into).collect();
128 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Int(
129 unresolved_rngs,
130 ))))
131 }
132
133 pub fn int_ground(ranges: Vec<Range<Int>>) -> DomainPtr {
135 let rngs = Range::squeeze(&ranges);
136 Moo::new(Domain::Ground(Moo::new(GroundDomain::Int(rngs))))
137 }
138
139 pub fn set<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
143 where
144 T: Into<SetAttr<IntVal>> + TryInto<SetAttr<Int>> + Clone,
145 {
146 if let Domain::Ground(gd) = inner_dom.as_ref()
147 && let Ok(int_attr) = attr.clone().try_into()
148 {
149 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Set(
150 int_attr,
151 gd.clone(),
152 ))));
153 }
154 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Set(
155 attr.into(),
156 inner_dom,
157 ))))
158 }
159
160 pub fn mset<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
162 where
163 T: Into<MSetAttr<IntVal>> + TryInto<MSetAttr<Int>> + Clone,
164 {
165 if let Domain::Ground(gd) = inner_dom.as_ref()
166 && let Ok(int_attr) = attr.clone().try_into()
167 {
168 return Moo::new(Domain::Ground(Moo::new(GroundDomain::MSet(
169 int_attr,
170 gd.clone(),
171 ))));
172 }
173 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::MSet(
174 attr.into(),
175 inner_dom,
176 ))))
177 }
178
179 pub fn matrix(inner_dom: DomainPtr, idx_doms: Vec<DomainPtr>) -> DomainPtr {
183 if let Domain::Ground(gd) = inner_dom.as_ref()
184 && let Some(idx_gds) = as_grounds(&idx_doms)
185 {
186 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Matrix(
187 gd.clone(),
188 idx_gds,
189 ))));
190 }
191 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Matrix(
192 inner_dom, idx_doms,
193 ))))
194 }
195
196 pub fn tuple(inner_doms: Vec<DomainPtr>) -> DomainPtr {
200 if let Some(inner_gds) = as_grounds(&inner_doms) {
201 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Tuple(inner_gds))));
202 }
203 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Tuple(
204 inner_doms,
205 ))))
206 }
207
208 pub fn record(entries: Vec<FieldEntry>) -> DomainPtr {
212 if let Ok(entries_gds) = entries.iter().cloned().map(TryInto::try_into).try_collect() {
213 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Record(entries_gds))));
214 }
215 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Record(
216 entries,
217 ))))
218 }
219
220 pub fn reference(ptr: DeclarationPtr) -> Option<DomainPtr> {
222 let _ = ptr.as_domain_letting()?;
223 Some(Moo::new(Domain::Unresolved(Moo::new(
224 UnresolvedDomain::Reference(Reference::new(ptr)),
225 ))))
226 }
227
228 pub fn partition<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
230 where
231 T: Into<PartitionAttr<IntVal>> + TryInto<PartitionAttr<Int>> + Clone,
232 {
233 if let Domain::Ground(gd) = inner_dom.as_ref()
234 && let Ok(int_attr) = attr.clone().try_into()
235 {
236 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Partition(
237 int_attr,
238 gd.clone(),
239 ))));
240 }
241 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Partition(
242 attr.into(),
243 inner_dom,
244 ))))
245 }
246
247 pub fn function<T>(attrs: T, dom: DomainPtr, cdom: DomainPtr) -> DomainPtr
249 where
250 T: Into<FuncAttr<IntVal>> + TryInto<FuncAttr<Int>> + Clone,
251 {
252 if let Ok(attrs_gd) = attrs.clone().try_into()
253 && let Some(dom_gd) = dom.as_ground()
254 && let Some(cdom_gd) = cdom.as_ground()
255 {
256 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Function(
257 attrs_gd,
258 Moo::new(dom_gd.clone()),
259 Moo::new(cdom_gd.clone()),
260 ))));
261 }
262
263 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Function(
264 attrs.into(),
265 dom,
266 cdom,
267 ))))
268 }
269
270 pub fn variant(entries: Vec<FieldEntry>) -> DomainPtr {
274 if let Ok(entries_gds) = entries.iter().cloned().map(TryInto::try_into).try_collect() {
275 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Variant(entries_gds))));
276 }
277 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Variant(
278 entries,
279 ))))
280 }
281
282 pub fn relation<T>(attrs: T, inner_doms: Vec<DomainPtr>) -> DomainPtr
286 where
287 T: Into<RelAttr<IntVal>> + TryInto<RelAttr<Int>> + Clone,
288 {
289 if let Ok(attrs_gd) = attrs.clone().try_into()
290 && let Some(doms_gd) = as_grounds(&inner_doms)
291 {
292 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Relation(
293 attrs_gd, doms_gd,
294 ))));
295 }
296
297 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Relation(
298 attrs.into(),
299 inner_doms,
300 ))))
301 }
302
303 pub fn sequence<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
305 where
306 T: Into<SequenceAttr<IntVal>> + TryInto<SequenceAttr<Int>> + Clone,
307 {
308 if let Domain::Ground(gd) = inner_dom.as_ref()
309 && let Ok(int_attr) = attr.clone().try_into()
310 {
311 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Sequence(
312 int_attr,
313 gd.clone(),
314 ))));
315 }
316 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Sequence(
317 attr.into(),
318 inner_dom,
319 ))))
320 }
321
322 pub fn resolve(&self) -> Option<Moo<GroundDomain>> {
327 match self {
328 Domain::Ground(gd) => Some(gd.clone()),
329 Domain::Unresolved(ud) => ud.resolve().map(Moo::new),
330 }
331 }
332
333 pub fn as_ground(&self) -> Option<&GroundDomain> {
337 match self {
338 Domain::Ground(gd) => Some(gd.as_ref()),
339 _ => None,
340 }
341 }
342
343 pub fn as_ground_mut(&mut self) -> Option<&mut GroundDomain> {
346 match self {
347 Domain::Ground(gd) => Some(Moo::<GroundDomain>::make_mut(gd)),
348 _ => None,
349 }
350 }
351
352 pub fn as_unresolved(&self) -> Option<&UnresolvedDomain> {
354 match self {
355 Domain::Unresolved(ud) => Some(ud.as_ref()),
356 _ => None,
357 }
358 }
359
360 pub fn as_unresolved_mut(&mut self) -> Option<&mut UnresolvedDomain> {
362 match self {
363 Domain::Unresolved(ud) => Some(Moo::<UnresolvedDomain>::make_mut(ud)),
364 _ => None,
365 }
366 }
367
368 pub fn as_dom_empty(&self) -> Option<&ReturnType> {
370 if let Some(GroundDomain::Empty(ty)) = self.as_ground() {
371 return Some(ty);
372 }
373 None
374 }
375
376 pub fn as_dom_empty_mut(&mut self) -> Option<&mut ReturnType> {
378 if let Some(GroundDomain::Empty(ty)) = self.as_ground_mut() {
379 return Some(ty);
380 }
381 None
382 }
383
384 pub fn is_bool(&self) -> bool {
386 self.return_type() == ReturnType::Bool
387 }
388
389 pub fn is_int(&self) -> bool {
391 self.return_type() == ReturnType::Int
392 }
393
394 pub fn as_int(&self) -> Option<Vec<Range<IntVal>>> {
397 if let Some(GroundDomain::Int(rngs)) = self.as_ground() {
398 return Some(rngs.iter().cloned().map(|r| r.into()).collect());
399 }
400 if let Some(UnresolvedDomain::Int(rngs)) = self.as_unresolved() {
401 return Some(rngs.clone());
402 }
403 None
404 }
405
406 pub fn as_int_mut(&mut self) -> Option<&mut Vec<Range<IntVal>>> {
409 if let Some(GroundDomain::Int(rngs_gds)) = self.as_ground() {
415 let rngs: Vec<Range<IntVal>> = rngs_gds.iter().cloned().map(|r| r.into()).collect();
416 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Int(rngs)))
417 }
418
419 if let Some(UnresolvedDomain::Int(rngs)) = self.as_unresolved_mut() {
420 return Some(rngs);
421 }
422 None
423 }
424
425 pub fn as_int_ground(&self) -> Option<&Vec<Range<Int>>> {
427 if let Some(GroundDomain::Int(rngs)) = self.as_ground() {
428 return Some(rngs);
429 }
430 None
431 }
432
433 pub fn as_int_ground_mut(&mut self) -> Option<&mut Vec<Range<Int>>> {
435 if let Some(GroundDomain::Int(rngs)) = self.as_ground_mut() {
436 return Some(rngs);
437 }
438 None
439 }
440
441 pub fn as_matrix(&self) -> Option<(DomainPtr, Vec<DomainPtr>)> {
444 if let Some(GroundDomain::Matrix(inner_dom_gd, idx_doms_gds)) = self.as_ground() {
445 let idx_doms: Vec<DomainPtr> = idx_doms_gds.iter().cloned().map(|d| d.into()).collect();
446 let inner_dom: DomainPtr = inner_dom_gd.clone().into();
447 return Some((inner_dom, idx_doms));
448 }
449 if let Some(UnresolvedDomain::Matrix(inner_dom, idx_doms)) = self.as_unresolved() {
450 return Some((inner_dom.clone(), idx_doms.clone()));
451 }
452 None
453 }
454
455 pub fn as_matrix_mut(&mut self) -> Option<(&mut DomainPtr, &mut Vec<DomainPtr>)> {
459 if let Some(GroundDomain::Matrix(inner_dom_gd, idx_doms_gds)) = self.as_ground() {
462 let inner_dom: DomainPtr = inner_dom_gd.clone().into();
463 let idx_doms: Vec<DomainPtr> = idx_doms_gds.iter().cloned().map(|d| d.into()).collect();
464 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Matrix(inner_dom, idx_doms)));
465 }
466
467 if let Some(UnresolvedDomain::Matrix(inner_dom, idx_doms)) = self.as_unresolved_mut() {
468 return Some((inner_dom, idx_doms));
469 }
470 None
471 }
472
473 pub fn as_matrix_ground(&self) -> Option<(&Moo<GroundDomain>, &Vec<Moo<GroundDomain>>)> {
475 if let Some(GroundDomain::Matrix(inner_dom, idx_doms)) = self.as_ground() {
476 return Some((inner_dom, idx_doms));
477 }
478 None
479 }
480
481 pub fn as_matrix_ground_mut(
483 &mut self,
484 ) -> Option<(&mut Moo<GroundDomain>, &mut Vec<Moo<GroundDomain>>)> {
485 if let Some(GroundDomain::Matrix(inner_dom, idx_doms)) = self.as_ground_mut() {
486 return Some((inner_dom, idx_doms));
487 }
488 None
489 }
490
491 pub fn as_set(&self) -> Option<(SetAttr<IntVal>, DomainPtr)> {
493 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground() {
494 return Some((attr.clone().into(), inner_dom.clone().into()));
495 }
496 if let Some(UnresolvedDomain::Set(attr, inner_dom)) = self.as_unresolved() {
497 return Some((attr.clone(), inner_dom.clone()));
498 }
499 None
500 }
501
502 pub fn as_set_mut(&mut self) -> Option<(&mut SetAttr<IntVal>, &mut DomainPtr)> {
505 if let Some(GroundDomain::Set(attr_gd, inner_dom_gd)) = self.as_ground() {
506 let attr: SetAttr<IntVal> = attr_gd.clone().into();
507 let inner_dom = inner_dom_gd.clone().into();
508 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Set(attr, inner_dom)));
509 }
510
511 if let Some(UnresolvedDomain::Set(attr, inner_dom)) = self.as_unresolved_mut() {
512 return Some((attr, inner_dom));
513 }
514 None
515 }
516
517 pub fn as_set_ground(&self) -> Option<(&SetAttr<Int>, &Moo<GroundDomain>)> {
519 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground() {
520 return Some((attr, inner_dom));
521 }
522 None
523 }
524
525 pub fn as_set_ground_mut(&mut self) -> Option<(&mut SetAttr<Int>, &mut Moo<GroundDomain>)> {
527 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground_mut() {
528 return Some((attr, inner_dom));
529 }
530 None
531 }
532
533 pub fn as_mset(&self) -> Option<(MSetAttr<IntVal>, DomainPtr)> {
535 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground() {
536 return Some((attr.clone().into(), inner_dom.clone().into()));
537 }
538 if let Some(UnresolvedDomain::MSet(attr, inner_dom)) = self.as_unresolved() {
539 return Some((attr.clone(), inner_dom.clone()));
540 }
541 None
542 }
543
544 pub fn as_mset_mut(&mut self) -> Option<(&mut MSetAttr<IntVal>, &mut DomainPtr)> {
547 if let Some(GroundDomain::MSet(attr_gd, inner_dom_gd)) = self.as_ground() {
548 let attr: MSetAttr<IntVal> = attr_gd.clone().into();
549 let inner_dom = inner_dom_gd.clone().into();
550 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::MSet(attr, inner_dom)));
551 }
552
553 if let Some(UnresolvedDomain::MSet(attr, inner_dom)) = self.as_unresolved_mut() {
554 return Some((attr, inner_dom));
555 }
556 None
557 }
558
559 pub fn as_mset_ground(&self) -> Option<(&MSetAttr<Int>, &Moo<GroundDomain>)> {
561 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground() {
562 return Some((attr, inner_dom));
563 }
564 None
565 }
566
567 pub fn as_mset_ground_mut(&mut self) -> Option<(&mut MSetAttr<Int>, &mut Moo<GroundDomain>)> {
569 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground_mut() {
570 return Some((attr, inner_dom));
571 }
572 None
573 }
574
575 pub fn as_tuple(&self) -> Option<Vec<DomainPtr>> {
577 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground() {
578 return Some(inner_doms.iter().cloned().map(|d| d.into()).collect());
579 }
580 if let Some(UnresolvedDomain::Tuple(inner_doms)) = self.as_unresolved() {
581 return Some(inner_doms.clone());
582 }
583 None
584 }
585
586 pub fn as_tuple_mut(&mut self) -> Option<&mut Vec<DomainPtr>> {
589 if let Some(GroundDomain::Tuple(inner_doms_gds)) = self.as_ground() {
590 let inner_doms: Vec<DomainPtr> =
591 inner_doms_gds.iter().cloned().map(|d| d.into()).collect();
592 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Tuple(inner_doms)));
593 }
594
595 if let Some(UnresolvedDomain::Tuple(inner_doms)) = self.as_unresolved_mut() {
596 return Some(inner_doms);
597 }
598 None
599 }
600
601 pub fn as_tuple_ground(&self) -> Option<&Vec<Moo<GroundDomain>>> {
603 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground() {
604 return Some(inner_doms);
605 }
606 None
607 }
608
609 pub fn as_tuple_ground_mut(&mut self) -> Option<&mut Vec<Moo<GroundDomain>>> {
611 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground_mut() {
612 return Some(inner_doms);
613 }
614 None
615 }
616
617 pub fn as_record(&self) -> Option<Vec<FieldEntry>> {
619 if let Some(GroundDomain::Record(record_entries)) = self.as_ground() {
620 return Some(record_entries.iter().cloned().map(|r| r.into()).collect());
621 }
622 if let Some(UnresolvedDomain::Record(record_entries)) = self.as_unresolved() {
623 return Some(record_entries.clone());
624 }
625 None
626 }
627
628 pub fn as_record_ground(&self) -> Option<&Vec<FieldEntryGround>> {
630 if let Some(GroundDomain::Record(entries)) = self.as_ground() {
631 return Some(entries);
632 }
633 None
634 }
635
636 pub fn as_record_mut(&mut self) -> Option<&mut Vec<FieldEntry>> {
639 if let Some(GroundDomain::Record(entries_gds)) = self.as_ground() {
640 let entries: Vec<FieldEntry> = entries_gds.iter().cloned().map(|r| r.into()).collect();
641 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Record(entries)));
642 }
643
644 if let Some(UnresolvedDomain::Record(entries_gds)) = self.as_unresolved_mut() {
645 return Some(entries_gds);
646 }
647 None
648 }
649
650 pub fn as_record_ground_mut(&mut self) -> Option<&mut Vec<FieldEntryGround>> {
652 if let Some(GroundDomain::Record(entries)) = self.as_ground_mut() {
653 return Some(entries);
654 }
655 None
656 }
657
658 pub fn as_sequence(&self) -> Option<(SequenceAttr<IntVal>, Moo<Domain>)> {
660 if let Some(GroundDomain::Sequence(attrs, dom)) = self.as_ground() {
661 return Some((attrs.clone().into(), dom.clone().into()));
662 }
663 if let Some(UnresolvedDomain::Sequence(attrs, dom)) = self.as_unresolved() {
664 return Some((attrs.clone(), dom.clone()));
665 }
666 None
667 }
668
669 pub fn as_sequence_mut(&mut self) -> Option<(&mut SequenceAttr<IntVal>, &mut Moo<Domain>)> {
673 if let Some(GroundDomain::Sequence(attrs, dom)) = self.as_ground() {
674 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Sequence(
675 attrs.clone().into(),
676 dom.clone().into(),
677 )));
678 }
679
680 if let Some(UnresolvedDomain::Sequence(attrs, dom)) = self.as_unresolved_mut() {
681 return Some((attrs, dom));
682 }
683 None
684 }
685
686 pub fn as_function(&self) -> Option<(FuncAttr<IntVal>, Moo<Domain>, Moo<Domain>)> {
688 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
689 return Some((
690 attrs.clone().into(),
691 dom.clone().into(),
692 codom.clone().into(),
693 ));
694 }
695 if let Some(UnresolvedDomain::Function(attrs, dom, codom)) = self.as_unresolved() {
696 return Some((attrs.clone(), dom.clone(), codom.clone()));
697 }
698 None
699 }
700
701 pub fn as_function_mut(
705 &mut self,
706 ) -> Option<(&mut FuncAttr<IntVal>, &mut Moo<Domain>, &mut Moo<Domain>)> {
707 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
708 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Function(
709 attrs.clone().into(),
710 dom.clone().into(),
711 codom.clone().into(),
712 )));
713 }
714
715 if let Some(UnresolvedDomain::Function(attrs, dom, codom)) = self.as_unresolved_mut() {
716 return Some((attrs, dom, codom));
717 }
718 None
719 }
720
721 pub fn as_function_ground(
723 &self,
724 ) -> Option<(&FuncAttr, &Moo<GroundDomain>, &Moo<GroundDomain>)> {
725 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
726 return Some((attrs, dom, codom));
727 }
728 None
729 }
730
731 pub fn as_function_ground_mut(
733 &mut self,
734 ) -> Option<(
735 &mut FuncAttr,
736 &mut Moo<GroundDomain>,
737 &mut Moo<GroundDomain>,
738 )> {
739 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground_mut() {
740 return Some((attrs, dom, codom));
741 }
742 None
743 }
744
745 pub fn as_partition(&self) -> Option<(PartitionAttr<IntVal>, Moo<Domain>)> {
747 if let Some(GroundDomain::Partition(attrs, doms)) = self.as_ground() {
748 return Some((attrs.clone().into(), doms.clone().into()));
749 }
750 if let Some(UnresolvedDomain::Partition(attrs, doms)) = self.as_unresolved() {
751 return Some((attrs.clone(), doms.clone()));
752 }
753 None
754 }
755
756 pub fn as_partition_mut(&mut self) -> Option<(&mut PartitionAttr<IntVal>, &mut DomainPtr)> {
759 if let Some(GroundDomain::Partition(attr_gd, inner_dom_gd)) = self.as_ground() {
760 let attr: PartitionAttr<IntVal> = attr_gd.clone().into();
761 let inner_dom = inner_dom_gd.clone().into();
762 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Partition(attr, inner_dom)));
763 }
764
765 if let Some(UnresolvedDomain::Partition(attr, inner_dom)) = self.as_unresolved_mut() {
766 return Some((attr, inner_dom));
767 }
768 None
769 }
770
771 pub fn as_partition_ground(&self) -> Option<(&PartitionAttr<Int>, &Moo<GroundDomain>)> {
773 if let Some(GroundDomain::Partition(attr, inner_dom)) = self.as_ground() {
774 return Some((attr, inner_dom));
775 }
776 None
777 }
778
779 pub fn as_partition_ground_mut(
781 &mut self,
782 ) -> Option<(&mut PartitionAttr<Int>, &mut Moo<GroundDomain>)> {
783 if let Some(GroundDomain::Partition(attr, inner_dom)) = self.as_ground_mut() {
784 return Some((attr, inner_dom));
785 }
786 None
787 }
788
789 pub fn as_variant(&self) -> Option<Vec<FieldEntry>> {
791 if let Some(GroundDomain::Variant(entries)) = self.as_ground() {
792 return Some(entries.iter().cloned().map(|r| r.into()).collect());
793 }
794 if let Some(UnresolvedDomain::Variant(entries)) = self.as_unresolved() {
795 return Some(entries.clone());
796 }
797 None
798 }
799
800 pub fn as_variant_ground(&self) -> Option<&Vec<FieldEntryGround>> {
802 if let Some(GroundDomain::Variant(entries)) = self.as_ground() {
803 return Some(entries);
804 }
805 None
806 }
807
808 pub fn as_variant_mut(&mut self) -> Option<&mut Vec<FieldEntry>> {
811 if let Some(GroundDomain::Variant(entries_gds)) = self.as_ground() {
812 let entries: Vec<FieldEntry> = entries_gds.iter().cloned().map(|r| r.into()).collect();
813 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Variant(entries)));
814 }
815
816 if let Some(UnresolvedDomain::Variant(entries_gds)) = self.as_unresolved_mut() {
817 return Some(entries_gds);
818 }
819 None
820 }
821
822 pub fn as_variant_ground_mut(&mut self) -> Option<&mut Vec<FieldEntryGround>> {
824 if let Some(GroundDomain::Variant(entries)) = self.as_ground_mut() {
825 return Some(entries);
826 }
827 None
828 }
829
830 pub fn as_relation(&self) -> Option<(RelAttr<IntVal>, Vec<Moo<Domain>>)> {
832 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
833 return Some((
834 attrs.clone().into(),
835 doms.iter().cloned().map(|d| d.into()).collect(),
836 ));
837 }
838 if let Some(UnresolvedDomain::Relation(attrs, doms)) = self.as_unresolved() {
839 return Some((attrs.clone(), doms.clone()));
840 }
841 None
842 }
843
844 pub fn as_relation_mut(&mut self) -> Option<(&mut RelAttr<IntVal>, &mut Vec<Moo<Domain>>)> {
848 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
849 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Relation(
850 attrs.clone().into(),
851 doms.iter().cloned().map(|d| d.into()).collect(),
852 )));
853 }
854
855 if let Some(UnresolvedDomain::Relation(attrs, doms)) = self.as_unresolved_mut() {
856 return Some((attrs, doms));
857 }
858 None
859 }
860
861 pub fn as_relation_ground(&self) -> Option<(&RelAttr, &Vec<Moo<GroundDomain>>)> {
863 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
864 return Some((attrs, doms));
865 }
866 None
867 }
868
869 pub fn as_relation_ground_mut(
871 &mut self,
872 ) -> Option<(&mut RelAttr, &mut Vec<Moo<GroundDomain>>)> {
873 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground_mut() {
874 return Some((attrs, doms));
875 }
876 None
877 }
878
879 pub fn union(&self, other: &Domain) -> Result<Domain, DomainOpError> {
881 match (self, other) {
882 (Domain::Ground(a), Domain::Ground(b)) => Ok(Domain::Ground(Moo::new(a.union(b)?))),
883 (Domain::Unresolved(a), Domain::Unresolved(b)) => {
884 Ok(Domain::Unresolved(Moo::new(a.union_unresolved(b)?)))
885 }
886 (Domain::Unresolved(u), Domain::Ground(g))
887 | (Domain::Ground(g), Domain::Unresolved(u)) => {
888 todo!("Union of unresolved domain {u} and ground domain {g} is not yet implemented")
889 }
890 }
891 }
892
893 pub fn intersect(&self, other: &Domain) -> Result<Domain, DomainOpError> {
895 match (self, other) {
896 (Domain::Ground(a), Domain::Ground(b)) => {
897 a.intersect(b).map(|res| Domain::Ground(Moo::new(res)))
898 }
899 _ => Err(DomainOpError::NotGround),
900 }
901 }
902
903 pub fn values(&self) -> Result<impl Iterator<Item = Literal>, DomainOpError> {
905 if let Some(gd) = self.as_ground() {
906 return gd.values();
907 }
908 Err(DomainOpError::NotGround)
909 }
910
911 pub fn length(&self) -> Result<u64, DomainOpError> {
913 if let Some(gd) = self.as_ground() {
914 return gd.length();
915 }
916 Err(DomainOpError::NotGround)
917 }
918 pub fn length_signed(&self) -> Result<i32, DomainOpError> {
924 let gd = self.as_ground().ok_or(DomainOpError::NotGround)?;
925 let len = gd.length()?;
926 len.try_into().map_err(|_| DomainOpError::TooLarge)
927 }
928
929 pub fn from_literal_vec(vals: &[Literal]) -> Result<DomainPtr, DomainOpError> {
931 GroundDomain::from_literal_vec(vals).map(DomainPtr::from)
932 }
933
934 pub fn contains(&self, lit: &Literal) -> Result<bool, DomainOpError> {
936 if let Some(gd) = self.as_ground() {
937 return gd.contains(lit);
938 }
939 Err(DomainOpError::NotGround)
940 }
941
942 pub fn element_domain(&self) -> Option<DomainPtr> {
943 match self {
944 Domain::Ground(gd) => gd.element_domain().map(DomainPtr::from),
945 Domain::Unresolved(ud) => ud.element_domain(),
946 }
947 }
948}
949
950impl Typeable for Domain {
951 fn return_type(&self) -> ReturnType {
952 match self {
953 Domain::Ground(dom) => dom.return_type(),
954 Domain::Unresolved(dom) => dom.return_type(),
955 }
956 }
957}
958
959impl Display for Domain {
960 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
961 match &self {
962 Domain::Ground(gd) => gd.fmt(f),
963 Domain::Unresolved(ud) => ud.fmt(f),
964 }
965 }
966}
967
968fn as_grounds(doms: &[DomainPtr]) -> Option<Vec<Moo<GroundDomain>>> {
969 doms.iter()
970 .map(|idx| match idx.as_ref() {
971 Domain::Ground(idx_gd) => Some(idx_gd.clone()),
972 _ => None,
973 })
974 .collect()
975}
976
977#[cfg(test)]
978mod tests {
979 use super::*;
980 use crate::ast::Name;
981 use crate::{domain_int, range};
982
983 #[test]
984 fn test_negative_product() {
985 let d1 = Domain::int(vec![Range::Bounded(-2, 1)]);
986 let d2 = Domain::int(vec![Range::Bounded(-2, 1)]);
987 let res = d1
988 .as_ground()
989 .unwrap()
990 .apply_i32(|a, b| Some(a * b), d2.as_ground().unwrap())
991 .unwrap();
992
993 assert!(matches!(res, GroundDomain::Int(_)));
994 if let GroundDomain::Int(ranges) = res {
995 assert!(!ranges.contains(&Range::Bounded(-4, 4)));
996 }
997 }
998
999 #[test]
1000 fn test_negative_div() {
1001 let d1 = GroundDomain::Int(vec![Range::Bounded(-2, 1)]);
1002 let d2 = GroundDomain::Int(vec![Range::Bounded(-2, 1)]);
1003 let res = d1
1004 .apply_i32(|a, b| if b != 0 { Some(a / b) } else { None }, &d2)
1005 .unwrap();
1006
1007 assert!(matches!(res, GroundDomain::Int(_)));
1008 if let GroundDomain::Int(ranges) = res {
1009 assert!(!ranges.contains(&Range::Bounded(-4, 4)));
1010 }
1011 }
1012
1013 #[test]
1014 fn test_length_basic() {
1015 assert_eq!(Domain::empty(ReturnType::Int).length(), Ok(0));
1016 assert_eq!(Domain::bool().length(), Ok(2));
1017 assert_eq!(domain_int!(1..3, 5, 7..9).length(), Ok(7));
1018 assert_eq!(
1019 domain_int!(1..2, 5..).length(),
1020 Err(DomainOpError::Unbounded)
1021 );
1022 }
1023 #[test]
1024 fn test_length_set_basic() {
1025 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..3));
1027 assert_eq!(s.length(), Ok(8));
1028
1029 let s = Domain::set(SetAttr::new_size(2), domain_int!(1..3));
1031 assert_eq!(s.length(), Ok(3));
1032
1033 let s = Domain::set(SetAttr::new_min_max_size(1, 2), domain_int!(1..3));
1035 assert_eq!(s.length(), Ok(6));
1036
1037 let s = Domain::set(SetAttr::new_min_size(1), domain_int!(1..3));
1039 assert_eq!(s.length(), Ok(7));
1040
1041 let s = Domain::set(SetAttr::new_max_size(2), domain_int!(1..3));
1043 assert_eq!(s.length(), Ok(7));
1044 }
1045
1046 #[test]
1047 fn test_length_set_nested() {
1048 let s2 = Domain::set(
1055 SetAttr::new_max_size(2),
1056 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..2)),
1058 );
1059 assert_eq!(s2.length(), Ok(11));
1060 }
1061
1062 #[test]
1063 fn test_length_set_unbounded_inner() {
1064 let s2_bad = Domain::set(
1066 SetAttr::new_max_size(2),
1067 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..)),
1068 );
1069 assert_eq!(s2_bad.length(), Err(DomainOpError::Unbounded));
1070 }
1071
1072 #[test]
1073 fn test_length_set_overflow() {
1074 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..20));
1075 assert!(s.length().is_ok());
1076
1077 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..63));
1079 assert_eq!(s.length(), Err(DomainOpError::TooLarge));
1080 }
1081
1082 #[test]
1083 fn test_length_tuple() {
1084 let t = Domain::tuple(vec![domain_int!(1..3), Domain::bool()]);
1086 assert_eq!(t.length(), Ok(6));
1087 }
1088
1089 #[test]
1090 fn test_length_record() {
1091 let t = Domain::record(vec![
1093 FieldEntry {
1094 name: Name::user("a"),
1095 domain: domain_int!(1..3),
1096 },
1097 FieldEntry {
1098 name: Name::user("b"),
1099 domain: Domain::bool(),
1100 },
1101 ]);
1102 assert_eq!(t.length(), Ok(6));
1103 }
1104
1105 #[test]
1106 fn test_length_matrix_basic() {
1107 let m = Domain::matrix(Domain::bool(), vec![domain_int!(1..3)]);
1109 assert_eq!(m.length(), Ok(8));
1110
1111 let m = Domain::matrix(domain_int!(1..3), vec![domain_int!(1..2)]);
1113 assert_eq!(m.length(), Ok(9));
1114 }
1115
1116 #[test]
1117 fn test_length_matrix_2d() {
1118 let m = Domain::matrix(Domain::bool(), vec![domain_int!(1..2), domain_int!(1..3)]);
1120 assert_eq!(m.length(), Ok(64));
1121 }
1122
1123 #[test]
1124 fn test_length_matrix_of_sets() {
1125 let m = Domain::matrix(
1127 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..2)),
1128 vec![domain_int!(1..3)],
1129 );
1130 assert_eq!(m.length(), Ok(64));
1131 }
1132}