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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
289
2042240
        Some(elems)
290
3600080
    }
291
}
292

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

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

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

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

            
496
1412240
    fn try_from(value: Literal) -> Result<Self, Self::Error> {
497
1412240
        match value {
498
1298960
            Literal::Int(i) => Ok(i),
499
113280
            _ => Err("Cannot convert non-i32 literal to i32"),
500
        }
501
1412240
    }
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
1313580
    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
532
1313580
        match value {
533
1313580
            Literal::Int(i) => Ok(*i),
534
            _ => Err("Cannot convert non-i32 literal to i32"),
535
        }
536
1313580
    }
537
}
538

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

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

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

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

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

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

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

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

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

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

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

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

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

            
704
18
                res
705
18
            });
706

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