1
use std::fmt::{Display, Formatter};
2
use std::iter::zip;
3

            
4
use crate::ast::domains::attrs::MSetAttr;
5
use crate::ast::domains::attrs::PartitionAttr;
6
use crate::ast::domains::attrs::SetAttr;
7
use crate::ast::domains::ground::FieldGround;
8
use crate::ast::records::Field;
9
use crate::ast::{
10
    DomainOpError, Expression, FuncAttr, Moo, Reference, RelAttr, ReturnType, SequenceAttr,
11
    Typeable,
12
    domains::{DomainPtr, GroundDomain, int_val::IntVal, range::Range},
13
    pretty::pretty_vec,
14
};
15
use crate::bug;
16

            
17
use funcmap::{FuncMap, TryFuncMap};
18
use itertools::Itertools;
19
use polyquine::Quine;
20
use serde::{Deserialize, Serialize};
21
use uniplate::Uniplate;
22

            
23
pub(super) type FieldUnresolved = Field<DomainPtr>;
24

            
25
impl From<FieldGround> for FieldUnresolved {
26
1
    fn from(v: FieldGround) -> Self {
27
1
        v.func_map(DomainPtr::from)
28
1
    }
29
}
30

            
31
impl TryFrom<FieldUnresolved> for FieldGround {
32
    type Error = DomainOpError;
33
803
    fn try_from(v: FieldUnresolved) -> Result<Self, Self::Error> {
34
803
        v.try_func_map(DomainPtr::try_into)
35
803
    }
36
}
37

            
38
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine, Uniplate)]
39
#[path_prefix(conjure_cp::ast)]
40
#[biplate(to=Expression)]
41
#[biplate(to=Reference)]
42
#[biplate(to=IntVal)]
43
#[biplate(to=DomainPtr)]
44
pub enum UnresolvedDomain {
45
    Int(Vec<Range<IntVal>>),
46
    /// A set of elements drawn from the inner domain
47
    Set(SetAttr<IntVal>, DomainPtr),
48
    MSet(MSetAttr<IntVal>, DomainPtr),
49
    /// A n-dimensional matrix with a value domain and n-index domains
50
    Matrix(DomainPtr, Vec<DomainPtr>),
51
    /// A tuple of N elements, each with its own domain
52
    Tuple(Vec<DomainPtr>),
53
    Sequence(SequenceAttr<IntVal>, DomainPtr),
54
    /// A reference to a domain letting
55
    #[polyquine_skip]
56
    Reference(Reference),
57
    /// A record
58
    Record(Vec<FieldUnresolved>),
59
    /// A function with attributes, domain, and range
60
    Function(FuncAttr<IntVal>, DomainPtr, DomainPtr),
61
    /// A variant domain with its domain options (reusing field entries)
62
    Variant(Vec<FieldUnresolved>),
63
    /// A relation as a set of tuples
64
    Relation(RelAttr<IntVal>, Vec<DomainPtr>),
65
    Partition(PartitionAttr<IntVal>, DomainPtr),
66
}
67

            
68
impl UnresolvedDomain {
69
1940112
    pub fn resolve(&self) -> Result<GroundDomain, DomainOpError> {
70
1940112
        match self {
71
889696
            UnresolvedDomain::Int(rngs) => rngs
72
889696
                .iter()
73
889696
                .map(Range::<IntVal>::resolve)
74
889696
                .collect::<Result<_, _>>()
75
889696
                .map(GroundDomain::Int),
76
            UnresolvedDomain::Set(attr, inner) => {
77
                Ok(GroundDomain::Set(attr.resolve()?, inner.resolve()?))
78
            }
79
            UnresolvedDomain::MSet(attr, inner) => {
80
                Ok(GroundDomain::MSet(attr.resolve()?, inner.resolve()?))
81
            }
82
            UnresolvedDomain::Partition(attr, inner) => {
83
                Ok(GroundDomain::Partition(attr.resolve()?, inner.resolve()?))
84
            }
85
404668
            UnresolvedDomain::Matrix(inner, idx_doms) => {
86
404668
                let inner_gd = inner.resolve()?;
87
404668
                idx_doms
88
404668
                    .iter()
89
404668
                    .map(DomainPtr::resolve)
90
404668
                    .collect::<Result<_, _>>()
91
404668
                    .map(|idx| GroundDomain::Matrix(inner_gd, idx))
92
            }
93
            UnresolvedDomain::Sequence(attr, inner) => {
94
                Ok(GroundDomain::Sequence(attr.resolve()?, inner.resolve()?))
95
            }
96
            UnresolvedDomain::Tuple(inners) => inners
97
                .iter()
98
                .map(DomainPtr::resolve)
99
                .collect::<Result<_, _>>()
100
                .map(GroundDomain::Tuple),
101
            UnresolvedDomain::Record(entries) => entries
102
                .iter()
103
                .map(|f| {
104
                    f.value.resolve().map(|gd| FieldGround {
105
                        name: f.name.clone(),
106
                        value: gd,
107
                    })
108
                })
109
                .collect::<Result<_, _>>()
110
                .map(GroundDomain::Record),
111
645748
            UnresolvedDomain::Reference(re) => re
112
645748
                .ptr
113
645748
                .as_domain_letting()
114
645748
                .unwrap_or_else(|| {
115
                    bug!("Reference domain should point to domain letting, but got {re}")
116
                })
117
645748
                .resolve()
118
645748
                .map(Moo::unwrap_or_clone),
119
            UnresolvedDomain::Function(attr, dom, cdom) => Ok(GroundDomain::Function(
120
                attr.resolve()?,
121
                dom.resolve()?,
122
                cdom.resolve()?,
123
            )),
124
            UnresolvedDomain::Variant(entries) => entries
125
                .iter()
126
                .map(|f| {
127
                    f.value.resolve().map(|gd| FieldGround {
128
                        name: f.name.clone(),
129
                        value: gd,
130
                    })
131
                })
132
                .collect::<Result<_, _>>()
133
                .map(GroundDomain::Variant),
134
            UnresolvedDomain::Relation(attr, inners) => {
135
                let resolved_attr = attr.resolve()?;
136
                inners
137
                    .iter()
138
                    .map(DomainPtr::resolve)
139
                    .collect::<Result<_, _>>()
140
                    .map(|items| GroundDomain::Relation(resolved_attr, items))
141
            }
142
        }
143
1940112
    }
144

            
145
    pub(super) fn union_unresolved(
146
        &self,
147
        other: &UnresolvedDomain,
148
    ) -> Result<UnresolvedDomain, DomainOpError> {
149
        match (self, other) {
150
            (UnresolvedDomain::Int(lhs), UnresolvedDomain::Int(rhs)) => {
151
                let merged = lhs.iter().chain(rhs.iter()).cloned().collect_vec();
152
                Ok(UnresolvedDomain::Int(merged))
153
            }
154
            (UnresolvedDomain::Int(_), _) | (_, UnresolvedDomain::Int(_)) => {
155
                Err(DomainOpError::WrongType)
156
            }
157
            (UnresolvedDomain::Set(_, in1), UnresolvedDomain::Set(_, in2)) => {
158
                Ok(UnresolvedDomain::Set(SetAttr::default(), in1.union(in2)?))
159
            }
160
            (UnresolvedDomain::Set(_, _), _) | (_, UnresolvedDomain::Set(_, _)) => {
161
                Err(DomainOpError::WrongType)
162
            }
163
            (UnresolvedDomain::MSet(_, in1), UnresolvedDomain::MSet(_, in2)) => {
164
                Ok(UnresolvedDomain::MSet(MSetAttr::default(), in1.union(in2)?))
165
            }
166
            (UnresolvedDomain::MSet(_, _), _) | (_, UnresolvedDomain::MSet(_, _)) => {
167
                Err(DomainOpError::WrongType)
168
            }
169
            (UnresolvedDomain::Matrix(in1, idx1), UnresolvedDomain::Matrix(in2, idx2))
170
                if idx1 == idx2 =>
171
            {
172
                Ok(UnresolvedDomain::Matrix(in1.union(in2)?, idx1.clone()))
173
            }
174
            (UnresolvedDomain::Matrix(_, _), _) | (_, UnresolvedDomain::Matrix(_, _)) => {
175
                Err(DomainOpError::WrongType)
176
            }
177
            (UnresolvedDomain::Tuple(lhs), UnresolvedDomain::Tuple(rhs))
178
                if lhs.len() == rhs.len() =>
179
            {
180
                let mut merged = Vec::new();
181
                for (l, r) in zip(lhs, rhs) {
182
                    merged.push(l.union(r)?)
183
                }
184
                Ok(UnresolvedDomain::Tuple(merged))
185
            }
186
            (UnresolvedDomain::Tuple(_), _) | (_, UnresolvedDomain::Tuple(_)) => {
187
                Err(DomainOpError::WrongType)
188
            }
189
            (UnresolvedDomain::Relation(_, in1s), UnresolvedDomain::Relation(_, in2s)) => {
190
                let mut inners = Vec::new();
191
                for (in1, in2) in in1s.iter().zip(in2s.iter()) {
192
                    inners.push(in1.union(in2)?)
193
                }
194
                Ok(UnresolvedDomain::Relation(RelAttr::default(), inners))
195
            }
196
            (UnresolvedDomain::Relation(_, _), _) | (_, UnresolvedDomain::Relation(_, _)) => {
197
                Err(DomainOpError::WrongType)
198
            }
199
            // TODO: Could we support unions of reference domains symbolically?
200
            (UnresolvedDomain::Reference(_), _) | (_, UnresolvedDomain::Reference(_)) => {
201
                Err(DomainOpError::NotGround)
202
            }
203
            // TODO: Could we define semantics for merging record domains?
204
            #[allow(unreachable_patterns)]
205
            (UnresolvedDomain::Record(_), _) | (_, UnresolvedDomain::Record(_)) => {
206
                Err(DomainOpError::WrongType)
207
            }
208
            #[allow(unreachable_patterns)]
209
            (UnresolvedDomain::Function(_, _, _), _) | (_, UnresolvedDomain::Function(_, _, _)) => {
210
                Err(DomainOpError::WrongType)
211
            }
212
            #[allow(unreachable_patterns)]
213
            (UnresolvedDomain::Partition(_, _), _) | (_, UnresolvedDomain::Partition(_, _)) => {
214
                Err(DomainOpError::WrongType)
215
            }
216
            #[allow(unreachable_patterns)]
217
            (UnresolvedDomain::Variant(_), _) | (_, UnresolvedDomain::Variant(_)) => {
218
                Err(DomainOpError::WrongType)
219
            }
220
            #[allow(unreachable_patterns)]
221
            (UnresolvedDomain::Sequence(_, _), _) | (_, UnresolvedDomain::Sequence(_, _)) => {
222
                Err(DomainOpError::WrongType)
223
            }
224
        }
225
    }
226

            
227
    pub fn element_domain(&self) -> Option<DomainPtr> {
228
        match self {
229
            UnresolvedDomain::Set(_, inner_dom) => Some(inner_dom.clone()),
230
            UnresolvedDomain::Sequence(_, inner_dom) => Some(inner_dom.clone()),
231
            UnresolvedDomain::Matrix(_, _) => {
232
                todo!("Unwrap one dimension of the domain")
233
            }
234
            _ => None,
235
        }
236
    }
237
}
238

            
239
impl Typeable for UnresolvedDomain {
240
107736
    fn return_type(&self) -> ReturnType {
241
107736
        match self {
242
19320
            UnresolvedDomain::Reference(re) => re.return_type(),
243
11324
            UnresolvedDomain::Int(_) => ReturnType::Int,
244
            UnresolvedDomain::Set(_attr, inner) => ReturnType::Set(Box::new(inner.return_type())),
245
            UnresolvedDomain::MSet(_attr, inner) => ReturnType::MSet(Box::new(inner.return_type())),
246
            UnresolvedDomain::Partition(_, inner) => {
247
                ReturnType::Partition(Box::new(inner.return_type()))
248
            }
249
            UnresolvedDomain::Sequence(_attr, inner) => {
250
                ReturnType::Sequence(Box::new(inner.return_type()))
251
            }
252
77092
            UnresolvedDomain::Matrix(inner, _idx) => {
253
77092
                ReturnType::Matrix(Box::new(inner.return_type()))
254
            }
255
            UnresolvedDomain::Tuple(inners) => {
256
                let mut inner_types = Vec::new();
257
                for inner in inners {
258
                    inner_types.push(inner.return_type());
259
                }
260
                ReturnType::Tuple(inner_types)
261
            }
262
            UnresolvedDomain::Record(entries) => {
263
                let mut entry_types = Vec::new();
264
                for entry in entries {
265
                    entry_types.push(entry.clone().func_map(|x| x.return_type()));
266
                }
267
                ReturnType::Record(entry_types)
268
            }
269
            UnresolvedDomain::Variant(entries) => {
270
                let mut entry_types = Vec::new();
271
                for entry in entries {
272
                    entry_types.push(entry.clone().func_map(|x| x.return_type()));
273
                }
274
                ReturnType::Variant(entry_types)
275
            }
276
            UnresolvedDomain::Function(_, dom, cdom) => {
277
                ReturnType::Function(Box::new(dom.return_type()), Box::new(cdom.return_type()))
278
            }
279
            UnresolvedDomain::Relation(_, inners) => {
280
                let mut inner_types = Vec::new();
281
                for inner in inners {
282
                    inner_types.push(inner.return_type());
283
                }
284
                ReturnType::Relation(inner_types)
285
            }
286
        }
287
107736
    }
288
}
289

            
290
impl Display for FieldUnresolved {
291
160
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
292
160
        write!(f, "{}: {}", self.name, self.value)
293
160
    }
