1
use itertools::Itertools;
2
use serde::{Deserialize, Serialize};
3
use std::fmt::{Display, Formatter};
4
use std::hash::Hash;
5
use ustr::Ustr;
6

            
7
use super::{
8
    Atom, Domain, DomainPtr, Expression, GroundDomain, Metadata, Moo, Range, ReturnType, SetAttr,
9
    Typeable, domains::HasDomain, domains::Int, records::RecordValue,
10
};
11
use crate::ast::domains::MSetAttr;
12
use crate::ast::pretty::pretty_vec;
13
use crate::bug;
14
use polyquine::Quine;
15
use uniplate::{Biplate, Tree, Uniplate};
16

            
17
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate, Hash, Quine)]
18
#[uniplate(walk_into=[AbstractLiteral<Literal>])]
19
#[biplate(to=Atom)]
20
#[biplate(to=AbstractLiteral<Literal>)]
21
#[biplate(to=AbstractLiteral<Expression>)]
22
#[biplate(to=RecordValue<Literal>)]
23
#[biplate(to=RecordValue<Expression>)]
24
#[biplate(to=Expression)]
25
#[path_prefix(conjure_cp::ast)]
26
/// A literal value, equivalent to constants in Conjure.
27
pub enum Literal {
28
    Int(i32),
29
    Bool(bool),
30
    //abstract literal variant ends in Literal, but that's ok
31
    #[allow(clippy::enum_variant_names)]
32
    AbstractLiteral(AbstractLiteral<Literal>),
33
}
34

            
35
impl HasDomain for Literal {
36
25223
    fn domain_of(&self) -> DomainPtr {
37
25223
        match self {
38
20042
            Literal::Int(i) => Domain::int(vec![Range::Single(*i)]),
39
3721
            Literal::Bool(_) => Domain::bool(),
40
1460
            Literal::AbstractLiteral(abstract_literal) => abstract_literal.domain_of(),
41
        }
42
25223
    }
43
}
44

            
45
// make possible values of an AbstractLiteral a closed world to make the trait bounds more sane (particularly in Uniplate instances!!)
46
pub trait AbstractLiteralValue:
47
    Clone + Eq + PartialEq + Display + Uniplate + Biplate<RecordValue<Self>> + 'static
