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

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

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

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

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

            
66
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
67
#[path_prefix(conjure_cp::ast)]
68
pub enum AbstractLiteral<T: AbstractLiteralValue> {
69
    Set(Vec<T>),
70

            
71
    MSet(Vec<T>),
72

            
73
    /// A 1 dimensional matrix slice with an index domain.
74
    Matrix(Vec<T>, T::Dom),
75

            
76
    // a tuple of literals
77
    Tuple(Vec<T>),
78

            
79
    Record(Vec<Field<T>>),
80

            
81
    Sequence(Vec<T>),
82

            
83
    Function(Vec<(T, T)>),
84

            
85
    // Variants only contain one of their name-domain pairs
86
    Variant(Moo<Field<T>>),
87

            
88
    // A list of partitions, each part has a set of values
89
    Partition(Vec<Vec<T>>),
90
    Relation(Vec<Vec<T>>),
91
}
92

            
93
// TODO: use HasDomain instead once Expression::domain_of returns Domain not Option<Domain>
94
impl AbstractLiteral<Expression> {
95
242420
    pub fn domain_of(&self) -> Option<DomainPtr> {
96
242420
        match self {
97
8120
            AbstractLiteral::Set(items) => {
98
                // ensure that all items have a domain, or return None
99
8120
                let item_domains: Vec<DomainPtr> = items
100
8120
                    .iter()
101
20040
                    .map(|x| x.domain_of())
102
8120
                    .collect::<Option<Vec<DomainPtr>>>()?;
103

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

            
112
8120
                Some(Domain::set(SetAttr::<Int>::default(), item_domain))
113
            }
114

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

            
122
                // union all item domains together
123
40
                let mut item_domain_iter = item_domains.iter().cloned();
124
40
                let first_item = item_domain_iter.next()?;
125
40
                let item_domain = item_domains
126
40
                    .iter()
127
120
                    .try_fold(first_item, |x, y| x.union(y))
128
40
                    .expect("taking the union of all item domains of a set literal should succeed");
129

            
130
40
                Some(Domain::mset(MSetAttr::<Int>::default(), item_domain))
131
            }
132

            
133
120
            AbstractLiteral::Sequence(elems) => {
134
120
                let item_domains: Vec<DomainPtr> = elems
135
120
                    .iter()
136
400
                    .map(|x| x.domain_of())
137
120
                    .collect::<Option<Vec<DomainPtr>>>()?;
138

            
139
                // Get the union of all domains in the sequence.
140
                // i.e. if <(1..3), (1..3), (5), (8..9)> then seq dom is (1..3, 5, 8..9)
141
120
                let mut item_domain_iter = item_domains.iter().cloned();
142
120
                let first_item = item_domain_iter.next()?;
143
120
                let item_domain = item_domains
144
120
                    .iter()
145
400
                    .try_fold(first_item, |x, y| x.union(y))
146
120
                    .expect("taking the union of all item domains of a set literal should succeed");
147

            
148
120
                Some(Domain::sequence(
149
120
                    SequenceAttr::<Int>::default(),
150
120
                    item_domain,
151
120
                ))
152
            }
153

            
154
40
            AbstractLiteral::Partition(items) => {
155
                // Flatten the Vec<Vec< into a single vec
156
                // ensure that all elemes in each part have a domain, or return None
157

            
158
40
                let item_domains: Vec<DomainPtr> = items
159
40
                    .iter()
160
40
                    .flatten()
161
160
                    .map(|x| x.domain_of())
162
40
                    .collect::<Option<Vec<DomainPtr>>>()?;
163

            
164
                // union all item domains together
165
40
                let mut item_domain_iter = item_domains.iter().cloned();
166
40
                let first_item = item_domain_iter.next()?;
167
40
                let item_domain = item_domains
168
40
                    .iter()
169
160
                    .try_fold(first_item, |x, y| x.union(y))
170
40
                    .expect("taking the union of all item domains of a partition literal should succeed");
171

            
172
40
                Some(Domain::partition(
173
40
                    PartitionAttr::<Int>::default(),
174
40
                    item_domain,
175
40
                ))
176
            }
177

            
178
233580
            AbstractLiteral::Matrix(items, _) => {
179
                // ensure that all items have a domain, or return None
180
233580
                let item_domains = items
181
233580
                    .iter()
182
1485536
                    .map(|x| x.domain_of())
183
233580
                    .collect::<Option<Vec<DomainPtr>>>()?;
184

            
185
                // union all item domains together
186
233572
                let mut item_domain_iter = item_domains.iter().cloned();
187

            
188
233572
                let first_item = item_domain_iter.next()?;
189

            
190
233572
                let item_domain = item_domains
191
233572
                    .iter()
192
1485528
                    .try_fold(first_item, |x, y| x.union(y))
193
233572
                    .expect(
194
233572
                        "taking the union of all item domains of a matrix literal should succeed",
195
                    );
196

            
197
233572
                let mut new_index_domain = vec![];
198

            
199
                // flatten index domains of n-d matrix into list
200
233572
                let mut e = Expression::AbstractLiteral(Metadata::new(), self.clone());
201
247140
                while let Expression::AbstractLiteral(_, AbstractLiteral::Matrix(elems, idx)) = e {
202
247140
                    assert!(
203
247140
                        idx.as_matrix().is_none(),
204
                        "n-dimensional matrix literals should be represented as a matrix inside a matrix, got {idx}"
205
                    );
206
247140
                    new_index_domain.push(idx);
207
247140
                    e = elems[0].clone();
208
                }
209
233572
                Some(Domain::matrix(item_domain, new_index_domain))
210
            }
211
280
            AbstractLiteral::Tuple(_) => None,
212
40
            AbstractLiteral::Record(_) => None,
213
80
            AbstractLiteral::Function(_) => None,
214
40
            AbstractLiteral::Variant(_) => None,
215
80
            AbstractLiteral::Relation(_) => None,
216
        }
217
242420
    }
