1
use crate::ast::domains::attrs::MSetAttr;
2
use crate::ast::domains::attrs::PartitionAttr;
3
use crate::ast::domains::attrs::SetAttr;
4
use crate::ast::{
5
    DeclarationKind, DomainOpError, Expression, FieldEntryGround, FuncAttr, Literal, Metadata, Moo,
6
    Reference, RelAttr, SequenceAttr, Typeable,
7
    domains::{
8
        GroundDomain,
9
        domain::{DomainPtr, Int},
10
        range::Range,
11
    },
12
};
13
use crate::{bug, domain_int, matrix_expr, range};
14
use conjure_cp_core::ast::pretty::pretty_vec;
15
use conjure_cp_core::ast::{Name, ReturnType, eval_constant};
16
use itertools::Itertools;
17
use polyquine::Quine;
18
use serde::{Deserialize, Serialize};
19
use std::fmt::{Display, Formatter};
20
use std::iter::zip;
21
use std::ops::Deref;
22
use uniplate::Uniplate;
23

            
24
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
25
#[path_prefix(conjure_cp::ast)]
26
#[biplate(to=Expression)]
27
#[biplate(to=Reference)]
28
pub enum IntVal {
29
    Const(Int),
30
    #[polyquine_skip]
31
    Reference(Reference),
32
    Expr(Moo<Expression>),
33
}
34

            
35
impl From<Int> for IntVal {
36
43984
    fn from(value: Int) -> Self {
37
43984
        Self::Const(value)
38
43984
    }
39
}
40

            
41
impl TryInto<Int> for IntVal {
42
    type Error = DomainOpError;
43

            
44
131806
    fn try_into(self) -> Result<Int, Self::Error> {
45
131806
        match self {
46
126772
            IntVal::Const(val) => Ok(val),
47
5034
            _ => Err(DomainOpError::NotGround),
48
        }
49
131806
    }
50
}
51

            
52
impl From<Range<Int>> for Range<IntVal> {
53
22516
    fn from(value: Range<Int>) -> Self {
54
22516
        match value {
55
946
            Range::Single(x) => Range::Single(x.into()),
56
21506
            Range::Bounded(l, r) => Range::Bounded(l.into(), r.into()),
57
10
            Range::UnboundedL(r) => Range::UnboundedL(r.into()),
58
16
            Range::UnboundedR(l) => Range::UnboundedR(l.into()),
59
38
            Range::Unbounded => Range::Unbounded,
60
        }
61
22516
    }
62
}
63

            
64
impl TryInto<Range<Int>> for Range<IntVal> {
65
    type Error = DomainOpError;
66

            
67
71860
    fn try_into(self) -> Result<Range<Int>, Self::Error> {
68
71860
        match self {
69
5050
            Range::Single(x) => Ok(Range::Single(x.try_into()?)),
70
63560
            Range::Bounded(l, r) => Ok(Range::Bounded(l.try_into()?, r.try_into()?)),
71
506
            Range::UnboundedL(r) => Ok(Range::UnboundedL(r.try_into()?)),
72
536
            Range::UnboundedR(l) => Ok(Range::UnboundedR(l.try_into()?)),
73
2208
            Range::Unbounded => Ok(Range::Unbounded),
74
        }
75
71860
    }
76
}
77

            
78
impl From<SetAttr<Int>> for SetAttr<IntVal> {
79
2
    fn from(value: SetAttr<Int>) -> Self {
80
2
        SetAttr {
81
2
            size: value.size.into(),
82
2
        }
83
2
    }
84
}
85

            
86
impl TryInto<SetAttr<Int>> for SetAttr<IntVal> {
87
    type Error = DomainOpError;
88

            
89
850
    fn try_into(self) -> Result<SetAttr<Int>, Self::Error> {
90
850
        let size: Range<Int> = self.size.try_into()?;
91
850
        Ok(SetAttr { size })
92
850
    }
93
}
94

            
95
impl From<MSetAttr<Int>> for MSetAttr<IntVal> {
96
2
    fn from(value: MSetAttr<Int>) -> Self {
97
2
        MSetAttr {
98
2
            size: value.size.into(),
99
2
            occurrence: value.occurrence.into(),
100
2
        }
101
2
    }
102
}
103

            
104
impl TryInto<MSetAttr<Int>> for MSetAttr<IntVal> {
105
    type Error = DomainOpError;
106

            
107
482
    fn try_into(self) -> Result<MSetAttr<Int>, Self::Error> {
108
482
        let size: Range<Int> = self.size.try_into()?;
109
482
        let occurrence: Range<Int> = self.occurrence.try_into()?;
110
482
        Ok(MSetAttr { size, occurrence })
111
482
    }
112
}
113

            
114
impl From<FuncAttr<Int>> for FuncAttr<IntVal> {
115
70
    fn from(value: FuncAttr<Int>) -> Self {
116
70
        FuncAttr {
117
70
            size: value.size.into(),
118
70
            partiality: value.partiality,
119
70
            jectivity: value.jectivity,
120
70
        }
121
70
    }
122
}
123

            
124
impl TryInto<FuncAttr<Int>> for FuncAttr<IntVal> {
125
    type Error = DomainOpError;
126

            
127
718
    fn try_into(self) -> Result<FuncAttr<Int>, Self::Error> {
128
718
        let size: Range<Int> = self.size.try_into()?;
129
718
        Ok(FuncAttr {
130
718
            size,
131
718
            jectivity: self.jectivity,
132
718
            partiality: self.partiality,
133
718
        })
134
718
    }
135
}
136

            
137
impl From<RelAttr<Int>> for RelAttr<IntVal> {
138
4
    fn from(value: RelAttr<Int>) -> Self {
139
4
        RelAttr {
140
4
            size: value.size.into(),
141
4
            binary: value.binary,
142
4
        }
143
4
    }
144
}
145

            
146
impl TryInto<RelAttr<Int>> for RelAttr<IntVal> {
147
    type Error = DomainOpError;
148

            
149
488
    fn try_into(self) -> Result<RelAttr<Int>, Self::Error> {
150
488
        let size: Range<Int> = self.size.try_into()?;
151
488
        Ok(RelAttr {
152
488
            size,
153
488
            binary: self.binary,
154
488
        })
155
488
    }
156
}
157

            
158
impl From<PartitionAttr<Int>> for PartitionAttr<IntVal> {
159
10
    fn from(value: PartitionAttr<Int>) -> Self {
160
10
        PartitionAttr {
161
10
            num_parts: value.num_parts.into(),
162
10
            part_len: value.part_len.into(),
163
10
            is_regular: value.is_regular,
164
10
        }
165
10
    }
166
}
167

            
168
impl TryInto<PartitionAttr<Int>> for PartitionAttr<IntVal> {
169
    type Error = DomainOpError;
170

            
171
368
    fn try_into(self) -> Result<PartitionAttr<Int>, Self::Error> {
172
368
        let num_parts: Range<Int> = self.num_parts.try_into()?;
173
368
        let part_len: Range<Int> = self.part_len.try_into()?;
174
368
        let is_regular: bool = self.is_regular;
175
368
        Ok(PartitionAttr {
176
368
            num_parts,
177
368
            part_len,
178
368
            is_regular,
179
368
        })
180
368
    }
181
}
182

            
183
impl From<SequenceAttr<Int>> for SequenceAttr<IntVal> {
184
    fn from(value: SequenceAttr<Int>) -> Self {
185
        SequenceAttr {
186
            size: value.size.into(),
187
            jectivity: value.jectivity,
188
        }
189
    }
190
}
191

            
192
impl TryInto<SequenceAttr<Int>> for SequenceAttr<IntVal> {
193
    type Error = DomainOpError;
194

            
195
320
    fn try_into(self) -> Result<SequenceAttr<Int>, Self::Error> {
196
320
        let size: Range<Int> = self.size.try_into()?;
197
320
        Ok(SequenceAttr {
198
320
            size,
199
320
            jectivity: self.jectivity,
200
320
        })
201
320
    }
202
}
203

            
204
impl Display for IntVal {
205
6102230
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
206
6102230
        match self {
207
2958508
            IntVal::Const(val) => write!(f, "{val}"),
208
3025472
            IntVal::Reference(re) => write!(f, "{re}"),
209
118250
            IntVal::Expr(expr) => write!(f, "({expr})"),
210
        }
211
6102230
    }