48
{
49
    type Dom: Clone + Eq + PartialEq + Display + Quine + From<GroundDomain> + Into<DomainPtr>;
50
}
51
impl AbstractLiteralValue for Expression {
52
    type Dom = DomainPtr;
53
}
54
impl AbstractLiteralValue for Literal {
55
    type Dom = Moo<GroundDomain>;
56
}
57

            
58
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
59
#[path_prefix(conjure_cp::ast)]
60
pub enum AbstractLiteral<T: AbstractLiteralValue> {
61
    Set(Vec<T>),
62

            
63
    MSet(Vec<T>),
64

            
65
    /// A 1 dimensional matrix slice with an index domain.
66
    Matrix(Vec<T>, T::Dom),
67

            
68
    // a tuple of literals
69
    Tuple(Vec<T>),
70

            
71
    Record(Vec<RecordValue<T>>),
72

            
73
    Function(Vec<(T, T)>),
74
}
75

            
76
// TODO: use HasDomain instead once Expression::domain_of returns Domain not Option<Domain>
77
impl AbstractLiteral<Expression> {
78
160
    pub fn domain_of(&self) -> Option<DomainPtr> {
79
160
        match self {
80
            AbstractLiteral::Set(items) => {
81
                // ensure that all items have a domain, or return None
82
                let item_domains: Vec<DomainPtr> = items
83
                    .iter()
84
                    .map(|x| x.domain_of())
85
                    .collect::<Option<Vec<DomainPtr>>>()?;
86

            
87
                // union all item domains together
88
                let mut item_domain_iter = item_domains.iter().cloned();
89
                let first_item = item_domain_iter.next()?;
90
                let item_domain = item_domains
91
                    .iter()
92
                    .try_fold(first_item, |x, y| x.union(y))
93
                    .expect("taking the union of all item domains of a set literal should succeed");
94

            
95
                Some(Domain::set(SetAttr::<Int>::default(), item_domain))
96
            }
97

            
98
            AbstractLiteral::MSet(items) => {
99
                // ensure that all items have a domain, or return None
100
                let item_domains: Vec<DomainPtr> = items
101
                    .iter()
102
                    .map(|x| x.domain_of())
103
                    .collect::<Option<Vec<DomainPtr>>>()?;
104

            
105
                // union all item domains together
106
                let mut item_domain_iter = item_domains.iter().cloned();
107
                let first_item = item_domain_iter.next()?;
108
                let item_domain = item_domains
109
                    .iter()
110
                    .try_fold(first_item, |x, y| x.union(y))
111
                    .expect("taking the union of all item domains of a set literal should succeed");
112

            
113
                Some(Domain::mset(MSetAttr::<Int>::default(), item_domain))
114
            }
115

            
116
160
            AbstractLiteral::Matrix(items, _) => {
117
                // ensure that all items have a domain, or return None
118
160
                let item_domains = items
119
160
                    .iter()
120
540
                    .map(|x| x.domain_of())
121
160
                    .collect::<Option<Vec<DomainPtr>>>()?;
122

            
123
                // union all item domains together
124
160
                let mut item_domain_iter = item_domains.iter().cloned();
125

            
126
160
                let first_item = item_domain_iter.next()?;
127

            
128
160
                let item_domain = item_domains
129
160
                    .iter()
130
540
                    .try_fold(first_item, |x, y| x.union(y))
131
160
                    .expect(
132
160
                        "taking the union of all item domains of a matrix literal should succeed",
133
                    );
134

            
135
160
                let mut new_index_domain = vec![];
136

            
137
                // flatten index domains of n-d matrix into list
138
160
                let mut e = Expression::AbstractLiteral(Metadata::new(), self.clone());
139
180
                while let Expression::AbstractLiteral(_, AbstractLiteral::Matrix(elems, idx)) = e {
140
180
                    assert!(
141
180
                        idx.as_matrix().is_none(),
142
                        "n-dimensional matrix literals should be represented as a matrix inside a matrix, got {idx}"
143
                    );
144
180
                    new_index_domain.push(idx);
145
180
                    e = elems[0].clone();
146
                }
147
160
                Some(Domain::matrix(item_domain, new_index_domain))
148
            }
149
            AbstractLiteral::Tuple(_) => None,
150
            AbstractLiteral::Record(_) => None,
151
            AbstractLiteral::Function(_) => None,
152
        }
153
160
    }
154
}
155

            
156
impl HasDomain for AbstractLiteral<Literal> {
157
1460
    fn domain_of(&self) -> DomainPtr {
158
1460
        Domain::from_literal_vec(&[Literal::AbstractLiteral(self.clone())])
159
1460
            .expect("abstract literals should be correctly typed")
160
1460
    }
161
}
162

            
163
impl Typeable for AbstractLiteral<Expression> {
164
6300
    fn return_type(&self) -> ReturnType {
165
        match self {
166
            AbstractLiteral::Set(items) if items.is_empty() => {
167
                ReturnType::Set(Box::new(ReturnType::Unknown))
168
            }
169
            AbstractLiteral::Set(items) => {
170
                let item_type = items[0].return_type();
171

            
172
                // if any items do not have a type, return none.
173
                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
174

            
175
                assert!(
176
                    item_types.iter().all(|x| x == &item_type),
177
                    "all items in a set should have the same type"
178
                );
179

            
180
                ReturnType::Set(Box::new(item_type))
181
            }
182
            AbstractLiteral::MSet(items) if items.is_empty() => {
183
                ReturnType::MSet(Box::new(ReturnType::Unknown))
184
            }
185
            AbstractLiteral::MSet(items) => {
186
                let item_type = items[0].return_type();
187

            
188
                // if any items do not have a type, return none.
189
                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
190

            
191
                assert!(
192
                    item_types.iter().all(|x| x == &item_type),
193
                    "all items in a set should have the same type"
194
                );
195

            
196
                ReturnType::MSet(Box::new(item_type))
197
            }
198
6300
            AbstractLiteral::Matrix(items, _) if items.is_empty() => {
199
80
                ReturnType::Matrix(Box::new(ReturnType::Unknown))
200
            }
201
6220
            AbstractLiteral::Matrix(items, _) => {
202
6220
                let item_type = items[0].return_type();
203

            
204
                // if any items do not have a type, return none.
205
20700
                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
206

            
207
6220
                assert!(
208
20700
                    item_types.iter().all(|x| x == &item_type),
209
                    "all items in a matrix should have the same type. items: {items} types: {types:#?}",
210
                    items = pretty_vec(items),
211
                    types = items
212
                        .iter()
213
                        .map(|x| x.return_type())
214
                        .collect::<Vec<ReturnType>>()
215
                );
216

            
217
6220
                ReturnType::Matrix(Box::new(item_type))
218
            }
219
            AbstractLiteral::Tuple(items) => {
220
                let mut item_types = vec![];
221
                for item in items {
222
                    item_types.push(item.return_type());
223
                }
224
                ReturnType::Tuple(item_types)
225
            }
226
            AbstractLiteral::Record(items) => {
227
                let mut item_types = vec![];
228
                for item in items {
229
                    item_types.push(item.value.return_type());
230
                }
231
                ReturnType::Record(item_types)
232
            }
233
            AbstractLiteral::Function(items) => {
234
                if items.is_empty() {
235
                    return ReturnType::Function(
236
                        Box::new(ReturnType::Unknown),
237
                        Box::new(ReturnType::Unknown),
238
                    );
239
                }
240

            
241
                // Check that all items have the same return type
242
                let (x1, y1) = &items[0];
243
                let (t1, t2) = (x1.return_type(), y1.return_type());
244
                for (x, y) in items {
245
                    let (tx, ty) = (x.return_type(), y.return_type());
246
                    if tx != t1 {
247
                        bug!("Expected {t1}, got {x}: {tx}");
248
                    }
249
                    if ty != t2 {
250
                        bug!("Expected {t2}, got {y}: {ty}");
251
                    }
252
                }
253

            
254
                ReturnType::Function(Box::new(t1), Box::new(t2))
255
            }
256
        }
257
6300
    }
258
}
259

            
260
impl<T> AbstractLiteral<T>
261
where
262
    T: AbstractLiteralValue,