294
}
295

            
296
impl Display for UnresolvedDomain {
297
14522964
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
298
14522964
        match &self {
299
5549744
            UnresolvedDomain::Reference(re) => write!(f, "{re}"),
300
4088780
            UnresolvedDomain::Int(ranges) => {
301
4088780
                if ranges.iter().all(Range::is_lower_or_upper_bounded) {
302
4089260
                    let rngs: String = ranges.iter().map(|r| format!("{r}")).join(", ");
303
4088780
                    write!(f, "int({})", rngs)
304
                } else {
305
                    write!(f, "int")
306
                }
307
            }
308
            UnresolvedDomain::Set(attrs, inner_dom) => write!(f, "set {attrs} of {inner_dom}"),
309
            UnresolvedDomain::MSet(attrs, inner_dom) => write!(f, "mset {attrs} of {inner_dom}"),
310
            UnresolvedDomain::Partition(attrs, inner_dom) => {
311
                write!(f, "partition {attrs} from {inner_dom}")
312
            }
313
            UnresolvedDomain::Sequence(attrs, inner_dom) => {
314
                write!(f, "sequence {attrs} of {inner_dom}")
315
            }
316
4884240
            UnresolvedDomain::Matrix(value_domain, index_domains) => {
317
4884240
                write!(
318
4884240
                    f,
319
                    "matrix indexed by {} of {value_domain}",
320
4884240
                    pretty_vec(&index_domains.iter().collect_vec())
321
                )
322
            }
323
80
            UnresolvedDomain::Tuple(domains) => {
324
80
                write!(f, "tuple ({})", &domains.iter().join(","))
325
            }
326
40
            UnresolvedDomain::Record(entries) => {
327
80
                let inners = entries.iter().map(|t| format!("{}", t)).join(", ");
328
40
                write!(f, "record {{{inners}}}",)
329
            }
330
40
            UnresolvedDomain::Variant(entries) => {
331
80
                let inners = entries.iter().map(|t| format!("{}", t)).join(", ");
332
40
                write!(f, "variant {{{inners}}}",)
333
            }
334
            UnresolvedDomain::Function(attribute, domain, codomain) => {
335
                write!(f, "function {} {} --> {} ", attribute, domain, codomain)
336
            }
337
40
            UnresolvedDomain::Relation(attrs, domains) => {
338
40
                write!(f, "relation {} of ({})", attrs, domains.iter().join(" * "))
339
            }
340
        }
341
14522964
    }
342
}