218
}
219

            
220
impl HasDomain for AbstractLiteral<Literal> {
221
25738
    fn domain_of(&self) -> DomainPtr {
222
25738
        Domain::from_literal_vec(&[Literal::AbstractLiteral(self.clone())])
223
25738
            .expect("abstract literals should be correctly typed")
224
25738
    }
225
}
226

            
227
impl Typeable for AbstractLiteral<Expression> {
228
135440
    fn return_type(&self) -> ReturnType {
229
        match self {
230
            AbstractLiteral::Set(items) if items.is_empty() => {
231
                ReturnType::Set(Box::new(ReturnType::Unknown))
232
            }
233
            AbstractLiteral::Set(items) => {
234
                let item_type = items[0].return_type();
235

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

            
239
                assert!(
240
                    item_types.iter().all(|x| x == &item_type),
241
                    "all items in a set should have the same type"
242
                );
243

            
244
                ReturnType::Set(Box::new(item_type))
245
            }
246
            AbstractLiteral::MSet(items) if items.is_empty() => {
247
                ReturnType::MSet(Box::new(ReturnType::Unknown))
248
            }
249
            AbstractLiteral::MSet(items) => {
250
                let item_type = items[0].return_type();
251

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

            
255
                assert!(
256
                    item_types.iter().all(|x| x == &item_type),
257
                    "all items in a set should have the same type"
258
                );
259

            
260
                ReturnType::MSet(Box::new(item_type))
261
            }
262
            AbstractLiteral::Sequence(items) if items.is_empty() => {
263
                ReturnType::Sequence(Box::new(ReturnType::Unknown))
264
            }
265
            AbstractLiteral::Sequence(items) => {
266
                let item_type = items[0].return_type();
267

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

            
271
                assert!(
272
                    item_types.iter().all(|x| x == &item_type),
273
                    "all items in a sequence should have the same type"
274
                );
275

            
276
                ReturnType::Sequence(Box::new(item_type))
277
            }
278
            AbstractLiteral::Partition(items) if items.is_empty() || items[0].is_empty() => {
279
                ReturnType::Partition(Box::new(ReturnType::Unknown))
280
            }
281
            AbstractLiteral::Partition(items) => {
282
                let item_type = items[0][0].return_type();
283

            
284
                // if any items do not have a type, return none.
285
                let item_types: Vec<ReturnType> =
286
                    items.iter().flatten().map(|x| x.return_type()).collect();
287

            
288
                assert!(
289
                    item_types.iter().all(|x| x == &item_type),
290
                    "all items in every part of a partition should have the same type"
291
                );
292

            
293
                ReturnType::Partition(Box::new(item_type))
294
            }
295
135360
            AbstractLiteral::Matrix(items, _) if items.is_empty() => {
296
                ReturnType::Matrix(Box::new(ReturnType::Unknown))
297
            }
298
135360
            AbstractLiteral::Matrix(items, _) => {
299
135360
                let item_type = items[0].return_type();
300

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

            
304
135360
                assert!(
305
972444
                    item_types.iter().all(|x| x == &item_type),
306
                    "all items in a matrix should have the same type. items: {items} types: {types:#?}",
307
                    items = pretty_vec(items),
308
                    types = items
309
                        .iter()
310
                        .map(|x| x.return_type())
311
                        .collect::<Vec<ReturnType>>()
312
                );
313

            
314
135360
                ReturnType::Matrix(Box::new(item_type))
315
            }
316
80
            AbstractLiteral::Tuple(items) => {
317
80
                let mut item_types = vec![];
318
160
                for item in items {
319
160
                    item_types.push(item.return_type());
320
160
                }
321
80
                ReturnType::Tuple(item_types)
322
            }
323
            AbstractLiteral::Record(items) => {
324
                let mut item_types = vec![];
325
                for item in items {
326
                    item_types.push(item.clone().func_map(|x| x.return_type()));
327
                }
328
                ReturnType::Record(item_types)
329
            }
330
            AbstractLiteral::Function(items) => {
331
                if items.is_empty() {
332
                    return ReturnType::Function(
333
                        Box::new(ReturnType::Unknown),
334
                        Box::new(ReturnType::Unknown),
335
                    );
336
                }
337

            
338
                // Check that all items have the same return type
339
                let (x1, y1) = &items[0];
340
                let (t1, t2) = (x1.return_type(), y1.return_type());
341
                for (x, y) in items {
342
                    let (tx, ty) = (x.return_type(), y.return_type());
343
                    if tx != t1 {
344
                        bug!("Expected {t1}, got {x}: {tx}");
345
                    }
346
                    if ty != t2 {
347
                        bug!("Expected {t2}, got {y}: {ty}");
348
                    }
349
                }
350

            
351
                ReturnType::Function(Box::new(t1), Box::new(t2))
352
            }
353
            AbstractLiteral::Variant(item) => {
354
                // Variants hold multiple possible types. In the case of a literal we know which type it chose
355
                ReturnType::Variant(vec![item.as_ref().clone().func_map(|x| x.return_type())])
356
            }
357
            AbstractLiteral::Relation(items) => {
358
                if items.is_empty() {
359
                    return ReturnType::Relation(vec![ReturnType::Unknown]);
360
                }
361
                let mut item_types = vec![];
362
                let x1 = &items[0];
363
                let size = x1.len();
364
                for item in x1 {
365
                    item_types.push(item.return_type());
366
                }
367
                for x in items {
368
                    if x.len() != size {
369
                        let strs = item_types.iter().map(|x| format!("{}", x)).join(",");
370
                        bug!("Expected ({strs}) with length {size}, got size {}", x.len());
371
                    }
372
                    for i in 1..size {
373
                        if let Some(new_type) = x.get(i)
374
                            && let Some(old_type) = item_types.get(i)
375
                            && new_type.return_type() != *old_type
376
                        {
377
                            bug!("Expected {old_type}, got {new_type}");
378
                        }
379
                    }
380
                }
381
                ReturnType::Relation(item_types)
382
            }
383
        }
384
135440
    }
385
}
386

            
387
impl<T> AbstractLiteral<T>
388
where
389
    T: AbstractLiteralValue,