263
{
264
    /// Creates a matrix with elements `elems`, with domain `int(1..)`.
265
    ///
266
    /// This acts as a variable sized list.
267
61231
    pub fn matrix_implied_indices(elems: Vec<T>) -> Self {
268
61231
        AbstractLiteral::Matrix(elems, GroundDomain::Int(vec![Range::UnboundedR(1)]).into())
269
61231
    }
270

            
271
    /// If the AbstractLiteral is a list, returns its elements.
272
    ///
273
    /// A list is any a matrix with the domain `int(1..)`. This includes matrix literals without
274
    /// any explicitly specified domain.
275
289420
    pub fn unwrap_list(&self) -> Option<&Vec<T>> {
276
289420
        let AbstractLiteral::Matrix(elems, domain) = self else {
277
            return None;
278
        };
279

            
280
289420
        let domain: DomainPtr = domain.clone().into();
281
289420
        let Some(GroundDomain::Int(ranges)) = domain.as_ground() else {
282
            return None;
283
        };
284

            
285
289420
        let [Range::UnboundedR(1)] = ranges[..] else {
286
107000
            return None;
287
        };
288

            
289
182420
        Some(elems)
290
289420
    }
291
}
292

            
293
impl<T> Display for AbstractLiteral<T>
294
where
295
    T: AbstractLiteralValue,
296
{
297
130060
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
298
130060
        match self {
299
4440
            AbstractLiteral::Set(elems) => {
300
11440
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
301
4440
                write!(f, "{{{elems_str}}}")
302
            }
303
40
            AbstractLiteral::MSet(elems) => {
304
120
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
305
40
                write!(f, "mset({elems_str})")
306
            }
307
125260
            AbstractLiteral::Matrix(elems, index_domain) => {
308
289460
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
309
125260
                write!(f, "[{elems_str};{index_domain}]")
310
            }
311
160
            AbstractLiteral::Tuple(elems) => {
312
400
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
313
160
                write!(f, "({elems_str})")
314
            }
315
40
            AbstractLiteral::Record(entries) => {
316
40
                let entries_str: String = entries
317
40
                    .iter()
318
80
                    .map(|entry| format!("{}: {}", entry.name, entry.value))
319
40
                    .join(",");
320
40
                write!(f, "{{{entries_str}}}")
321
            }
322
120
            AbstractLiteral::Function(entries) => {
323
120
                let entries_str: String = entries
324
120
                    .iter()
325
240
                    .map(|entry| format!("{} --> {}", entry.0, entry.1))
326
120
                    .join(",");
327
120
                write!(f, "function({entries_str})")
328
            }
329
        }
330
130060
    }