212
}
213

            
214
impl IntVal {
215
1836
    pub fn new_ref(re: &Reference) -> Option<IntVal> {
216
1836
        match re.ptr.kind().deref() {
217
1650
            DeclarationKind::ValueLetting(expr, _)
218
            | DeclarationKind::TemporaryValueLetting(expr)
219
1650
            | DeclarationKind::QuantifiedExpr(expr) => match expr.return_type() {
220
1650
                ReturnType::Int => Some(IntVal::Reference(re.clone())),
221
                _ => None,
222
            },
223
106
            DeclarationKind::Given(dom) => match dom.return_type() {
224
106
                ReturnType::Int => Some(IntVal::Reference(re.clone())),
225
                _ => None,
226
            },
227
80
            DeclarationKind::Quantified(inner) => match inner.domain().return_type() {
228
80
                ReturnType::Int => Some(IntVal::Reference(re.clone())),
229
                _ => None,
230
            },
231
            DeclarationKind::Find(var) => match var.return_type() {
232
                ReturnType::Int => Some(IntVal::Reference(re.clone())),
233
                _ => None,
234
            },
235
            DeclarationKind::DomainLetting(_) | DeclarationKind::Field(_) => None,
236
        }
237
1836
    }
238

            
239
1188
    pub fn new_expr(value: Moo<Expression>) -> Option<IntVal> {
240
1188
        if value.return_type() != ReturnType::Int {
241
            return None;
242
1188
        }
243
1188
        Some(IntVal::Expr(value))
244
1188
    }
245

            
246
1145612
    pub fn resolve(&self) -> Option<Int> {
247
1145612
        match self {
248
557316
            IntVal::Const(value) => Some(*value),
249
58274
            IntVal::Expr(expr) => eval_expr_to_int(expr),
250
530022
            IntVal::Reference(re) => match re.ptr.kind().deref() {
251
523484
                DeclarationKind::ValueLetting(expr, _)
252
528284
                | DeclarationKind::TemporaryValueLetting(expr) => eval_expr_to_int(expr),
253
                // If this is an int given we will be able to resolve it eventually, but not yet
254
18
                DeclarationKind::Given(_) => None,
255
200
                DeclarationKind::Quantified(inner) => {
256
200
                    if let Some(generator) = inner.generator()
257
                        && let Some(expr) = generator.as_value_letting()
258
                    {
259
                        eval_expr_to_int(&expr)
260
                    } else {
261
200
                        None
262
                    }
263
                }
264
                // TODO: idk what this whole file does but I very much doubt it affects this
265
                DeclarationKind::QuantifiedExpr(_) => None,
266
                // Decision variables inside domains are unresolved until solving.
267
1520
                DeclarationKind::Find(_) => None,
268
                DeclarationKind::DomainLetting(_) | DeclarationKind::Field(_) => bug!(
269
                    "Expected integer expression, given, or letting inside int domain; Got: {re}"
270
                ),
271
            },
272
        }
273
1145612
    }
274
}
275

            
276
586558
fn eval_expr_to_int(expr: &Expression) -> Option<Int> {
277
586558
    match eval_constant(expr)? {
278
579598
        Literal::Int(v) => Some(v),
279
        _ => bug!("Expected integer expression, got: {expr}"),
280
    }
281
586558
}
282

            
283
impl From<IntVal> for Expression {
284
1360
    fn from(value: IntVal) -> Self {
285
1360
        match value {
286
320
            IntVal::Const(val) => val.into(),
287
360
            IntVal::Reference(re) => re.into(),
288
680
            IntVal::Expr(expr) => expr.as_ref().clone(),
289
        }
290
1360
    }
291
}
292

            
293
impl From<IntVal> for Moo<Expression> {
294
86
    fn from(value: IntVal) -> Self {
295
86
        match value {
296
            IntVal::Const(val) => Moo::new(val.into()),
297
86
            IntVal::Reference(re) => Moo::new(re.into()),
298
            IntVal::Expr(expr) => expr,
299
        }
300
86
    }
301
}
302

            
303
impl std::ops::Neg for IntVal {
304
    type Output = IntVal;
305

            
306
8372
    fn neg(self) -> Self::Output {
307
8372
        match self {
308
8286
            IntVal::Const(val) => IntVal::Const(-val),
309
            IntVal::Reference(_) | IntVal::Expr(_) => {
310
86
                IntVal::Expr(Moo::new(Expression::Neg(Metadata::new(), self.into())))
311
            }
312
        }
313
8372
    }
314
}
315

            
316
impl<T> std::ops::Add<T> for IntVal
317
where
318
    T: Into<Expression>,