390
{
391
    /// Creates a matrix with elements `elems`, with domain `int(1..)`.
392
    ///
393
    /// This acts as a variable sized list.
394
952105
    pub fn matrix_implied_indices(elems: Vec<T>) -> Self {
395
952105
        AbstractLiteral::Matrix(elems, GroundDomain::Int(vec![Range::UnboundedR(1)]).into())
396
952105
    }
397

            
398
    /// If the AbstractLiteral is a list, returns its elements.
399
    ///
400
    /// A list is any a matrix with the domain `int(1..)`. This includes matrix literals without
401
    /// any explicitly specified domain.
402
7750500
    pub fn unwrap_list(&self) -> Option<&Vec<T>> {
403
7750500
        let AbstractLiteral::Matrix(elems, domain) = self else {
404
            return None;
405
        };
406

            
407
7750500
        let domain: DomainPtr = domain.clone().into();
408
7750500
        let Some(GroundDomain::Int(ranges)) = domain.as_ground() else {
409
            return None;
410
        };
411

            
412
7750500
        let [Range::UnboundedR(1)] = ranges[..] else {
413
1487936
            return None;
414
        };
415

            
416
6262564
        Some(elems)
417
7750500
    }
418
}
419

            
420
impl<T> Display for AbstractLiteral<T>
421
where
422
    T: AbstractLiteralValue,