331
}
332

            
333
impl<T> Uniplate for AbstractLiteral<T>
334
where
335
    T: AbstractLiteralValue + Biplate<AbstractLiteral<T>>,
336
{
337
526
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
338
        // walking into T
339
526
        match self {
340
            AbstractLiteral::Set(vec) => {
341
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
342
                (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
343
            }
344
            AbstractLiteral::MSet(vec) => {
345
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
346
                (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
347
            }
348
526
            AbstractLiteral::Matrix(elems, index_domain) => {
349
526
                let index_domain = index_domain.clone();
350
526
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
351
                (
352
526
                    f1_tree,
353
526
                    Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
354
                )
355
            }
356
            AbstractLiteral::Tuple(elems) => {
357
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
358
                (
359
                    f1_tree,
360
                    Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
361
                )
362
            }
363
            AbstractLiteral::Record(entries) => {
364
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
365
                (
366
                    f1_tree,
367
                    Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
368
                )
369
            }
370
            AbstractLiteral::Function(entries) => {
371
                let entry_count = entries.len();
372
                let flattened: Vec<T> = entries
373
                    .iter()
374
                    .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
375
                    .collect();
376

            
377
                let (f1_tree, f1_ctx) =
378
                    <Vec<T> as Biplate<AbstractLiteral<T>>>::biplate(&flattened);
379
                (
380
                    f1_tree,
381
                    Box::new(move |x| {
382
                        let rebuilt = f1_ctx(x);
383
                        assert_eq!(
384
                            rebuilt.len(),
385
                            entry_count * 2,
386
                            "number of function literal children should remain unchanged"
387
                        );
388

            
389
                        let mut iter = rebuilt.into_iter();
390
                        let mut pairs = Vec::with_capacity(entry_count);
391
                        while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
392
                            pairs.push((lhs, rhs));
393
                        }
394

            
395
                        AbstractLiteral::Function(pairs)
396
                    }),
397
                )
398
            }
399
        }
400
526
    }
401
}
402

            
403
impl<U, To> Biplate<To> for AbstractLiteral<U>
404
where
405
    To: Uniplate,
406
    U: AbstractLiteralValue + Biplate<AbstractLiteral<U>> + Biplate<To>,
407
    RecordValue<U>: Biplate<AbstractLiteral<U>> + Biplate<To>,
408
{
409
2273385
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
410
2273385
        if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
411
            // To ==From => return One(self)
412

            
413
            unsafe {
414
                // SAFETY: asserted the type equality above
415
245
                let self_to = std::mem::transmute::<&AbstractLiteral<U>, &To>(self).clone();
416
245
                let tree = Tree::One(self_to);
417
245
                let ctx = Box::new(move |x| {
418
                    let Tree::One(x) = x else {
419
                        panic!();
420
                    };
421

            
422
                    std::mem::transmute::<&To, &AbstractLiteral<U>>(&x).clone()
423
                });
424

            
425
245
                (tree, ctx)
426
            }
427
        } else {
428
            // walking into T
429
2273140
            match self {
430
15520
                AbstractLiteral::Set(vec) => {
431
15520
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
432
15520
                    (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
433
                }
434
180
                AbstractLiteral::MSet(vec) => {
435
180
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
436
180
                    (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
437
                }
438
2250380
                AbstractLiteral::Matrix(elems, index_domain) => {
439
2250380
                    let index_domain = index_domain.clone();
440
2250380
                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(elems);
441
                    (
442
2250380
                        f1_tree,
443
2250380
                        Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
444
                    )
445
                }
446
2080
                AbstractLiteral::Tuple(elems) => {
447
2080
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
448
                    (
449
2080
                        f1_tree,
450
2080
                        Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
451
                    )
452
                }
453
4380
                AbstractLiteral::Record(entries) => {
454
4380
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
455
                    (
456
4380
                        f1_tree,
457
4380
                        Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
458
                    )
459
                }
460
600
                AbstractLiteral::Function(entries) => {
461
600
                    let entry_count = entries.len();
462
600
                    let flattened: Vec<U> = entries
463
600
                        .iter()
464
1200
                        .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
465
600
                        .collect();
466

            
467
600
                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(&flattened);
468
                    (
469
600
                        f1_tree,
470
600
                        Box::new(move |x| {
471
                            let rebuilt = f1_ctx(x);
472
                            assert_eq!(
473
                                rebuilt.len(),
474
                                entry_count * 2,
475
                                "number of function literal children should remain unchanged"
476
                            );
477

            
478
                            let mut iter = rebuilt.into_iter();
479
                            let mut pairs = Vec::with_capacity(entry_count);
480
                            while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
481
                                pairs.push((lhs, rhs));
482
                            }
483

            
484
                            AbstractLiteral::Function(pairs)
485
                        }),
486
                    )
487
                }
488
            }
489
        }
490
2273385
    }