319
{
320
    type Output = IntVal;
321

            
322
    fn add(self, rhs: T) -> Self::Output {
323
        let lhs: Expression = self.into();
324
        let rhs: Expression = rhs.into();
325
        let sum = matrix_expr!(lhs, rhs; domain_int!(1..));
326
        IntVal::Expr(Moo::new(Expression::Sum(Metadata::new(), Moo::new(sum))))
327
    }
328
}
329

            
330
impl Range<IntVal> {
331
575800
    pub fn resolve(&self) -> Option<Range<Int>> {
332
575800
        match self {
333
7120
            Range::Single(x) => Some(Range::Single(x.resolve()?)),
334
568536
            Range::Bounded(l, r) => Some(Range::Bounded(l.resolve()?, r.resolve()?)),
335
20
            Range::UnboundedL(r) => Some(Range::UnboundedL(r.resolve()?)),
336
40
            Range::UnboundedR(l) => Some(Range::UnboundedR(l.resolve()?)),
337
84
            Range::Unbounded => Some(Range::Unbounded),
338
        }
339
575800
    }
340
}
341

            
342
impl SetAttr<IntVal> {
343
2
    pub fn resolve(&self) -> Option<SetAttr<Int>> {
344
        Some(SetAttr {
345
2
            size: self.size.resolve()?,
346
        })
347
2
    }
348
}
349

            
350
impl SequenceAttr<IntVal> {
351
    pub fn resolve(&self) -> Option<SequenceAttr<Int>> {
352
        Some(SequenceAttr {
353
            size: self.size.resolve()?,
354
            jectivity: self.jectivity.clone(),
355
        })
356
    }
357
}
358

            
359
impl MSetAttr<IntVal> {
360
4
    pub fn resolve(&self) -> Option<MSetAttr<Int>> {
361
        Some(MSetAttr {
362
4
            size: self.size.resolve()?,
363
4
            occurrence: self.occurrence.resolve()?,
364
        })
365
4
    }
366
}
367

            
368
impl PartitionAttr<IntVal> {
369
8
    pub fn resolve(&self) -> Option<PartitionAttr<Int>> {
370
        Some(PartitionAttr {
371
8
            num_parts: self.num_parts.resolve()?,
372
8
            part_len: self.part_len.resolve()?,
373
8
            is_regular: self.is_regular,
374
        })
375
8
    }
376
}
377

            
378
impl FuncAttr<IntVal> {
379
172
    pub fn resolve(&self) -> Option<FuncAttr<Int>> {
380
        Some(FuncAttr {
381
172
            size: self.size.resolve()?,
382
172
            partiality: self.partiality.clone(),
383
172
            jectivity: self.jectivity.clone(),
384
        })
385
172
    }
386
}
387

            
388
impl RelAttr<IntVal> {
389
2
    pub fn resolve(&self) -> Option<RelAttr<Int>> {
390
        Some(RelAttr {
391
2
            size: self.size.resolve()?,
392
2
            binary: self.binary.clone(),
393
        })
394
2
    }
395
}
396

            
397
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Uniplate, Quine)]
398
#[path_prefix(conjure_cp::ast)]
399
pub struct FieldEntry {
400
    pub name: Name,
401
    pub domain: DomainPtr,
402
}
403

            
404
impl FieldEntry {
405
    pub fn resolve(self) -> Option<FieldEntryGround> {
406
        Some(FieldEntryGround {
407
            name: self.name,
408
            domain: self.domain.resolve()?,
409
        })
410
    }
411
}
412

            
413
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
414
#[path_prefix(conjure_cp::ast)]
415
#[biplate(to=Expression)]
416
#[biplate(to=Reference)]
417
#[biplate(to=IntVal)]
418
#[biplate(to=DomainPtr)]
419
#[biplate(to=FieldEntry)]
420
pub enum UnresolvedDomain {
421
    Int(Vec<Range<IntVal>>),
422
    /// A set of elements drawn from the inner domain
423
    Set(SetAttr<IntVal>, DomainPtr),
424
    MSet(MSetAttr<IntVal>, DomainPtr),
425
    /// A n-dimensional matrix with a value domain and n-index domains
426
    Matrix(DomainPtr, Vec<DomainPtr>),
427
    /// A tuple of N elements, each with its own domain
428
    Tuple(Vec<DomainPtr>),
429
    Sequence(SequenceAttr<IntVal>, DomainPtr),
430
    /// A reference to a domain letting
431
    #[polyquine_skip]
432
    Reference(Reference),
433
    /// A record
434
    Record(Vec<FieldEntry>),
435
    /// A function with attributes, domain, and range
436
    Function(FuncAttr<IntVal>, DomainPtr, DomainPtr),
437
    /// A variant domain with its domain options (reusing field entries)
438
    Variant(Vec<FieldEntry>),
439
    /// A relation as a set of tuples
440
    Relation(RelAttr<IntVal>, Vec<DomainPtr>),
441
    Partition(PartitionAttr<IntVal>, DomainPtr),
442
}
443

            
444
impl UnresolvedDomain {
445
1456620
    pub fn resolve(&self) -> Option<GroundDomain> {
446
1456620
        match self {
447
575600
            UnresolvedDomain::Int(rngs) => rngs
448
575600
                .iter()
449
575600
                .map(Range::<IntVal>::resolve)
450
575600
                .collect::<Option<_>>()
451
575600
                .map(GroundDomain::Int),
452
            UnresolvedDomain::Set(attr, inner) => {
453
                Some(GroundDomain::Set(attr.resolve()?, inner.resolve()?))
454
            }
455
            UnresolvedDomain::MSet(attr, inner) => {
456
                Some(GroundDomain::MSet(attr.resolve()?, inner.resolve()?))
457
            }
458
            UnresolvedDomain::Partition(attr, inner) => {
459
                Some(GroundDomain::Partition(attr.resolve()?, inner.resolve()?))
460
            }
461
317700
            UnresolvedDomain::Matrix(inner, idx_doms) => {
462
317700
                let inner_gd = inner.resolve()?;
463
317700
                idx_doms
464
317700
                    .iter()
465
317700
                    .map(DomainPtr::resolve)
466
317700
                    .collect::<Option<_>>()
467
317700
                    .map(|idx| GroundDomain::Matrix(inner_gd, idx))
468
            }
469
            UnresolvedDomain::Sequence(attr, inner) => {
470
                Some(GroundDomain::Sequence(attr.resolve()?, inner.resolve()?))
471
            }
472
            UnresolvedDomain::Tuple(inners) => inners
473
                .iter()
474
                .map(DomainPtr::resolve)
475
                .collect::<Option<_>>()
476
                .map(GroundDomain::Tuple),
477
            UnresolvedDomain::Record(entries) => entries
478
                .iter()
479
                .map(|f| {
480
                    f.domain.resolve().map(|gd| FieldEntryGround {
481
                        name: f.name.clone(),
482
                        domain: gd,
483
                    })
484
                })
485
                .collect::<Option<_>>()
486
                .map(GroundDomain::Record),
487
563320
            UnresolvedDomain::Reference(re) => re
488
563320
                .ptr
489
563320
                .as_domain_letting()
490
563320
                .unwrap_or_else(|| {
491
                    bug!("Reference domain should point to domain letting, but got {re}")
492
                })
493
563320
                .resolve()
494
563320
                .map(Moo::unwrap_or_clone),
495
            UnresolvedDomain::Function(attr, dom, cdom) => {
496
                if let Some(attr_gd) = attr.resolve()
497
                    && let Some(dom_gd) = dom.resolve()
498
                    && let Some(cdom_gd) = cdom.resolve()
499
                {
500
                    return Some(GroundDomain::Function(attr_gd, dom_gd, cdom_gd));
501
                }
502
                None
503
            }
504
            UnresolvedDomain::Variant(entries) => entries
505
                .iter()
506
                .map(|f| {
507
                    f.domain.resolve().map(|gd| FieldEntryGround {
508
                        name: f.name.clone(),
509
                        domain: gd,
510
                    })
511
                })
512
                .collect::<Option<_>>()
513
                .map(GroundDomain::Variant),
514
            UnresolvedDomain::Relation(attr, inners) => {
515
                let resolved_attr = attr.resolve()?;
516
                inners
517
                    .iter()
518
                    .map(DomainPtr::resolve)
519
                    .collect::<Option<_>>()
520
                    .map(|items| GroundDomain::Relation(resolved_attr, items))
521
            }
522
        }
523
1456620
    }
524

            
525
    pub(super) fn union_unresolved(
526
        &self,
527
        other: &UnresolvedDomain,
528
    ) -> Result<UnresolvedDomain, DomainOpError> {
529
        match (self, other) {
530
            (UnresolvedDomain::Int(lhs), UnresolvedDomain::Int(rhs)) => {
531
                let merged = lhs.iter().chain(rhs.iter()).cloned().collect_vec();
532
                Ok(UnresolvedDomain::Int(merged))
533
            }
534
            (UnresolvedDomain::Int(_), _) | (_, UnresolvedDomain::Int(_)) => {
535
                Err(DomainOpError::WrongType)
536
            }
537
            (UnresolvedDomain::Set(_, in1), UnresolvedDomain::Set(_, in2)) => {
538
                Ok(UnresolvedDomain::Set(SetAttr::default(), in1.union(in2)?))
539
            }
540
            (UnresolvedDomain::Set(_, _), _) | (_, UnresolvedDomain::Set(_, _)) => {
541
                Err(DomainOpError::WrongType)
542
            }
543
            (UnresolvedDomain::MSet(_, in1), UnresolvedDomain::MSet(_, in2)) => {
544
                Ok(UnresolvedDomain::MSet(MSetAttr::default(), in1.union(in2)?))
545
            }
546
            (UnresolvedDomain::MSet(_, _), _) | (_, UnresolvedDomain::MSet(_, _)) => {
547
                Err(DomainOpError::WrongType)
548
            }
549
            (UnresolvedDomain::Matrix(in1, idx1), UnresolvedDomain::Matrix(in2, idx2))
550
                if idx1 == idx2 =>
551
            {
552
                Ok(UnresolvedDomain::Matrix(in1.union(in2)?, idx1.clone()))
553
            }
554
            (UnresolvedDomain::Matrix(_, _), _) | (_, UnresolvedDomain::Matrix(_, _)) => {
555
                Err(DomainOpError::WrongType)
556
            }
557
            (UnresolvedDomain::Tuple(lhs), UnresolvedDomain::Tuple(rhs))
558
                if lhs.len() == rhs.len() =>
559
            {
560
                let mut merged = Vec::new();
561
                for (l, r) in zip(lhs, rhs) {
562
                    merged.push(l.union(r)?)
563
                }
564
                Ok(UnresolvedDomain::Tuple(merged))
565
            }
566
            (UnresolvedDomain::Tuple(_), _) | (_, UnresolvedDomain::Tuple(_)) => {
567
                Err(DomainOpError::WrongType)
568
            }
569
            (UnresolvedDomain::Relation(_, in1s), UnresolvedDomain::Relation(_, in2s)) => {
570
                let mut inners = Vec::new();
571
                for (in1, in2) in in1s.iter().zip(in2s.iter()) {
572
                    inners.push(in1.union(in2)?)
573
                }
574
                Ok(UnresolvedDomain::Relation(RelAttr::default(), inners))
575
            }
576
            (UnresolvedDomain::Relation(_, _), _) | (_, UnresolvedDomain::Relation(_, _)) => {
577
                Err(DomainOpError::WrongType)
578
            }
579
            // TODO: Could we support unions of reference domains symbolically?
580
            (UnresolvedDomain::Reference(_), _) | (_, UnresolvedDomain::Reference(_)) => {
581
                Err(DomainOpError::NotGround)
582
            }
583
            // TODO: Could we define semantics for merging record domains?
584
            #[allow(unreachable_patterns)] // Technically redundant but logically makes sense
585
            (UnresolvedDomain::Record(_), _) | (_, UnresolvedDomain::Record(_)) => {
586
                Err(DomainOpError::WrongType)
587
            }
588
            #[allow(unreachable_patterns)]
589
            // Technically redundant but logically clearer to have both
590
            (UnresolvedDomain::Function(_, _, _), _) | (_, UnresolvedDomain::Function(_, _, _)) => {
591
                Err(DomainOpError::WrongType)
592
            }
593
            #[allow(unreachable_patterns)]
594
            // Technically redundant but logically clearer to have both
595
            (UnresolvedDomain::Partition(_, _), _) | (_, UnresolvedDomain::Partition(_, _)) => {
596
                Err(DomainOpError::WrongType)
597
            }
598
            #[allow(unreachable_patterns)]
599
            (UnresolvedDomain::Variant(_), _) | (_, UnresolvedDomain::Variant(_)) => {
600
                Err(DomainOpError::WrongType)
601
            }
602
            #[allow(unreachable_patterns)]
603
            (UnresolvedDomain::Sequence(_, _), _) | (_, UnresolvedDomain::Sequence(_, _)) => {
604
                Err(DomainOpError::WrongType)
605
            }
606
        }
607
    }
608

            
609
    pub fn element_domain(&self) -> Option<DomainPtr> {
610
        match self {
611
            UnresolvedDomain::Set(_, inner_dom) => Some(inner_dom.clone()),
612
            UnresolvedDomain::Sequence(_, inner_dom) => Some(inner_dom.clone()),
613
            UnresolvedDomain::Matrix(_, _) => {
614
                todo!("Unwrap one dimension of the domain")
615
            }
616
            _ => None,
617
        }
618
    }
619
}
620

            
621
impl Typeable for UnresolvedDomain {
622
86626
    fn return_type(&self) -> ReturnType {
623
86626
        match self {
624
18120
            UnresolvedDomain::Reference(re) => re.return_type(),
625
7246
            UnresolvedDomain::Int(_) => ReturnType::Int,
626
            UnresolvedDomain::Set(_attr, inner) => ReturnType::Set(Box::new(inner.return_type())),
627
            UnresolvedDomain::MSet(_attr, inner) => ReturnType::MSet(Box::new(inner.return_type())),
628
            UnresolvedDomain::Partition(_, inner) => {
629
                ReturnType::Partition(Box::new(inner.return_type()))
630
            }
631
            UnresolvedDomain::Sequence(_attr, inner) => {
632
                ReturnType::Sequence(Box::new(inner.return_type()))
633
            }
634
61260
            UnresolvedDomain::Matrix(inner, _idx) => {
635
61260
                ReturnType::Matrix(Box::new(inner.return_type()))
636
            }
637
            UnresolvedDomain::Tuple(inners) => {
638
                let mut inner_types = Vec::new();
639
                for inner in inners {
640
                    inner_types.push(inner.return_type());
641
                }
642
                ReturnType::Tuple(inner_types)
643
            }
644
            UnresolvedDomain::Record(entries) => {
645
                let mut entry_types = Vec::new();
646
                for entry in entries {
647
                    entry_types.push(entry.domain.return_type());
648
                }
649
                ReturnType::Record(entry_types)
650
            }
651
            UnresolvedDomain::Function(_, dom, cdom) => {
652
                ReturnType::Function(Box::new(dom.return_type()), Box::new(cdom.return_type()))
653
            }
654
            UnresolvedDomain::Variant(entries) => {
655
                let mut entry_types = Vec::new();
656
                for entry in entries {
657
                    entry_types.push(entry.domain.return_type());
658
                }
659
                ReturnType::Variant(entry_types)
660
            }
661
            UnresolvedDomain::Relation(_, inners) => {
662
                let mut inner_types = Vec::new();
663
                for inner in inners {
664
                    inner_types.push(inner.return_type());
665
                }
666
                ReturnType::Relation(inner_types)
667
            }
668
        }
669
86626
    }
670
}
671

            
672
impl Display for UnresolvedDomain {
673
13215372
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
674
13215372
        match &self {
675
5595210
            UnresolvedDomain::Reference(re) => write!(f, "{re}"),
676
3123174
            UnresolvedDomain::Int(ranges) => {
677
3123174
                if ranges.iter().all(Range::is_lower_or_upper_bounded) {
678
3123654
                    let rngs: String = ranges.iter().map(|r| format!("{r}")).join(", ");
679
3123174
                    write!(f, "int({})", rngs)
680
                } else {
681
                    write!(f, "int")
682
                }
683
            }
684
            UnresolvedDomain::Set(attrs, inner_dom) => write!(f, "set {attrs} of {inner_dom}"),
685
            UnresolvedDomain::MSet(attrs, inner_dom) => write!(f, "mset {attrs} of {inner_dom}"),
686
            UnresolvedDomain::Partition(attrs, inner_dom) => {
687
                write!(f, "partition {attrs} from {inner_dom}")
688
            }
689
            UnresolvedDomain::Sequence(attrs, inner_dom) => {
690
                write!(f, "sequence {attrs} of {inner_dom}")
691
            }
692
4496788
            UnresolvedDomain::Matrix(value_domain, index_domains) => {
693
4496788
                write!(
694
4496788
                    f,
695
                    "matrix indexed by {} of {value_domain}",
696
4496788
                    pretty_vec(&index_domains.iter().collect_vec())
697
                )
698
            }
699
80
            UnresolvedDomain::Tuple(domains) => {
700
80
                write!(f, "tuple ({})", &domains.iter().join(","))
701
            }
702
40
            UnresolvedDomain::Record(entries) => {
703
40
                write!(
704
40
                    f,
705
                    "record {{{}}}",
706
40
                    entries
707
40
                        .iter()
708
80
                        .map(|entry| format!("{}: {}", entry.name, entry.domain))
709
40
                        .join(", ")
710
                )
711
            }
712
            UnresolvedDomain::Function(attribute, domain, codomain) => {
713
                write!(f, "function {} {} --> {} ", attribute, domain, codomain)
714
            }
715
40
            UnresolvedDomain::Variant(entries) => {
716
40
                write!(
717
40
                    f,
718
                    "variant {{{}}}",
719
40
                    entries
720
40
                        .iter()
721
80
                        .map(|entry| format!("{}: {}", entry.name, entry.domain))
722
40
                        .join(", ")
723
                )
724
            }
725
40
            UnresolvedDomain::Relation(attrs, domains) => {
726
40
                write!(f, "relation {} of ({})", attrs, domains.iter().join(" * "))
727
            }
728
        }
729
13215372
    }
730
}