423
{
424
3251820
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
425
3251820
        match self {
426
9256
            AbstractLiteral::Set(elems) => {
427
24044
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
428
9256
                write!(f, "{{{elems_str}}}")
429
            }
430
40
            AbstractLiteral::MSet(elems) => {
431
120
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
432
40
                write!(f, "mset({elems_str})")
433
            }
434
3240644
            AbstractLiteral::Matrix(elems, index_domain) => {
435
12450292
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
436
3240644
                write!(f, "[{elems_str};{index_domain}]")
437
            }
438
1080
            AbstractLiteral::Tuple(elems) => {
439
2480
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
440
1080
                write!(f, "({elems_str})")
441
            }
442
120
            AbstractLiteral::Sequence(elems) => {
443
400
                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
444
120
                write!(f, "sequence({elems_str})")
445
            }
446
40
            AbstractLiteral::Partition(parts) => {
447
40
                let elems_str: String = parts
448
40
                    .iter()
449
120
                    .map(|inner| {
450
160
                        let elems_str = inner.iter().map(|x| format!("{x}")).join(",");
451
120
                        format!("{{{}}}", elems_str)
452
120
                    })
453
40
                    .join(", ");
454

            
455
40
                write!(f, "partition({elems_str})")
456
            }
457
400
            AbstractLiteral::Record(entries) => {
458
400
                let entries_str: String = entries
459
400
                    .iter()
460
800
                    .map(|entry| format!("{} = {}", entry.name, entry.value))
461
400
                    .join(",");
462
400
                write!(f, "record {{{entries_str}}}")
463
            }
464
120
            AbstractLiteral::Function(entries) => {
465
120
                let entries_str: String = entries
466
120
                    .iter()
467
240
                    .map(|entry| format!("{} --> {}", entry.0, entry.1))
468
120
                    .join(",");
469
120
                write!(f, "function({entries_str})")
470
            }
471
40
            AbstractLiteral::Variant(entry) => {
472
40
                write!(f, "variant{{{} = {}}}", entry.name, entry.value)
473
            }
474
80
            AbstractLiteral::Relation(elems) => {
475
80
                let elems_str: String = elems
476
80
                    .iter()
477
480
                    .map(|x| format!("({})", x.iter().map(|x| format!("{x}")).join(",")))
478
80
                    .join(",");
479
80
                write!(f, "relation({elems_str})")
480
            }
481
        }
482
3251820
    }
483
}
484

            
485
impl<T> Uniplate for AbstractLiteral<T>
486
where
487
    T: AbstractLiteralValue + Biplate<AbstractLiteral<T>>,
488
{
489
6
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
490
        // walking into T
491
6
        match self {
492
            AbstractLiteral::Set(vec) => {
493
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
494
                (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
495
            }
496
            AbstractLiteral::MSet(vec) => {
497
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
498
                (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
499
            }
500
6
            AbstractLiteral::Matrix(elems, index_domain) => {
501
6
                let index_domain = index_domain.clone();
502
6
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
503
                (
504
6
                    f1_tree,
505
6
                    Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
506
                )
507
            }
508
            AbstractLiteral::Sequence(vec) => {
509
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
510
                (
511
                    f1_tree,
512
                    Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
513
                )
514
            }
515
            AbstractLiteral::Tuple(elems) => {
516
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
517
                (
518
                    f1_tree,
519
                    Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
520
                )
521
            }
522
            AbstractLiteral::Record(entries) => {
523
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
524
                (
525
                    f1_tree,
526
                    Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
527
                )
528
            }
529
            AbstractLiteral::Function(entries) => {
530
                let entry_count = entries.len();
531
                let flattened: Vec<T> = entries
532
                    .iter()
533
                    .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
534
                    .collect();
535

            
536
                let (f1_tree, f1_ctx) =
537
                    <Vec<T> as Biplate<AbstractLiteral<T>>>::biplate(&flattened);
538
                (
539
                    f1_tree,
540
                    Box::new(move |x| {
541
                        let rebuilt = f1_ctx(x);
542
                        assert_eq!(
543
                            rebuilt.len(),
544
                            entry_count * 2,
545
                            "number of function literal children should remain unchanged"
546
                        );
547

            
548
                        let mut iter = rebuilt.into_iter();
549
                        let mut pairs = Vec::with_capacity(entry_count);
550
                        while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
551
                            pairs.push((lhs, rhs));
552
                        }
553

            
554
                        AbstractLiteral::Function(pairs)
555
                    }),
556
                )
557
            }
558
            AbstractLiteral::Variant(entries) => {
559
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
560
                (
561
                    f1_tree,
562
                    Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
563
                )
564
            }
565
            AbstractLiteral::Relation(elems) => {
566
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
567
                (
568
                    f1_tree,
569
                    Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
570
                )
571
            }
572
            AbstractLiteral::Partition(elems) => {
573
                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
574
                (
575
                    f1_tree,
576
                    Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
577
                )
578
            }
579
        }
580
6
    }
581
}
582

            
583
impl<U, To> Biplate<To> for AbstractLiteral<U>
584
where
585
    To: Uniplate,