491
}
492

            
493
impl TryFrom<Literal> for i32 {
494
    type Error = &'static str;
495

            
496
31120
    fn try_from(value: Literal) -> Result<Self, Self::Error> {
497
31120
        match value {
498
26620
            Literal::Int(i) => Ok(i),
499
4500
            _ => Err("Cannot convert non-i32 literal to i32"),
500
        }
501
31120
    }
502
}
503

            
504
impl TryFrom<Box<Literal>> for i32 {
505
    type Error = &'static str;
506

            
507
    fn try_from(value: Box<Literal>) -> Result<Self, Self::Error> {
508
        (*value).try_into()
509
    }
510
}
511

            
512
impl TryFrom<&Box<Literal>> for i32 {
513
    type Error = &'static str;
514

            
515
180
    fn try_from(value: &Box<Literal>) -> Result<Self, Self::Error> {
516
180
        TryFrom::<&Literal>::try_from(value.as_ref())
517
180
    }
518
}
519

            
520
impl TryFrom<&Moo<Literal>> for i32 {
521
    type Error = &'static str;
522

            
523
    fn try_from(value: &Moo<Literal>) -> Result<Self, Self::Error> {
524
        TryFrom::<&Literal>::try_from(value.as_ref())
525
    }
526
}
527

            
528
impl TryFrom<&Literal> for i32 {
529
    type Error = &'static str;
530

            
531
60580
    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
532
60580
        match value {
533
60580
            Literal::Int(i) => Ok(*i),
534
            _ => Err("Cannot convert non-i32 literal to i32"),
535
        }
536
60580
    }
537
}
538

            
539
impl TryFrom<Literal> for bool {
540
    type Error = &'static str;
541

            
542
10020
    fn try_from(value: Literal) -> Result<Self, Self::Error> {
543
10020
        match value {
544
9180
            Literal::Bool(b) => Ok(b),
545
840
            _ => Err("Cannot convert non-bool literal to bool"),
546
        }
547
10020
    }
548
}
549

            
550
impl TryFrom<&Literal> for bool {
551
    type Error = &'static str;
552

            
553
20
    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
554
20
        match value {
555
20
            Literal::Bool(b) => Ok(*b),
556
            _ => Err("Cannot convert non-bool literal to bool"),
557
        }
558
20
    }
