1use crate::ast::domains::{
2 attrs::{MSetAttr, PartitionAttr, 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 type DomainPtr = Moo<Domain>;
23
24impl DomainPtr {
25 pub fn resolve(&self) -> Result<Moo<GroundDomain>, DomainOpError> {
26 self.as_ref().resolve()
27 }
28
29 pub fn union(&self, other: &DomainPtr) -> Result<DomainPtr, DomainOpError> {
32 self.as_ref().union(other.as_ref()).map(DomainPtr::new)
33 }
34
35 pub fn intersect(&self, other: &DomainPtr) -> Result<DomainPtr, DomainOpError> {
38 self.as_ref().intersect(other.as_ref()).map(DomainPtr::new)
39 }
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
43#[biplate(to=DomainPtr)]
44#[biplate(to=GroundDomain)]
45#[biplate(to=UnresolvedDomain)]
46#[biplate(to=Expression)]
47#[biplate(to=Reference)]
48#[biplate(to=IntVal)]
49#[path_prefix(conjure_cp::ast)]
50pub enum Domain {
51 Ground(Moo<GroundDomain>),
53 Unresolved(Moo<UnresolvedDomain>),
55}
56
57pub trait HasDomain {
59 fn domain_of(&self) -> DomainPtr;
61}
62
63impl<T: HasDomain> Typeable for T {
64 fn return_type(&self) -> ReturnType {
65 self.domain_of().return_type()
66 }
67}
68
69thread_local! {
72 static BOOL_DOMAIN: DomainPtr =
73 Moo::new(Domain::Ground(Moo::new(GroundDomain::Bool)));
74}
75
76impl Domain {
77 pub fn bool() -> DomainPtr {
80 BOOL_DOMAIN.with(Clone::clone)
81 }
82
83 pub fn empty(ty: ReturnType) -> DomainPtr {
86 Moo::new(Domain::Ground(Moo::new(GroundDomain::Empty(ty))))
87 }
88
89 pub fn int<T>(ranges: Vec<T>) -> DomainPtr
93 where
94 T: Into<Range<IntVal>> + TryInto<Range<Int>> + Clone,
95 {
96 if let Ok(int_rngs) = ranges
97 .iter()
98 .cloned()
99 .map(TryInto::try_into)
100 .collect::<Result<Vec<_>, _>>()
101 {
102 return Domain::int_ground(int_rngs);
103 }
104 let unresolved_rngs: Vec<Range<IntVal>> = ranges.into_iter().map(Into::into).collect();
105 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Int(
106 unresolved_rngs,
107 ))))
108 }
109
110 pub fn int_ground(ranges: Vec<Range<Int>>) -> DomainPtr {
112 let rngs = Range::squeeze(&ranges);
113 Moo::new(Domain::Ground(Moo::new(GroundDomain::Int(rngs))))
114 }
115
116 pub fn set<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
120 where
121 T: Into<SetAttr<IntVal>> + TryInto<SetAttr<Int>> + Clone,
122 {
123 if let Domain::Ground(gd) = inner_dom.as_ref()
124 && let Ok(int_attr) = attr.clone().try_into()
125 {
126 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Set(
127 int_attr,
128 gd.clone(),
129 ))));
130 }
131 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Set(
132 attr.into(),
133 inner_dom,
134 ))))
135 }
136
137 pub fn mset<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
139 where
140 T: Into<MSetAttr<IntVal>> + TryInto<MSetAttr<Int>> + Clone,
141 {
142 if let Domain::Ground(gd) = inner_dom.as_ref()
143 && let Ok(int_attr) = attr.clone().try_into()
144 {
145 return Moo::new(Domain::Ground(Moo::new(GroundDomain::MSet(
146 int_attr,
147 gd.clone(),
148 ))));
149 }
150 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::MSet(
151 attr.into(),
152 inner_dom,
153 ))))
154 }
155
156 pub fn matrix(inner_dom: DomainPtr, idx_doms: Vec<DomainPtr>) -> DomainPtr {
160 if let Domain::Ground(gd) = inner_dom.as_ref()
161 && let Some(idx_gds) = as_grounds(&idx_doms)
162 {
163 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Matrix(
164 gd.clone(),
165 idx_gds,
166 ))));
167 }
168 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Matrix(
169 inner_dom, idx_doms,
170 ))))
171 }
172
173 pub fn tuple(inner_doms: Vec<DomainPtr>) -> DomainPtr {
177 if let Some(inner_gds) = as_grounds(&inner_doms) {
178 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Tuple(inner_gds))));
179 }
180 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Tuple(
181 inner_doms,
182 ))))
183 }
184
185 pub fn record(entries: Vec<Field<DomainPtr>>) -> DomainPtr {
189 if let Ok(entries_gds) = entries.iter().cloned().map(TryInto::try_into).try_collect() {
190 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Record(entries_gds))));
191 }
192 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Record(
193 entries,
194 ))))
195 }
196
197 pub fn reference(ptr: DeclarationPtr) -> Option<DomainPtr> {
199 let _ = ptr.as_domain_letting()?;
200 Some(Moo::new(Domain::Unresolved(Moo::new(
201 UnresolvedDomain::Reference(Reference::new(ptr)),
202 ))))
203 }
204
205 pub fn partition<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
207 where
208 T: Into<PartitionAttr<IntVal>> + TryInto<PartitionAttr<Int>> + Clone,
209 {
210 if let Domain::Ground(gd) = inner_dom.as_ref()
211 && let Ok(int_attr) = attr.clone().try_into()
212 {
213 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Partition(
214 int_attr,
215 gd.clone(),
216 ))));
217 }
218 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Partition(
219 attr.into(),
220 inner_dom,
221 ))))
222 }
223
224 pub fn function<T>(attrs: T, dom: DomainPtr, cdom: DomainPtr) -> DomainPtr
226 where
227 T: Into<FuncAttr<IntVal>> + TryInto<FuncAttr<Int>> + Clone,
228 {
229 if let Ok(attrs_gd) = attrs.clone().try_into()
230 && let Some(dom_gd) = dom.as_ground()
231 && let Some(cdom_gd) = cdom.as_ground()
232 {
233 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Function(
234 attrs_gd,
235 Moo::new(dom_gd.clone()),
236 Moo::new(cdom_gd.clone()),
237 ))));
238 }
239
240 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Function(
241 attrs.into(),
242 dom,
243 cdom,
244 ))))
245 }
246
247 pub fn variant(entries: Vec<Field<DomainPtr>>) -> DomainPtr {
251 if let Ok(entries_gds) = entries.iter().cloned().map(TryInto::try_into).try_collect() {
252 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Variant(entries_gds))));
253 }
254 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Variant(
255 entries,
256 ))))
257 }
258
259 pub fn relation<T>(attrs: T, inner_doms: Vec<DomainPtr>) -> DomainPtr
263 where
264 T: Into<RelAttr<IntVal>> + TryInto<RelAttr<Int>> + Clone,
265 {
266 if let Ok(attrs_gd) = attrs.clone().try_into()
267 && let Some(doms_gd) = as_grounds(&inner_doms)
268 {
269 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Relation(
270 attrs_gd, doms_gd,
271 ))));
272 }
273
274 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Relation(
275 attrs.into(),
276 inner_doms,
277 ))))
278 }
279
280 pub fn sequence<T>(attr: T, inner_dom: DomainPtr) -> DomainPtr
282 where
283 T: Into<SequenceAttr<IntVal>> + TryInto<SequenceAttr<Int>> + Clone,
284 {
285 if let Domain::Ground(gd) = inner_dom.as_ref()
286 && let Ok(int_attr) = attr.clone().try_into()
287 {
288 return Moo::new(Domain::Ground(Moo::new(GroundDomain::Sequence(
289 int_attr,
290 gd.clone(),
291 ))));
292 }
293 Moo::new(Domain::Unresolved(Moo::new(UnresolvedDomain::Sequence(
294 attr.into(),
295 inner_dom,
296 ))))
297 }
298
299 pub fn resolve(&self) -> Result<Moo<GroundDomain>, DomainOpError> {
304 match self {
305 Domain::Ground(gd) => Ok(gd.clone()),
306 Domain::Unresolved(ud) => ud.resolve().map(Moo::new),
307 }
308 }
309
310 pub fn as_ground(&self) -> Option<&GroundDomain> {
314 match self {
315 Domain::Ground(gd) => Some(gd.as_ref()),
316 _ => None,
317 }
318 }
319
320 pub fn as_ground_mut(&mut self) -> Option<&mut GroundDomain> {
323 match self {
324 Domain::Ground(gd) => Some(Moo::<GroundDomain>::make_mut(gd)),
325 _ => None,
326 }
327 }
328
329 pub fn as_unresolved(&self) -> Option<&UnresolvedDomain> {
331 match self {
332 Domain::Unresolved(ud) => Some(ud.as_ref()),
333 _ => None,
334 }
335 }
336
337 pub fn as_unresolved_mut(&mut self) -> Option<&mut UnresolvedDomain> {
339 match self {
340 Domain::Unresolved(ud) => Some(Moo::<UnresolvedDomain>::make_mut(ud)),
341 _ => None,
342 }
343 }
344
345 pub fn as_dom_empty(&self) -> Option<&ReturnType> {
347 if let Some(GroundDomain::Empty(ty)) = self.as_ground() {
348 return Some(ty);
349 }
350 None
351 }
352
353 pub fn as_dom_empty_mut(&mut self) -> Option<&mut ReturnType> {
355 if let Some(GroundDomain::Empty(ty)) = self.as_ground_mut() {
356 return Some(ty);
357 }
358 None
359 }
360
361 pub fn is_bool(&self) -> bool {
363 self.return_type() == ReturnType::Bool
364 }
365
366 pub fn is_int(&self) -> bool {
368 self.return_type() == ReturnType::Int
369 }
370
371 pub fn as_int(&self) -> Option<Vec<Range<IntVal>>> {
374 if let Some(GroundDomain::Int(rngs)) = self.as_ground() {
375 return Some(rngs.iter().cloned().map(|r| r.into()).collect());
376 }
377 if let Some(UnresolvedDomain::Int(rngs)) = self.as_unresolved() {
378 return Some(rngs.clone());
379 }
380 None
381 }
382
383 pub fn as_int_mut(&mut self) -> Option<&mut Vec<Range<IntVal>>> {
386 if let Some(GroundDomain::Int(rngs_gds)) = self.as_ground() {
392 let rngs: Vec<Range<IntVal>> = rngs_gds.iter().cloned().map(|r| r.into()).collect();
393 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Int(rngs)))
394 }
395
396 if let Some(UnresolvedDomain::Int(rngs)) = self.as_unresolved_mut() {
397 return Some(rngs);
398 }
399 None
400 }
401
402 pub fn as_int_ground(&self) -> Option<&Vec<Range<Int>>> {
404 if let Some(GroundDomain::Int(rngs)) = self.as_ground() {
405 return Some(rngs);
406 }
407 None
408 }
409
410 pub fn as_int_ground_mut(&mut self) -> Option<&mut Vec<Range<Int>>> {
412 if let Some(GroundDomain::Int(rngs)) = self.as_ground_mut() {
413 return Some(rngs);
414 }
415 None
416 }
417
418 pub fn as_matrix(&self) -> Option<(DomainPtr, Vec<DomainPtr>)> {
421 if let Some(GroundDomain::Matrix(inner_dom_gd, idx_doms_gds)) = self.as_ground() {
422 let idx_doms: Vec<DomainPtr> = idx_doms_gds.iter().cloned().map(|d| d.into()).collect();
423 let inner_dom: DomainPtr = inner_dom_gd.clone().into();
424 return Some((inner_dom, idx_doms));
425 }
426 if let Some(UnresolvedDomain::Matrix(inner_dom, idx_doms)) = self.as_unresolved() {
427 return Some((inner_dom.clone(), idx_doms.clone()));
428 }
429 None
430 }
431
432 pub fn as_matrix_mut(&mut self) -> Option<(&mut DomainPtr, &mut Vec<DomainPtr>)> {
436 if let Some(GroundDomain::Matrix(inner_dom_gd, idx_doms_gds)) = self.as_ground() {
439 let inner_dom: DomainPtr = inner_dom_gd.clone().into();
440 let idx_doms: Vec<DomainPtr> = idx_doms_gds.iter().cloned().map(|d| d.into()).collect();
441 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Matrix(inner_dom, idx_doms)));
442 }
443
444 if let Some(UnresolvedDomain::Matrix(inner_dom, idx_doms)) = self.as_unresolved_mut() {
445 return Some((inner_dom, idx_doms));
446 }
447 None
448 }
449
450 pub fn as_matrix_ground(&self) -> Option<(&Moo<GroundDomain>, &Vec<Moo<GroundDomain>>)> {
452 if let Some(GroundDomain::Matrix(inner_dom, idx_doms)) = self.as_ground() {
453 return Some((inner_dom, idx_doms));
454 }
455 None
456 }
457
458 pub fn as_matrix_ground_mut(
460 &mut self,
461 ) -> Option<(&mut Moo<GroundDomain>, &mut Vec<Moo<GroundDomain>>)> {
462 if let Some(GroundDomain::Matrix(inner_dom, idx_doms)) = self.as_ground_mut() {
463 return Some((inner_dom, idx_doms));
464 }
465 None
466 }
467
468 pub fn as_set(&self) -> Option<(SetAttr<IntVal>, DomainPtr)> {
470 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground() {
471 return Some((attr.clone().into(), inner_dom.clone().into()));
472 }
473 if let Some(UnresolvedDomain::Set(attr, inner_dom)) = self.as_unresolved() {
474 return Some((attr.clone(), inner_dom.clone()));
475 }
476 None
477 }
478
479 pub fn as_set_mut(&mut self) -> Option<(&mut SetAttr<IntVal>, &mut DomainPtr)> {
482 if let Some(GroundDomain::Set(attr_gd, inner_dom_gd)) = self.as_ground() {
483 let attr: SetAttr<IntVal> = attr_gd.clone().into();
484 let inner_dom = inner_dom_gd.clone().into();
485 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Set(attr, inner_dom)));
486 }
487
488 if let Some(UnresolvedDomain::Set(attr, inner_dom)) = self.as_unresolved_mut() {
489 return Some((attr, inner_dom));
490 }
491 None
492 }
493
494 pub fn as_set_ground(&self) -> Option<(&SetAttr<Int>, &Moo<GroundDomain>)> {
496 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground() {
497 return Some((attr, inner_dom));
498 }
499 None
500 }
501
502 pub fn as_set_ground_mut(&mut self) -> Option<(&mut SetAttr<Int>, &mut Moo<GroundDomain>)> {
504 if let Some(GroundDomain::Set(attr, inner_dom)) = self.as_ground_mut() {
505 return Some((attr, inner_dom));
506 }
507 None
508 }
509
510 pub fn as_mset(&self) -> Option<(MSetAttr<IntVal>, DomainPtr)> {
512 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground() {
513 return Some((attr.clone().into(), inner_dom.clone().into()));
514 }
515 if let Some(UnresolvedDomain::MSet(attr, inner_dom)) = self.as_unresolved() {
516 return Some((attr.clone(), inner_dom.clone()));
517 }
518 None
519 }
520
521 pub fn as_mset_mut(&mut self) -> Option<(&mut MSetAttr<IntVal>, &mut DomainPtr)> {
524 if let Some(GroundDomain::MSet(attr_gd, inner_dom_gd)) = self.as_ground() {
525 let attr: MSetAttr<IntVal> = attr_gd.clone().into();
526 let inner_dom = inner_dom_gd.clone().into();
527 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::MSet(attr, inner_dom)));
528 }
529
530 if let Some(UnresolvedDomain::MSet(attr, inner_dom)) = self.as_unresolved_mut() {
531 return Some((attr, inner_dom));
532 }
533 None
534 }
535
536 pub fn as_mset_ground(&self) -> Option<(&MSetAttr<Int>, &Moo<GroundDomain>)> {
538 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground() {
539 return Some((attr, inner_dom));
540 }
541 None
542 }
543
544 pub fn as_mset_ground_mut(&mut self) -> Option<(&mut MSetAttr<Int>, &mut Moo<GroundDomain>)> {
546 if let Some(GroundDomain::MSet(attr, inner_dom)) = self.as_ground_mut() {
547 return Some((attr, inner_dom));
548 }
549 None
550 }
551
552 pub fn as_tuple(&self) -> Option<Vec<DomainPtr>> {
554 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground() {
555 return Some(inner_doms.iter().cloned().map(|d| d.into()).collect());
556 }
557 if let Some(UnresolvedDomain::Tuple(inner_doms)) = self.as_unresolved() {
558 return Some(inner_doms.clone());
559 }
560 None
561 }
562
563 pub fn as_tuple_mut(&mut self) -> Option<&mut Vec<DomainPtr>> {
566 if let Some(GroundDomain::Tuple(inner_doms_gds)) = self.as_ground() {
567 let inner_doms: Vec<DomainPtr> =
568 inner_doms_gds.iter().cloned().map(|d| d.into()).collect();
569 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Tuple(inner_doms)));
570 }
571
572 if let Some(UnresolvedDomain::Tuple(inner_doms)) = self.as_unresolved_mut() {
573 return Some(inner_doms);
574 }
575 None
576 }
577
578 pub fn as_tuple_ground(&self) -> Option<&Vec<Moo<GroundDomain>>> {
580 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground() {
581 return Some(inner_doms);
582 }
583 None
584 }
585
586 pub fn as_tuple_ground_mut(&mut self) -> Option<&mut Vec<Moo<GroundDomain>>> {
588 if let Some(GroundDomain::Tuple(inner_doms)) = self.as_ground_mut() {
589 return Some(inner_doms);
590 }
591 None
592 }
593
594 pub fn as_record(&self) -> Option<Vec<FieldUnresolved>> {
596 if let Some(GroundDomain::Record(record_entries)) = self.as_ground() {
597 return Some(record_entries.iter().cloned().map(|r| r.into()).collect());
598 }
599 if let Some(UnresolvedDomain::Record(record_entries)) = self.as_unresolved() {
600 return Some(record_entries.clone());
601 }
602 None
603 }
604
605 pub fn as_record_ground(&self) -> Option<&Vec<FieldGround>> {
607 if let Some(GroundDomain::Record(entries)) = self.as_ground() {
608 return Some(entries);
609 }
610 None
611 }
612
613 pub fn as_record_mut(&mut self) -> Option<&mut Vec<FieldUnresolved>> {
616 if let Some(GroundDomain::Record(entries_gds)) = self.as_ground() {
617 let entries: Vec<FieldUnresolved> =
618 entries_gds.iter().cloned().map(|r| r.into()).collect();
619 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Record(entries)));
620 }
621
622 if let Some(UnresolvedDomain::Record(entries_gds)) = self.as_unresolved_mut() {
623 return Some(entries_gds);
624 }
625 None
626 }
627
628 pub fn as_record_ground_mut(&mut self) -> Option<&mut Vec<FieldGround>> {
630 if let Some(GroundDomain::Record(entries)) = self.as_ground_mut() {
631 return Some(entries);
632 }
633 None
634 }
635
636 pub fn as_sequence(&self) -> Option<(SequenceAttr<IntVal>, Moo<Domain>)> {
638 if let Some(GroundDomain::Sequence(attrs, dom)) = self.as_ground() {
639 return Some((attrs.clone().into(), dom.clone().into()));
640 }
641 if let Some(UnresolvedDomain::Sequence(attrs, dom)) = self.as_unresolved() {
642 return Some((attrs.clone(), dom.clone()));
643 }
644 None
645 }
646
647 pub fn as_sequence_mut(&mut self) -> Option<(&mut SequenceAttr<IntVal>, &mut Moo<Domain>)> {
651 if let Some(GroundDomain::Sequence(attrs, dom)) = self.as_ground() {
652 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Sequence(
653 attrs.clone().into(),
654 dom.clone().into(),
655 )));
656 }
657
658 if let Some(UnresolvedDomain::Sequence(attrs, dom)) = self.as_unresolved_mut() {
659 return Some((attrs, dom));
660 }
661 None
662 }
663
664 pub fn as_function(&self) -> Option<(FuncAttr<IntVal>, Moo<Domain>, Moo<Domain>)> {
666 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
667 return Some((
668 attrs.clone().into(),
669 dom.clone().into(),
670 codom.clone().into(),
671 ));
672 }
673 if let Some(UnresolvedDomain::Function(attrs, dom, codom)) = self.as_unresolved() {
674 return Some((attrs.clone(), dom.clone(), codom.clone()));
675 }
676 None
677 }
678
679 pub fn as_function_mut(
683 &mut self,
684 ) -> Option<(&mut FuncAttr<IntVal>, &mut Moo<Domain>, &mut Moo<Domain>)> {
685 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
686 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Function(
687 attrs.clone().into(),
688 dom.clone().into(),
689 codom.clone().into(),
690 )));
691 }
692
693 if let Some(UnresolvedDomain::Function(attrs, dom, codom)) = self.as_unresolved_mut() {
694 return Some((attrs, dom, codom));
695 }
696 None
697 }
698
699 pub fn as_function_ground(
701 &self,
702 ) -> Option<(&FuncAttr, &Moo<GroundDomain>, &Moo<GroundDomain>)> {
703 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground() {
704 return Some((attrs, dom, codom));
705 }
706 None
707 }
708
709 pub fn as_function_ground_mut(
711 &mut self,
712 ) -> Option<(
713 &mut FuncAttr,
714 &mut Moo<GroundDomain>,
715 &mut Moo<GroundDomain>,
716 )> {
717 if let Some(GroundDomain::Function(attrs, dom, codom)) = self.as_ground_mut() {
718 return Some((attrs, dom, codom));
719 }
720 None
721 }
722
723 pub fn as_partition(&self) -> Option<(PartitionAttr<IntVal>, Moo<Domain>)> {
725 if let Some(GroundDomain::Partition(attrs, doms)) = self.as_ground() {
726 return Some((attrs.clone().into(), doms.clone().into()));
727 }
728 if let Some(UnresolvedDomain::Partition(attrs, doms)) = self.as_unresolved() {
729 return Some((attrs.clone(), doms.clone()));
730 }
731 None
732 }
733
734 pub fn as_partition_mut(&mut self) -> Option<(&mut PartitionAttr<IntVal>, &mut DomainPtr)> {
737 if let Some(GroundDomain::Partition(attr_gd, inner_dom_gd)) = self.as_ground() {
738 let attr: PartitionAttr<IntVal> = attr_gd.clone().into();
739 let inner_dom = inner_dom_gd.clone().into();
740 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Partition(attr, inner_dom)));
741 }
742
743 if let Some(UnresolvedDomain::Partition(attr, inner_dom)) = self.as_unresolved_mut() {
744 return Some((attr, inner_dom));
745 }
746 None
747 }
748
749 pub fn as_partition_ground(&self) -> Option<(&PartitionAttr<Int>, &Moo<GroundDomain>)> {
751 if let Some(GroundDomain::Partition(attr, inner_dom)) = self.as_ground() {
752 return Some((attr, inner_dom));
753 }
754 None
755 }
756
757 pub fn as_partition_ground_mut(
759 &mut self,
760 ) -> Option<(&mut PartitionAttr<Int>, &mut Moo<GroundDomain>)> {
761 if let Some(GroundDomain::Partition(attr, inner_dom)) = self.as_ground_mut() {
762 return Some((attr, inner_dom));
763 }
764 None
765 }
766
767 pub fn as_variant(&self) -> Option<Vec<FieldUnresolved>> {
769 if let Some(GroundDomain::Variant(entries)) = self.as_ground() {
770 return Some(entries.iter().cloned().map(|r| r.into()).collect());
771 }
772 if let Some(UnresolvedDomain::Variant(entries)) = self.as_unresolved() {
773 return Some(entries.clone());
774 }
775 None
776 }
777
778 pub fn as_variant_ground(&self) -> Option<&Vec<FieldGround>> {
780 if let Some(GroundDomain::Variant(entries)) = self.as_ground() {
781 return Some(entries);
782 }
783 None
784 }
785
786 pub fn as_variant_mut(&mut self) -> Option<&mut Vec<FieldUnresolved>> {
789 if let Some(GroundDomain::Variant(entries_gds)) = self.as_ground() {
790 let entries: Vec<FieldUnresolved> =
791 entries_gds.iter().cloned().map(|r| r.into()).collect();
792 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Variant(entries)));
793 }
794
795 if let Some(UnresolvedDomain::Variant(entries_gds)) = self.as_unresolved_mut() {
796 return Some(entries_gds);
797 }
798 None
799 }
800
801 pub fn as_variant_ground_mut(&mut self) -> Option<&mut Vec<FieldGround>> {
803 if let Some(GroundDomain::Variant(entries)) = self.as_ground_mut() {
804 return Some(entries);
805 }
806 None
807 }
808
809 pub fn as_relation(&self) -> Option<(RelAttr<IntVal>, Vec<Moo<Domain>>)> {
811 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
812 return Some((
813 attrs.clone().into(),
814 doms.iter().cloned().map(|d| d.into()).collect(),
815 ));
816 }
817 if let Some(UnresolvedDomain::Relation(attrs, doms)) = self.as_unresolved() {
818 return Some((attrs.clone(), doms.clone()));
819 }
820 None
821 }
822
823 pub fn as_relation_mut(&mut self) -> Option<(&mut RelAttr<IntVal>, &mut Vec<Moo<Domain>>)> {
827 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
828 *self = Domain::Unresolved(Moo::new(UnresolvedDomain::Relation(
829 attrs.clone().into(),
830 doms.iter().cloned().map(|d| d.into()).collect(),
831 )));
832 }
833
834 if let Some(UnresolvedDomain::Relation(attrs, doms)) = self.as_unresolved_mut() {
835 return Some((attrs, doms));
836 }
837 None
838 }
839
840 pub fn as_relation_ground(&self) -> Option<(&RelAttr, &Vec<Moo<GroundDomain>>)> {
842 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground() {
843 return Some((attrs, doms));
844 }
845 None
846 }
847
848 pub fn as_relation_ground_mut(
850 &mut self,
851 ) -> Option<(&mut RelAttr, &mut Vec<Moo<GroundDomain>>)> {
852 if let Some(GroundDomain::Relation(attrs, doms)) = self.as_ground_mut() {
853 return Some((attrs, doms));
854 }
855 None
856 }
857
858 pub fn union(&self, other: &Domain) -> Result<Domain, DomainOpError> {
860 match (self, other) {
861 (Domain::Ground(a), Domain::Ground(b)) => Ok(Domain::Ground(Moo::new(a.union(b)?))),
862 (Domain::Unresolved(a), Domain::Unresolved(b)) => {
863 Ok(Domain::Unresolved(Moo::new(a.union_unresolved(b)?)))
864 }
865 (Domain::Unresolved(u), Domain::Ground(g))
866 | (Domain::Ground(g), Domain::Unresolved(u)) => {
867 todo!("Union of unresolved domain {u} and ground domain {g} is not yet implemented")
868 }
869 }
870 }
871
872 pub fn intersect(&self, other: &Domain) -> Result<Domain, DomainOpError> {
874 match (self, other) {
875 (Domain::Ground(a), Domain::Ground(b)) => {
876 a.intersect(b).map(|res| Domain::Ground(Moo::new(res)))
877 }
878 _ => Err(DomainOpError::NotGround),
879 }
880 }
881
882 pub fn values(&self) -> Result<impl Iterator<Item = Literal>, DomainOpError> {
884 if let Some(gd) = self.as_ground() {
885 return gd.values();
886 }
887 Err(DomainOpError::NotGround)
888 }
889
890 pub fn length(&self) -> Result<u64, DomainOpError> {
892 if let Some(gd) = self.as_ground() {
893 return gd.length();
894 }
895 Err(DomainOpError::NotGround)
896 }
897 pub fn length_signed(&self) -> Result<i32, DomainOpError> {
903 let gd = self.as_ground().ok_or(DomainOpError::NotGround)?;
904 let len = gd.length()?;
905 len.try_into().map_err(|_| DomainOpError::TooLarge)
906 }
907
908 pub fn from_literal_vec(vals: &[Literal]) -> Result<DomainPtr, DomainOpError> {
910 GroundDomain::from_literal_vec(vals).map(DomainPtr::from)
911 }
912
913 pub fn contains(&self, lit: &Literal) -> Result<bool, DomainOpError> {
915 if let Some(gd) = self.as_ground() {
916 return gd.contains(lit);
917 }
918 Err(DomainOpError::NotGround)
919 }
920
921 pub fn element_domain(&self) -> Option<DomainPtr> {
922 match self {
923 Domain::Ground(gd) => gd.element_domain().map(DomainPtr::from),
924 Domain::Unresolved(ud) => ud.element_domain(),
925 }
926 }
927}
928
929impl Typeable for Domain {
930 fn return_type(&self) -> ReturnType {
931 match self {
932 Domain::Ground(dom) => dom.return_type(),
933 Domain::Unresolved(dom) => dom.return_type(),
934 }
935 }
936}
937
938impl Display for Domain {
939 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
940 match &self {
941 Domain::Ground(gd) => gd.fmt(f),
942 Domain::Unresolved(ud) => ud.fmt(f),
943 }
944 }
945}
946
947fn as_grounds(doms: &[DomainPtr]) -> Option<Vec<Moo<GroundDomain>>> {
948 doms.iter()
949 .map(|idx| match idx.as_ref() {
950 Domain::Ground(idx_gd) => Some(idx_gd.clone()),
951 _ => None,
952 })
953 .collect()
954}
955
956#[cfg(test)]
957mod tests {
958 use super::*;
959 use crate::ast::Name;
960 use crate::{domain_int, range};
961
962 #[test]
963 fn test_negative_product() {
964 let d1 = Domain::int(vec![Range::Bounded(-2, 1)]);
965 let d2 = Domain::int(vec![Range::Bounded(-2, 1)]);
966 let res = d1
967 .as_ground()
968 .unwrap()
969 .apply_i32(|a, b| Some(a * b), d2.as_ground().unwrap())
970 .unwrap();
971
972 assert!(matches!(res, GroundDomain::Int(_)));
973 if let GroundDomain::Int(ranges) = res {
974 assert!(!ranges.contains(&Range::Bounded(-4, 4)));
975 }
976 }
977
978 #[test]
979 fn test_negative_div() {
980 let d1 = GroundDomain::Int(vec![Range::Bounded(-2, 1)]);
981 let d2 = GroundDomain::Int(vec![Range::Bounded(-2, 1)]);
982 let res = d1
983 .apply_i32(|a, b| if b != 0 { Some(a / b) } else { None }, &d2)
984 .unwrap();
985
986 assert!(matches!(res, GroundDomain::Int(_)));
987 if let GroundDomain::Int(ranges) = res {
988 assert!(!ranges.contains(&Range::Bounded(-4, 4)));
989 }
990 }
991
992 #[test]
993 fn test_length_basic() {
994 assert_eq!(Domain::empty(ReturnType::Int).length(), Ok(0));
995 assert_eq!(Domain::bool().length(), Ok(2));
996 assert_eq!(domain_int!(1..3, 5, 7..9).length(), Ok(7));
997 assert_eq!(
998 domain_int!(1..2, 5..).length(),
999 Err(DomainOpError::Unbounded)
1000 );
1001 }
1002 #[test]
1003 fn test_length_set_basic() {
1004 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..3));
1006 assert_eq!(s.length(), Ok(8));
1007
1008 let s = Domain::set(SetAttr::new_size(2), domain_int!(1..3));
1010 assert_eq!(s.length(), Ok(3));
1011
1012 let s = Domain::set(SetAttr::new_min_max_size(1, 2), domain_int!(1..3));
1014 assert_eq!(s.length(), Ok(6));
1015
1016 let s = Domain::set(SetAttr::new_min_size(1), domain_int!(1..3));
1018 assert_eq!(s.length(), Ok(7));
1019
1020 let s = Domain::set(SetAttr::new_max_size(2), domain_int!(1..3));
1022 assert_eq!(s.length(), Ok(7));
1023 }
1024
1025 #[test]
1026 fn test_length_set_nested() {
1027 let s2 = Domain::set(
1034 SetAttr::new_max_size(2),
1035 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..2)),
1037 );
1038 assert_eq!(s2.length(), Ok(11));
1039 }
1040
1041 #[test]
1042 fn test_length_set_unbounded_inner() {
1043 let s2_bad = Domain::set(
1045 SetAttr::new_max_size(2),
1046 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..)),
1047 );
1048 assert_eq!(s2_bad.length(), Err(DomainOpError::Unbounded));
1049 }
1050
1051 #[test]
1052 fn test_length_set_overflow() {
1053 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..20));
1054 assert!(s.length().is_ok());
1055
1056 let s = Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..63));
1058 assert_eq!(s.length(), Err(DomainOpError::TooLarge));
1059 }
1060
1061 #[test]
1062 fn test_length_tuple() {
1063 let t = Domain::tuple(vec![domain_int!(1..3), Domain::bool()]);
1065 assert_eq!(t.length(), Ok(6));
1066 }
1067
1068 #[test]
1069 fn test_length_record() {
1070 let t = Domain::record(vec![
1072 Field {
1073 name: Name::user("a"),
1074 value: domain_int!(1..3),
1075 },
1076 Field {
1077 name: Name::user("b"),
1078 value: Domain::bool(),
1079 },
1080 ]);
1081 assert_eq!(t.length(), Ok(6));
1082 }
1083
1084 #[test]
1085 fn test_length_matrix_basic() {
1086 let m = Domain::matrix(Domain::bool(), vec![domain_int!(1..3)]);
1088 assert_eq!(m.length(), Ok(8));
1089
1090 let m = Domain::matrix(domain_int!(1..3), vec![domain_int!(1..2)]);
1092 assert_eq!(m.length(), Ok(9));
1093 }
1094
1095 #[test]
1096 fn test_length_matrix_2d() {
1097 let m = Domain::matrix(Domain::bool(), vec![domain_int!(1..2), domain_int!(1..3)]);
1099 assert_eq!(m.length(), Ok(64));
1100 }
1101
1102 #[test]
1103 fn test_length_matrix_of_sets() {
1104 let m = Domain::matrix(
1106 Domain::set(SetAttr::<IntVal>::default(), domain_int!(1..2)),
1107 vec![domain_int!(1..3)],
1108 );
1109 assert_eq!(m.length(), Ok(64));
1110 }
1111}