586
    U: AbstractLiteralValue + Biplate<AbstractLiteral<U>> + Biplate<To>,
587
    Field<U>: Biplate<AbstractLiteral<U>> + Biplate<To>,
588
{
589
90538713
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
590
90538713
        if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
591
            // To ==From => return One(self)
592

            
593
            unsafe {
594
                // SAFETY: asserted the type equality above
595
5
                let self_to = std::mem::transmute::<&AbstractLiteral<U>, &To>(self).clone();
596
5
                let tree = Tree::One(self_to);
597
5
                let ctx = Box::new(move |x| {
598
                    let Tree::One(x) = x else {
599
                        panic!();
600
                    };
601

            
602
                    std::mem::transmute::<&To, &AbstractLiteral<U>>(&x).clone()
603
                });
604

            
605
5
                (tree, ctx)
606
            }
607
        } else {
608
            // walking into T
609
90538708
            match self {
610
215464
                AbstractLiteral::Set(vec) => {
611
215464
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
612
215464
                    (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
613
                }
614
240
                AbstractLiteral::MSet(vec) => {
615
240
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
616
240
                    (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
617
                }
618
90280704
                AbstractLiteral::Matrix(elems, index_domain) => {
619
90280704
                    let index_domain = index_domain.clone();
620
90280704
                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(elems);
621
                    (
622
90280704
                        f1_tree,
623
90280704
                        Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
624
                    )
625
                }
626
620
                AbstractLiteral::Sequence(vec) => {
627
620
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
628
                    (
629
620
                        f1_tree,
630
620
                        Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
631
                    )
632
                }
633
17840
                AbstractLiteral::Tuple(elems) => {
634
17840
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
635
                    (
636
17840
                        f1_tree,
637
17840
                        Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
638
                    )
639
                }
640
22340
                AbstractLiteral::Record(entries) => {
641
22340
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
642
                    (
643
22340
                        f1_tree,
644
22340
                        Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
645
                    )
646
                }
647
940
                AbstractLiteral::Function(entries) => {
648
940
                    let entry_count = entries.len();
649
940
                    let flattened: Vec<U> = entries
650
940
                        .iter()
651
1880
                        .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
652
940
                        .collect();
653

            
654
940
                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(&flattened);
655
                    (
656
940
                        f1_tree,
657
940
                        Box::new(move |x| {
658
                            let rebuilt = f1_ctx(x);
659
                            assert_eq!(
660
                                rebuilt.len(),
661
                                entry_count * 2,
662
                                "number of function literal children should remain unchanged"
663
                            );
664

            
665
                            let mut iter = rebuilt.into_iter();
666
                            let mut pairs = Vec::with_capacity(entry_count);
667
                            while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
668
                                pairs.push((lhs, rhs));
669
                            }
670

            
671
                            AbstractLiteral::Function(pairs)
672
                        }),
673
                    )
674
                }
675
140
                AbstractLiteral::Variant(entries) => {
676
140
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
677
                    (
678
140
                        f1_tree,
679
140
                        Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
680
                    )
681
                }
682
280
                AbstractLiteral::Relation(elems) => {
683
280
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
684
                    (
685
280
                        f1_tree,
686
280
                        Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
687
                    )
688
                }
689
140
                AbstractLiteral::Partition(elems) => {
690
140
                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
691
                    (
692
140
                        f1_tree,
693
140
                        Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
694
                    )
695
                }
696
            }
697
        }
698
90538713
    }