559
}
560

            
561
impl From<i32> for Literal {
562
316596
    fn from(i: i32) -> Self {
563
316596
        Literal::Int(i)
564
316596
    }
565
}
566

            
567
impl From<bool> for Literal {
568
5948
    fn from(b: bool) -> Self {
569
5948
        Literal::Bool(b)
570
5948
    }
571
}
572

            
573
impl From<Literal> for Ustr {
574
440
    fn from(value: Literal) -> Self {
575
        // TODO: avoid the temporary-allocation of a string by format! here?
576
440
        Ustr::from(&format!("{value}"))
577
440
    }
578
}
579

            
580
impl AbstractLiteral<Expression> {
581
    /// If all the elements are literals, returns this as an AbstractLiteral<Literal>.
582
    /// Otherwise, returns `None`.
583
111780
    pub fn into_literals(self) -> Option<AbstractLiteral<Literal>> {
584
111780
        match self {
585
2040
            AbstractLiteral::Set(elements) => {
586
2040
                let literals = elements
587
2040
                    .into_iter()
588
5120
                    .map(|expr| match expr {
589
5120
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
590
                        Expression::AbstractLiteral(_, abslit) => {
591
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
592
                        }
593
                        _ => None,
594
5120
                    })
595
2040
                    .collect::<Option<Vec<_>>>()?;
596
2040
                Some(AbstractLiteral::Set(literals))
597
            }
598
            AbstractLiteral::MSet(elements) => {
599
                let literals = elements
600
                    .into_iter()
601
                    .map(|expr| match expr {
602
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
603
                        Expression::AbstractLiteral(_, abslit) => {
604
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
605
                        }
606
                        _ => None,
607
                    })
608
                    .collect::<Option<Vec<_>>>()?;
609
                Some(AbstractLiteral::MSet(literals))
610
            }
611
109660
            AbstractLiteral::Matrix(items, domain) => {
612
109660
                let mut literals = vec![];
613
123720
                for item in items {
614
70060
                    let literal = match item {
615
19540
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
616
740
                        Expression::AbstractLiteral(_, abslit) => {
617
740
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
618
                        }
619
103440
                        _ => None,
620
103440
                    }?;
621
19780
                    literals.push(literal);
622
                }
623

            
624
5720
                Some(AbstractLiteral::Matrix(literals, domain.resolve()?))
625
            }
626
60
            AbstractLiteral::Tuple(items) => {
627
60
                let mut literals = vec![];
628
120
                for item in items {
629
120
                    let literal = match item {
630
120
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
631
                        Expression::AbstractLiteral(_, abslit) => {
632
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
633
                        }
634
                        _ => None,
635
                    }?;
636
120
                    literals.push(literal);
637
                }
638

            
639
60
                Some(AbstractLiteral::Tuple(literals))
640
            }
641
20
            AbstractLiteral::Record(entries) => {
642
20
                let mut literals = vec![];
643
40
                for entry in entries {
644
40
                    let literal = match entry.value {
645
40
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
646
                        Expression::AbstractLiteral(_, abslit) => {
647
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
648
                        }
649
                        _ => None,
650
                    }?;
651

            
652
40
                    literals.push((entry.name, literal));
653
                }
654
                Some(AbstractLiteral::Record(
655
20
                    literals
656
20
                        .into_iter()
657
20
                        .map(|(name, literal)| RecordValue {
658
40
                            name,
659
40
                            value: literal,
660
40
                        })
661
20
                        .collect(),
662
                ))
663
            }
664
            AbstractLiteral::Function(_) => todo!("Implement into_literals for functions"),
665
        }
666
111780
    }
667
}
668

            
669
// need display implementations for other types as well
670
impl Display for Literal {
671
772464
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
672
772464
        match &self {
673
749940
            Literal::Int(i) => write!(f, "{i}"),
674
18104
            Literal::Bool(b) => write!(f, "{b}"),
675
4420
            Literal::AbstractLiteral(l) => write!(f, "{l:?}"),
676
        }
677
772464
    }
678
}
679

            
680
#[cfg(test)]
681
mod tests {
682

            
683
    use super::*;
684
    use crate::{into_matrix, matrix};
685
    use uniplate::Uniplate;
686

            
687
    #[test]
688
1
    fn matrix_uniplate_universe() {
689
        // Can we traverse through matrices with uniplate?
690
1
        let my_matrix: AbstractLiteral<Literal> = into_matrix![
691
1
            vec![Literal::AbstractLiteral(matrix![Literal::Bool(true);Moo::new(GroundDomain::Bool)]); 5];
692
1
            Moo::new(GroundDomain::Bool)
693
        ];
694

            
695
1
        let expected_index_domains = vec![Moo::new(GroundDomain::Bool); 6];
696
1
        let actual_index_domains: Vec<Moo<GroundDomain>> =
697
6
            my_matrix.cata(&move |elem, children| {
698
6
                let mut res = vec![];
699
6
                res.extend(children.into_iter().flatten());
700
6
                if let AbstractLiteral::Matrix(_, index_domain) = elem {
701
6
                    res.push(index_domain);
702
6
                }
703

            
704
6
                res
705
6
            });
706

            
707
1
        assert_eq!(actual_index_domains, expected_index_domains);
708
1
    }
709
}