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
327593
    fn domain_of(&self) -> DomainPtr {
37
327593
        match self {
38
256811
            Literal::Int(i) => Domain::int(vec![Range::Single(*i)]),
39
68325
            Literal::Bool(_) => Domain::bool(),
40
2457
            Literal::AbstractLiteral(abstract_literal) => abstract_literal.domain_of(),
41
        }
42
327593
    }
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
39415
    pub fn domain_of(&self) -> Option<DomainPtr> {
79
39415
        match self {
80
2798
            AbstractLiteral::Set(items) => {
81
                // ensure that all items have a domain, or return None
82
2798
                let item_domains: Vec<DomainPtr> = items
83
2798
                    .iter()
84
6899
                    .map(|x| x.domain_of())
85
2798
                    .collect::<Option<Vec<DomainPtr>>>()?;
86

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

            
95
2798
                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
36578
            AbstractLiteral::Matrix(items, _) => {
117
                // ensure that all items have a domain, or return None
118
36578
                let item_domains = items
119
36578
                    .iter()
120
303369
                    .map(|x| x.domain_of())
121
36578
                    .collect::<Option<Vec<DomainPtr>>>()?;
122

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

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

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

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

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

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

            
163
impl Typeable for AbstractLiteral<Expression> {
164
21488
    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
21488
            AbstractLiteral::Matrix(items, _) if items.is_empty() => {
199
156
                ReturnType::Matrix(Box::new(ReturnType::Unknown))
200
            }
201
21332
            AbstractLiteral::Matrix(items, _) => {
202
21332
                let item_type = items[0].return_type();
203

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

            
207
21332
                assert!(
208
101550
                    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
21332
                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
21488
    }
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
639726
    pub fn matrix_implied_indices(elems: Vec<T>) -> Self {
268
639726
        AbstractLiteral::Matrix(elems, GroundDomain::Int(vec![Range::UnboundedR(1)]).into())
269
639726
    }
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
3972777
    pub fn unwrap_list(&self) -> Option<&Vec<T>> {
276
3972777
        let AbstractLiteral::Matrix(elems, domain) = self else {
277
            return None;
278
        };
279

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

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

            
289
2704458
        Some(elems)
290
3972777
    }
291
}
292

            
293
impl<T> Display for AbstractLiteral<T>
294
where
295
    T: AbstractLiteralValue,
296
{
297
1924635
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
298
1924635
        match self {
299
8544
            AbstractLiteral::Set(elems) => {
300
22080
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
301
8544
                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
1915541
            AbstractLiteral::Matrix(elems, index_domain) => {
308
6372775
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
309
1915541
                write!(f, "[{elems_str};{index_domain}]")
310
            }
311
312
            AbstractLiteral::Tuple(elems) => {
312
780
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
313
312
                write!(f, "({elems_str})")
314
            }
315
78
            AbstractLiteral::Record(entries) => {
316
78
                let entries_str: String = entries
317
78
                    .iter()
318
156
                    .map(|entry| format!("{}: {}", entry.name, entry.value))
319
78
                    .join(",");
320
78
                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
1924635
    }
331
}
332

            
333
impl<T> Uniplate for AbstractLiteral<T>
334
where
335
    T: AbstractLiteralValue + Biplate<AbstractLiteral<T>>,
336
{
337
1026
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
338
        // walking into T
339
1026
        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
1026
            AbstractLiteral::Matrix(elems, index_domain) => {
349
1026
                let index_domain = index_domain.clone();
350
1026
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
351
                (
352
1026
                    f1_tree,
353
1026
                    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
1026
    }
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
43550201
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
410
43550201
        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
478
                let self_to = std::mem::transmute::<&AbstractLiteral<U>, &To>(self).clone();
416
478
                let tree = Tree::One(self_to);
417
478
                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
478
                (tree, ctx)
426
            }
427
        } else {
428
            // walking into T
429
43549723
            match self {
430
18570
                AbstractLiteral::Set(vec) => {
431
18570
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
432
18570
                    (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
433
                }
434
120
                AbstractLiteral::MSet(vec) => {
435
120
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
436
120
                    (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
437
                }
438
43517543
                AbstractLiteral::Matrix(elems, index_domain) => {
439
43517543
                    let index_domain = index_domain.clone();
440
43517543
                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(elems);
441
                    (
442
43517543
                        f1_tree,
443
43517543
                        Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
444
                    )
445
                }
446
3939
                AbstractLiteral::Tuple(elems) => {
447
3939
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
448
                    (
449
3939
                        f1_tree,
450
3939
                        Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
451
                    )
452
                }
453
8931
                AbstractLiteral::Record(entries) => {
454
8931
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
455
                    (
456
8931
                        f1_tree,
457
8931
                        Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
458
                    )
459
                }
460
620
                AbstractLiteral::Function(entries) => {
461
620
                    let entry_count = entries.len();
462
620
                    let flattened: Vec<U> = entries
463
620
                        .iter()
464
1240
                        .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
465
620
                        .collect();
466

            
467
620
                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(&flattened);
468
                    (
469
620
                        f1_tree,
470
620
                        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
43550201
    }
491
}
492

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

            
496
1473669
    fn try_from(value: Literal) -> Result<Self, Self::Error> {
497
1473669
        match value {
498
1293378
            Literal::Int(i) => Ok(i),
499
180291
            _ => Err("Cannot convert non-i32 literal to i32"),
500
        }
501
1473669
    }
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
    fn try_from(value: &Box<Literal>) -> Result<Self, Self::Error> {
516
        TryFrom::<&Literal>::try_from(value.as_ref())
517
    }
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
1209098
    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
532
1209098
        match value {
533
1209098
            Literal::Int(i) => Ok(*i),
534
            _ => Err("Cannot convert non-i32 literal to i32"),
535
        }
536
1209098
    }
537
}
538

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

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

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

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

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

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

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

            
580
impl AbstractLiteral<Expression> {
581
    /// If all the elements are literals, returns this as an AbstractLiteral<Literal>.
582
    /// Otherwise, returns `None`.
583
2920946
    pub fn into_literals(self) -> Option<AbstractLiteral<Literal>> {
584
2920946
        match self {
585
3978
            AbstractLiteral::Set(elements) => {
586
3978
                let literals = elements
587
3978
                    .into_iter()
588
9984
                    .map(|expr| match expr {
589
9984
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
590
                        Expression::AbstractLiteral(_, abslit) => {
591
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
592
                        }
593
                        _ => None,
594
9984
                    })
595
3978
                    .collect::<Option<Vec<_>>>()?;
596
3978
                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
2916812
            AbstractLiteral::Matrix(items, domain) => {
612
2916812
                let mut literals = vec![];
613
3479005
                for item in items {
614
2353025
                    let literal = match item {
615
829222
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
616
1443
                        Expression::AbstractLiteral(_, abslit) => {
617
1443
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
618
                        }
619
2648340
                        _ => None,
620
2648340
                    }?;
621
829690
                    literals.push(literal);
622
                }
623

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

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

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

            
669
// need display implementations for other types as well
670
impl Display for Literal {
671
4918817
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
672
4918817
        match &self {
673
4623930
            Literal::Int(i) => write!(f, "{i}"),
674
283852
            Literal::Bool(b) => write!(f, "{b}"),
675
11035
            Literal::AbstractLiteral(l) => write!(f, "{l:?}"),
676
        }
677
4918817
    }
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
2
    fn matrix_uniplate_universe() {
689
        // Can we traverse through matrices with uniplate?
690
2
        let my_matrix: AbstractLiteral<Literal> = into_matrix![
691
2
            vec![Literal::AbstractLiteral(matrix![Literal::Bool(true);Moo::new(GroundDomain::Bool)]); 5];
692
2
            Moo::new(GroundDomain::Bool)
693
        ];
694

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

            
704
12
                res
705
12
            });
706

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