699
}
700

            
701
impl TryFrom<Literal> for i32 {
702
    type Error = &'static str;
703

            
704
2809952
    fn try_from(value: Literal) -> Result<Self, Self::Error> {
705
2809952
        match value {
706
2647236
            Literal::Int(i) => Ok(i),
707
162716
            _ => Err("Cannot convert non-i32 literal to i32"),
708
        }
709
2809952
    }
710
}
711

            
712
impl TryFrom<Box<Literal>> for i32 {
713
    type Error = &'static str;
714

            
715
    fn try_from(value: Box<Literal>) -> Result<Self, Self::Error> {
716
        (*value).try_into()
717
    }
718
}
719

            
720
impl TryFrom<&Box<Literal>> for i32 {
721
    type Error = &'static str;
722

            
723
162800
    fn try_from(value: &Box<Literal>) -> Result<Self, Self::Error> {
724
162800
        TryFrom::<&Literal>::try_from(value.as_ref())
725
162800
    }
726
}
727

            
728
impl TryFrom<&Moo<Literal>> for i32 {
729
    type Error = &'static str;
730

            
731
    fn try_from(value: &Moo<Literal>) -> Result<Self, Self::Error> {
732
        TryFrom::<&Literal>::try_from(value.as_ref())
733
    }
734
}
735

            
736
impl TryFrom<&Literal> for i32 {
737
    type Error = &'static str;
738

            
739
3084592
    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
740
3084592
        match value {
741
3084592
            Literal::Int(i) => Ok(*i),
742
            _ => Err("Cannot convert non-i32 literal to i32"),
743
        }
744
3084592
    }
745
}
746

            
747
impl TryFrom<Literal> for bool {
748
    type Error = &'static str;
749

            
750
1705612
    fn try_from(value: Literal) -> Result<Self, Self::Error> {
751
1705612
        match value {
752
1674880
            Literal::Bool(b) => Ok(b),
753
30732
            _ => Err("Cannot convert non-bool literal to bool"),
754
        }
755
1705612
    }
756
}
757

            
758
impl TryFrom<&Literal> for bool {
759
    type Error = &'static str;
760

            
761
246912
    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
762
246912
        match value {
763
246912
            Literal::Bool(b) => Ok(*b),
764
            _ => Err("Cannot convert non-bool literal to bool"),
765
        }
766
246912
    }
767
}
768

            
769
impl From<i32> for Literal {
770
4419124
    fn from(i: i32) -> Self {
771
4419124
        Literal::Int(i)
772
4419124
    }
773
}
774

            
775
impl From<bool> for Literal {
776
167130
    fn from(b: bool) -> Self {
777
167130
        Literal::Bool(b)
778
167130
    }
779
}
780

            
781
impl From<Literal> for Ustr {
782
1760
    fn from(value: Literal) -> Self {
783
        // TODO: avoid the temporary-allocation of a string by format! here?
784
1760
        Ustr::from(&format!("{value}"))
785
1760
    }
786
}
787

            
788
impl From<AbstractLiteral<Literal>> for Literal {
789
6542
    fn from(literal: AbstractLiteral<Literal>) -> Self {
790
6542
        Literal::AbstractLiteral(literal)
791
6542
    }
792
}
793

            
794
impl AbstractLiteral<Expression> {
795
    /// If all the elements are literals, returns this as an AbstractLiteral<Literal>.
796
    /// Otherwise, returns `None`.
797
5398288
    pub fn into_literals(self) -> Option<AbstractLiteral<Literal>> {
798
5398288
        match self {
799
4728
            AbstractLiteral::Set(elements) => {
800
4728
                let literals = elements
801
4728
                    .into_iter()
802
11852
                    .map(|expr| match expr {
803
11852
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
804
                        Expression::AbstractLiteral(_, abslit) => {
805
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
806
                        }
807
                        _ => None,
808
11852
                    })
809
4728
                    .collect::<Option<Vec<_>>>()?;
810
4728
                Some(AbstractLiteral::Set(literals))
811
            }
812
            AbstractLiteral::MSet(elements) => {
813
                let literals = elements
814
                    .into_iter()
815
                    .map(|expr| match expr {
816
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
817
                        Expression::AbstractLiteral(_, abslit) => {
818
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
819
                        }
820
                        _ => None,
821
                    })
822
                    .collect::<Option<Vec<_>>>()?;
823
                Some(AbstractLiteral::MSet(literals))
824
            }
825
            AbstractLiteral::Partition(elems) => {
826
                // want to ascertain if every elem in Vec<Vec<Expr>> is a literal. If any are not, return none
827
                // otherwise confirm it is an abslit<lit>
828
                let mut partition: Vec<Vec<_>> = Vec::new();
829

            
830
                for part in elems {
831
                    let literals = part
832
                        .into_iter()
833
                        .map(|expr| match expr {
834
                            Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
835
                            Expression::AbstractLiteral(_, abslit) => {
836
                                Some(Literal::AbstractLiteral(abslit.into_literals()?))
837
                            }
838
                            _ => None,
839
                        })
840
                        .collect::<Option<Vec<_>>>()?;
841

            
842
                    partition.push(literals);
843
                }
844

            
845
                Some(AbstractLiteral::Partition(partition))
846
            }
847
5393240
            AbstractLiteral::Matrix(items, domain) => {
848
5393240
                let mut literals = vec![];
849
8658296
                for item in items {
850
7168384
                    let literal = match item {
851
3805124
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
852
508480
                        Expression::AbstractLiteral(_, abslit) => {
853
508480
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
854
                        }
855
4344692
                        _ => None,
856
4344692
                    }?;
857
4312484
                    literals.push(literal);
858
                }
859

            
860
1047428
                Some(AbstractLiteral::Matrix(literals, domain.resolve().ok()?))
861
            }
862
            AbstractLiteral::Sequence(elements) => {
863
                let literals = elements
864
                    .into_iter()
865
                    .map(|expr| match expr {
866
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
867
                        Expression::AbstractLiteral(_, abslit) => {
868
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
869
                        }
870
                        _ => None,
871
                    })
872
                    .collect::<Option<Vec<_>>>()?;
873
                Some(AbstractLiteral::Sequence(literals))
874
            }
875
240
            AbstractLiteral::Tuple(items) => {
876
240
                let mut literals = vec![];
877
480
                for item in items {
878
480
                    let literal = match item {
879
480
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
880
                        Expression::AbstractLiteral(_, abslit) => {
881
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
882
                        }
883
                        _ => None,
884
                    }?;
885
480
                    literals.push(literal);
886
                }
887

            
888
240
                Some(AbstractLiteral::Tuple(literals))
889
            }
890
80
            AbstractLiteral::Record(entries) => {
891
80
                let mut literals = vec![];
892
160
                for entry in entries {
893
160
                    let literal = match entry.value {
894
160
                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
895
                        Expression::AbstractLiteral(_, abslit) => {
896
                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
897
                        }
898
                        _ => None,
899
                    }?;
900

            
901
160
                    literals.push((entry.name, literal));
902
                }
903
                Some(AbstractLiteral::Record(
904
80
                    literals
905
80
                        .into_iter()
906
80
                        .map(|(name, literal)| Field {
907
160
                            name,
908
160
                            value: literal,
909
160
                        })
910
80
                        .collect(),
911
                ))
912
            }
913
            AbstractLiteral::Function(_) => todo!("Implement into_literals for functions"),
914
            AbstractLiteral::Variant(entry) => {
915
                let literal = match entry.value.clone() {
916
                    Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
917
                    Expression::AbstractLiteral(_, abslit) => {
918
                        Some(Literal::AbstractLiteral(abslit.into_literals()?))
919
                    }
920
                    _ => None,
921
                }?;
922
                Some(AbstractLiteral::Variant(Moo::new(Field {
923
                    name: entry.name.clone(),
924
                    value: literal,
925
                })))
926
            }
927
            AbstractLiteral::Relation(_) => todo!("Implement into_literals for relations"),
928
        }
929
5398288
    }
930
}
931

            
932
// need display implementations for other types as well
933
impl Display for Literal {
934
7016428
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
935
7016428
        match &self {
936
5966760
            Literal::Int(i) => write!(f, "{i}"),
937
877368
            Literal::Bool(b) => write!(f, "{b}"),
938
172300
            Literal::AbstractLiteral(l) => write!(f, "{l}"),
939
        }
940
7016428
    }
941
}
942

            
943
#[cfg(test)]
944
mod tests {
945

            
946
    use super::*;
947
    use crate::ast::matrix::{flatten, partial_flatten, shape_of};
948
    use crate::{domain_int_ground, into_matrix, matrix, matrix_lit, range};
949
    use uniplate::Uniplate;
950

            
951
    #[test]
952
1
    fn matrix_uniplate_universe() {
953
        // Can we traverse through matrices with uniplate?
954
1
        let my_matrix: AbstractLiteral<Literal> = into_matrix![
955
1
            vec![Literal::AbstractLiteral(matrix![Literal::Bool(true);Moo::new(GroundDomain::Bool)]); 5];
956
1
            Moo::new(GroundDomain::Bool)
957
        ];
958

            
959
1
        let expected_index_domains = vec![Moo::new(GroundDomain::Bool); 6];
960
1
        let actual_index_domains: Vec<Moo<GroundDomain>> =
961
6
            my_matrix.cata(&move |elem, children| {
962
6
                let mut res = vec![];
963
6
                res.extend(children.into_iter().flatten());
964
6
                if let AbstractLiteral::Matrix(_, index_domain) = elem {
965
6
                    res.push(index_domain);
966
6
                }
967

            
968
6
                res
969
6
            });
970

            
971
1
        assert_eq!(actual_index_domains, expected_index_domains);
972
1
    }
973

            
974
    #[test]
975
1
    fn matrix_flatten() {
976
1
        let tensor: AbstractLiteral<Literal> = matrix![
977
            [
978
                // batch 1
979
                [1, 2, 3, 4],
980
                [5, 6, 7, 8],
981
                [9, 10, 11, 12]
982
            ],
983
            [
984
                // batch 2
985
                [13, 14, 15, 16],
986
                [17, 18, 19, 20],
987
                [21, 22, 23, 24]
988
            ]
989
        ];
990

            
991
1
        let actual_elems: Vec<Literal> = flatten(&tensor).cloned().collect();
992
1
        let expected_elems = (1..25).map(Literal::from).collect::<Vec<_>>();
993
1
        assert_eq!(actual_elems, expected_elems);
994
1
    }
995

            
996
    #[test]
997
1
    fn matrix_domain_1d() {
998
1
        let matrix = matrix_lit![10, 11, 12, 13; domain_int_ground!(1..4)];
999
1
        let dom = matrix.domain_of();
1
        let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1
        assert_eq!(inner_dom, &domain_int_ground!(10..13));
1
        assert_eq!(idx_doms.len(), 1);
1
        assert_eq!(&idx_doms[0], &domain_int_ground!(1..4));
1
    }
    #[test]
1
    fn matrix_domain_2d() {
1
        let matrix = matrix_lit![
            [1, 2, 3, 4],
            [5, 6, 7, 8];
            [
1
                domain_int_ground!(1..2),
1
                domain_int_ground!(1..4)
            ]
        ];
1
        let dom = matrix.domain_of();
1
        let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1
        assert_eq!(inner_dom, &domain_int_ground!(1..8));
1
        assert_eq!(idx_doms.len(), 2);
1
        assert_eq!(&idx_doms[0], &domain_int_ground!(1..2));
1
        assert_eq!(&idx_doms[1], &domain_int_ground!(1..4));
1
    }
    #[test]
1
    fn matrix_shape_3d() {
1
        let tensor: AbstractLiteral<Literal> = matrix![
            [
                [1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]
            ],
            [
                [13, 14, 15, 16],
                [17, 18, 19, 20],
                [21, 22, 23, 24]
            ];
            [
1
                domain_int_ground!(1..2),
1
                domain_int_ground!(1..3),
1
                domain_int_ground!(1..4)
            ]
        ];
1
        let shape = shape_of(&tensor).expect("shape_of to work on a 3D matrix");
1
        assert_eq!(shape.size, 24);
1
        assert_eq!(shape.dims, vec![2, 3, 4]);
1
        assert_eq!(shape.strides, vec![12, 4, 1]);
1
        assert_eq!(
            shape.idx_doms,
1
            vec![
1
                domain_int_ground!(1..2),
1
                domain_int_ground!(1..3),
1
                domain_int_ground!(1..4)
            ]
        );
1
    }
    #[test]
1
    fn matrix_partial_flatten() {
1
        let tensor: AbstractLiteral<Literal> = matrix![
            [
                // batch 1
                [1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]
            ],
            [
                // batch 2
                [13, 14, 15, 16],
                [17, 18, 19, 20],
                [21, 22, 23, 24]
            ]
        ];
1
        assert_eq!(partial_flatten(0, tensor.clone()), tensor);
1
        let expected_flatten_1: AbstractLiteral<Literal> = matrix![
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
            [13, 14, 15, 16],
            [17, 18, 19, 20],
            [21, 22, 23, 24]
        ];
1
        assert_eq!(partial_flatten(1, tensor.clone()), expected_flatten_1);
1
        let expected_flatten_2 =
1
            AbstractLiteral::matrix_implied_indices((1..25).map(Literal::from).collect());
1
        assert_eq!(partial_flatten(2, tensor), expected_flatten_2);
1
    }
}