Skip to main content

conjure_cp_core/ast/
literals.rs

1use funcmap::FuncMap;
2use itertools::Itertools;
3use serde::{Deserialize, Serialize};
4use std::cmp::Ordering;
5use std::fmt::{Debug, Display, Formatter};
6use std::hash::Hash;
7use ustr::Ustr;
8
9use super::{
10    Atom, Domain, DomainPtr, Expression, GroundDomain, Metadata, Moo, PartitionAttr,
11    PermutationAttr, Range, ReturnType, SetAttr, Typeable, domains::HasDomain, domains::Int,
12    records::Field,
13};
14use crate::ast::domains::{MSetAttr, SequenceAttr};
15use crate::ast::pretty::pretty_vec;
16use crate::bug;
17use crate::bug_assert;
18use polyquine::Quine;
19use uniplate::{Biplate, Tree, Uniplate};
20
21#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate, Hash, Quine)]
22#[uniplate(walk_into=[AbstractLiteral<Literal>])]
23#[biplate(to=Atom)]
24#[biplate(to=AbstractLiteral<Literal>)]
25#[biplate(to=AbstractLiteral<Expression>)]
26#[biplate(to=Field<Literal>)]
27#[biplate(to=Field<Expression>)]
28#[biplate(to=Expression)]
29#[path_prefix(conjure_cp::ast)]
30/// A literal value, equivalent to constants in Conjure.
31pub enum Literal {
32    Int(i32),
33    Bool(bool),
34    //abstract literal variant ends in Literal, but that's ok
35    #[allow(clippy::enum_variant_names)]
36    AbstractLiteral(AbstractLiteral<Literal>),
37}
38
39impl HasDomain for Literal {
40    fn domain_of(&self) -> DomainPtr {
41        match self {
42            Literal::Int(i) => Domain::int(vec![Range::Single(*i)]),
43            Literal::Bool(_) => Domain::bool(),
44            Literal::AbstractLiteral(abstract_literal) => abstract_literal.domain_of(),
45        }
46    }
47}
48
49impl Literal {
50    /// Compare values using Essence-aware value ordering.
51    ///
52    /// Booleans and integers use their natural order, tuple-like values use
53    /// lexicographic order, and sets use lexicographic occurrence order over
54    /// ascending element values (`false < true`).
55    pub fn essence_cmp(&self, other: &Self) -> Ordering {
56        match (self, other) {
57            (Literal::Bool(lhs), Literal::Bool(rhs)) => lhs.cmp(rhs),
58            (Literal::Int(lhs), Literal::Int(rhs)) => lhs.cmp(rhs),
59            (Literal::AbstractLiteral(lhs), Literal::AbstractLiteral(rhs)) => {
60                abstract_literal_essence_cmp(lhs, rhs)
61            }
62            _ => literal_kind(self).cmp(&literal_kind(other)),
63        }
64    }
65}
66
67fn literal_kind(literal: &Literal) -> u8 {
68    match literal {
69        Literal::Bool(_) => 0,
70        Literal::Int(_) => 1,
71        Literal::AbstractLiteral(_) => 2,
72    }
73}
74
75fn abstract_literal_essence_cmp(
76    lhs: &AbstractLiteral<Literal>,
77    rhs: &AbstractLiteral<Literal>,
78) -> Ordering {
79    match (lhs, rhs) {
80        (AbstractLiteral::Set(lhs), AbstractLiteral::Set(rhs)) => set_essence_cmp(lhs, rhs),
81        (AbstractLiteral::MSet(lhs), AbstractLiteral::MSet(rhs)) => sorted_literals_cmp(lhs, rhs),
82        (AbstractLiteral::Matrix(lhs, _), AbstractLiteral::Matrix(rhs, _))
83        | (AbstractLiteral::Tuple(lhs), AbstractLiteral::Tuple(rhs))
84        | (AbstractLiteral::Sequence(lhs), AbstractLiteral::Sequence(rhs)) => {
85            literal_slice_cmp(lhs, rhs)
86        }
87        (AbstractLiteral::Record(lhs), AbstractLiteral::Record(rhs)) => lhs
88            .iter()
89            .zip(rhs)
90            .find_map(|(lhs, rhs)| {
91                let ordering = lhs.name.to_string().cmp(&rhs.name.to_string());
92                (ordering != Ordering::Equal)
93                    .then_some(ordering)
94                    .or_else(|| {
95                        let ordering = lhs.value.essence_cmp(&rhs.value);
96                        (ordering != Ordering::Equal).then_some(ordering)
97                    })
98            })
99            .unwrap_or_else(|| lhs.len().cmp(&rhs.len())),
100        (AbstractLiteral::Function(lhs), AbstractLiteral::Function(rhs)) => lhs
101            .iter()
102            .zip(rhs)
103            .find_map(|((lhs_from, lhs_to), (rhs_from, rhs_to))| {
104                let ordering = lhs_from.essence_cmp(rhs_from);
105                (ordering != Ordering::Equal)
106                    .then_some(ordering)
107                    .or_else(|| {
108                        let ordering = lhs_to.essence_cmp(rhs_to);
109                        (ordering != Ordering::Equal).then_some(ordering)
110                    })
111            })
112            .unwrap_or_else(|| lhs.len().cmp(&rhs.len())),
113        (AbstractLiteral::Variant(lhs), AbstractLiteral::Variant(rhs)) => lhs
114            .name
115            .to_string()
116            .cmp(&rhs.name.to_string())
117            .then_with(|| lhs.value.essence_cmp(&rhs.value)),
118        (AbstractLiteral::Partition(lhs), AbstractLiteral::Partition(rhs))
119        | (AbstractLiteral::Relation(lhs), AbstractLiteral::Relation(rhs))
120        | (AbstractLiteral::Permutation(lhs), AbstractLiteral::Permutation(rhs)) => lhs
121            .iter()
122            .zip(rhs)
123            .find_map(|(lhs, rhs)| {
124                let ordering = literal_slice_cmp(lhs, rhs);
125                (ordering != Ordering::Equal).then_some(ordering)
126            })
127            .unwrap_or_else(|| lhs.len().cmp(&rhs.len())),
128        _ => abstract_literal_kind(lhs).cmp(&abstract_literal_kind(rhs)),
129    }
130}
131
132fn abstract_literal_kind(literal: &AbstractLiteral<Literal>) -> u8 {
133    match literal {
134        AbstractLiteral::Set(_) => 0,
135        AbstractLiteral::MSet(_) => 1,
136        AbstractLiteral::Matrix(..) => 2,
137        AbstractLiteral::Tuple(_) => 3,
138        AbstractLiteral::Record(_) => 4,
139        AbstractLiteral::Sequence(_) => 5,
140        AbstractLiteral::Function(_) => 6,
141        AbstractLiteral::Variant(_) => 7,
142        AbstractLiteral::Partition(_) => 8,
143        AbstractLiteral::Relation(_) => 9,
144        AbstractLiteral::Permutation(_) => 10,
145    }
146}
147
148fn literal_slice_cmp(lhs: &[Literal], rhs: &[Literal]) -> Ordering {
149    lhs.iter()
150        .zip(rhs)
151        .find_map(|(lhs, rhs)| {
152            let ordering = lhs.essence_cmp(rhs);
153            (ordering != Ordering::Equal).then_some(ordering)
154        })
155        .unwrap_or_else(|| lhs.len().cmp(&rhs.len()))
156}
157
158fn sorted_literals_cmp(lhs: &[Literal], rhs: &[Literal]) -> Ordering {
159    let mut lhs = lhs.iter().collect::<Vec<_>>();
160    let mut rhs = rhs.iter().collect::<Vec<_>>();
161    lhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
162    rhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
163    lhs.iter()
164        .zip(&rhs)
165        .find_map(|(lhs, rhs)| {
166            let ordering = lhs.essence_cmp(rhs);
167            (ordering != Ordering::Equal).then_some(ordering)
168        })
169        .unwrap_or_else(|| lhs.len().cmp(&rhs.len()))
170}
171
172/// Compare sets as occurrence vectors over the ordered union of their elements.
173fn set_essence_cmp(lhs: &[Literal], rhs: &[Literal]) -> Ordering {
174    let mut lhs = lhs.iter().collect::<Vec<_>>();
175    let mut rhs = rhs.iter().collect::<Vec<_>>();
176    lhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
177    rhs.sort_by(|lhs, rhs| lhs.essence_cmp(rhs));
178
179    let (mut lhs_index, mut rhs_index) = (0, 0);
180    while lhs_index < lhs.len() && rhs_index < rhs.len() {
181        match lhs[lhs_index].essence_cmp(rhs[rhs_index]) {
182            Ordering::Equal => {
183                lhs_index += 1;
184                rhs_index += 1;
185            }
186            // `lhs` contains the least differing element and `rhs` does not.
187            Ordering::Less => return Ordering::Greater,
188            // `rhs` contains the least differing element and `lhs` does not.
189            Ordering::Greater => return Ordering::Less,
190        }
191    }
192    match (lhs_index < lhs.len(), rhs_index < rhs.len()) {
193        (false, false) => Ordering::Equal,
194        (true, false) => Ordering::Greater,
195        (false, true) => Ordering::Less,
196        (true, true) => unreachable!(),
197    }
198}
199
200// make possible values of an AbstractLiteral a closed world to make the trait bounds more sane (particularly in Uniplate instances!!)
201pub trait AbstractLiteralValue:
202    Clone + Eq + PartialEq + Display + Uniplate + Biplate<Field<Self>> + 'static
203{
204    type Dom: Clone
205        + Eq
206        + PartialEq
207        + Debug
208        + Display
209        + Quine
210        + From<GroundDomain>
211        + Into<DomainPtr>;
212
213    /// Returns whether `domain` is the implicit one-based list index domain.
214    fn has_implied_list_domain(domain: &Self::Dom) -> bool;
215}
216impl AbstractLiteralValue for Expression {
217    type Dom = DomainPtr;
218
219    fn has_implied_list_domain(domain: &Self::Dom) -> bool {
220        let Domain::Ground(domain) = domain.as_ref() else {
221            return false;
222        };
223        matches!(domain.as_ref(), GroundDomain::Int(ranges) if ranges.as_slice() == [Range::UnboundedR(1)])
224    }
225}
226impl AbstractLiteralValue for Literal {
227    type Dom = Moo<GroundDomain>;
228
229    fn has_implied_list_domain(domain: &Self::Dom) -> bool {
230        matches!(domain.as_ref(), GroundDomain::Int(ranges) if ranges.as_slice() == [Range::UnboundedR(1)])
231    }
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
235#[path_prefix(conjure_cp::ast)]
236pub enum AbstractLiteral<T: AbstractLiteralValue> {
237    Set(Vec<T>),
238
239    MSet(Vec<T>),
240
241    /// A 1 dimensional matrix slice with an index domain.
242    Matrix(Vec<T>, T::Dom),
243
244    // a tuple of literals
245    Tuple(Vec<T>),
246
247    Record(Vec<Field<T>>),
248
249    Sequence(Vec<T>),
250
251    Function(Vec<(T, T)>),
252
253    // Variants only contain one of their name-domain pairs
254    Variant(Moo<Field<T>>),
255
256    // A list of partitions, each part has a set of values
257    Partition(Vec<Vec<T>>),
258    Relation(Vec<Vec<T>>),
259
260    /// Cycle notation for a permutation: each inner vec is one cycle. Unlike `Partition`, this is
261    /// *sparse* -- any element of the permutation's domain not mentioned in any cycle is an
262    /// implicit fixed point (maps to itself), rather than every element needing to be covered.
263    Permutation(Vec<Vec<T>>),
264}
265
266// TODO: use HasDomain instead once Expression::domain_of returns Domain not Option<Domain>
267fn union_item_domains(item_domains: Vec<DomainPtr>, literal_kind: &str) -> Option<DomainPtr> {
268    let mut item_domain_iter = item_domains.into_iter();
269    let first_item = item_domain_iter.next()?;
270
271    Some(
272        item_domain_iter
273            .try_fold(first_item, |x, y| x.union(&y))
274            .unwrap_or_else(|error| {
275                bug!(
276                    "taking the union of all item domains of a {literal_kind} literal should succeed: {error}"
277                )
278            }),
279    )
280}
281
282impl AbstractLiteral<Expression> {
283    pub fn domain_of(&self) -> Option<DomainPtr> {
284        match self {
285            AbstractLiteral::Set(items) => {
286                // ensure that all items have a domain, or return None
287                let item_domains: Vec<DomainPtr> = items
288                    .iter()
289                    .map(|x| x.domain_of())
290                    .collect::<Option<Vec<DomainPtr>>>()?;
291
292                // union all item domains together
293                let item_domain = union_item_domains(item_domains, "set")?;
294
295                Some(Domain::set(SetAttr::<Int>::default(), item_domain))
296            }
297
298            AbstractLiteral::MSet(items) => {
299                let cardinality = i32::try_from(items.len()).ok()?;
300                // ensure that all items have a domain, or return None
301                let item_domains: Vec<DomainPtr> = items
302                    .iter()
303                    .map(|x| x.domain_of())
304                    .collect::<Option<Vec<DomainPtr>>>()?;
305
306                // union all item domains together
307                let item_domain = union_item_domains(item_domains, "mset")?;
308
309                let occurrence = if cardinality == 0 {
310                    Range::Single(0)
311                } else {
312                    Range::Bounded(1, cardinality)
313                };
314                Some(Domain::mset(
315                    MSetAttr::new(Range::Single(cardinality), occurrence),
316                    item_domain,
317                ))
318            }
319
320            AbstractLiteral::Sequence(elems) => {
321                let item_domains: Vec<DomainPtr> = elems
322                    .iter()
323                    .map(|x| x.domain_of())
324                    .collect::<Option<Vec<DomainPtr>>>()?;
325
326                // Get the union of all domains in the sequence.
327                // i.e. if <(1..3), (1..3), (5), (8..9)> then seq dom is (1..3, 5, 8..9)
328                let item_domain = union_item_domains(item_domains, "sequence")?;
329
330                // The literal's own length is its size: without it nothing downstream can tell
331                // how many positions the sequence has.
332                let size = Range::Single(i32::try_from(elems.len()).ok()?);
333                Some(Domain::sequence(
334                    SequenceAttr::<Int> {
335                        size,
336                        ..SequenceAttr::default()
337                    },
338                    item_domain,
339                ))
340            }
341
342            AbstractLiteral::Partition(items) => {
343                // Flatten the Vec<Vec< into a single vec
344                // ensure that all elemes in each part have a domain, or return None
345
346                let item_domains: Vec<DomainPtr> = items
347                    .iter()
348                    .flatten()
349                    .map(|x| x.domain_of())
350                    .collect::<Option<Vec<DomainPtr>>>()?;
351
352                // union all item domains together
353                let item_domain = union_item_domains(item_domains, "partition")?;
354
355                Some(Domain::partition(
356                    PartitionAttr::<Int>::default(),
357                    item_domain,
358                ))
359            }
360
361            AbstractLiteral::Permutation(cycles) => {
362                // Flatten the Vec<Vec< into a single vec; unlike partition, elements not
363                // mentioned in any cycle are implicit fixed points, so an empty literal (or one
364                // with no domain-bearing elements) has no way to infer an inner domain.
365                let item_domains: Vec<DomainPtr> = cycles
366                    .iter()
367                    .flatten()
368                    .map(|x| x.domain_of())
369                    .collect::<Option<Vec<DomainPtr>>>()?;
370
371                let item_domain = union_item_domains(item_domains, "permutation")?;
372
373                Some(Domain::permutation(
374                    PermutationAttr::<Int>::default(),
375                    item_domain,
376                ))
377            }
378
379            AbstractLiteral::Matrix(items, _) => {
380                // ensure that all items have a domain, or return None
381                let item_domains = items
382                    .iter()
383                    .map(|x| x.domain_of())
384                    .collect::<Option<Vec<DomainPtr>>>()?;
385
386                // union all item domains together
387                let item_domain = union_item_domains(item_domains, "matrix")?;
388
389                let mut new_index_domain = vec![];
390
391                // flatten index domains of n-d matrix into list
392                let mut e = Expression::AbstractLiteral(Metadata::new(), self.clone());
393                while let Expression::AbstractLiteral(_, AbstractLiteral::Matrix(elems, idx)) = e {
394                    bug_assert!(
395                        idx.as_matrix().is_none(),
396                        "n-dimensional matrix literals should be represented as a matrix inside a matrix, got {idx}"
397                    );
398                    new_index_domain.push(idx);
399                    e = elems[0].clone();
400                }
401                Some(Domain::matrix(item_domain, new_index_domain))
402            }
403            AbstractLiteral::Tuple(_) => None,
404            AbstractLiteral::Record(_) => None,
405            AbstractLiteral::Function(_) => None,
406            AbstractLiteral::Variant(_) => None,
407            AbstractLiteral::Relation(_) => None,
408        }
409    }
410}
411
412impl HasDomain for AbstractLiteral<Literal> {
413    fn domain_of(&self) -> DomainPtr {
414        Domain::from_literal_vec(&[Literal::AbstractLiteral(self.clone())])
415            .expect("abstract literals should be correctly typed")
416    }
417}
418
419impl Typeable for AbstractLiteral<Expression> {
420    fn return_type(&self) -> ReturnType {
421        match self {
422            AbstractLiteral::Set(items) if items.is_empty() => {
423                ReturnType::Set(Box::new(ReturnType::Unknown))
424            }
425            AbstractLiteral::Set(items) => {
426                let item_type = items[0].return_type();
427
428                // if any items do not have a type, return none.
429                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
430
431                bug_assert!(
432                    item_types.iter().all(|x| x == &item_type),
433                    "all items in a set should have the same type"
434                );
435
436                ReturnType::Set(Box::new(item_type))
437            }
438            AbstractLiteral::MSet(items) if items.is_empty() => {
439                ReturnType::MSet(Box::new(ReturnType::Unknown))
440            }
441            AbstractLiteral::MSet(items) => {
442                let item_type = items[0].return_type();
443
444                // if any items do not have a type, return none.
445                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
446
447                bug_assert!(
448                    item_types.iter().all(|x| x == &item_type),
449                    "all items in a set should have the same type"
450                );
451
452                ReturnType::MSet(Box::new(item_type))
453            }
454            AbstractLiteral::Sequence(items) if items.is_empty() => {
455                ReturnType::Sequence(Box::new(ReturnType::Unknown))
456            }
457            AbstractLiteral::Sequence(items) => {
458                let item_type = items[0].return_type();
459
460                // if any items do not have a type, return none.
461                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
462
463                bug_assert!(
464                    item_types.iter().all(|x| x == &item_type),
465                    "all items in a sequence should have the same type"
466                );
467
468                ReturnType::Sequence(Box::new(item_type))
469            }
470            AbstractLiteral::Partition(items) if items.is_empty() || items[0].is_empty() => {
471                ReturnType::Partition(Box::new(ReturnType::Unknown))
472            }
473            AbstractLiteral::Partition(items) => {
474                let item_type = items[0][0].return_type();
475
476                // if any items do not have a type, return none.
477                let item_types: Vec<ReturnType> =
478                    items.iter().flatten().map(|x| x.return_type()).collect();
479
480                bug_assert!(
481                    item_types.iter().all(|x| x == &item_type),
482                    "all items in every part of a partition should have the same type"
483                );
484
485                ReturnType::Partition(Box::new(item_type))
486            }
487            AbstractLiteral::Permutation(items) if items.is_empty() || items[0].is_empty() => {
488                ReturnType::Permutation(Box::new(ReturnType::Unknown))
489            }
490            AbstractLiteral::Permutation(items) => {
491                let item_type = items[0][0].return_type();
492
493                let item_types: Vec<ReturnType> =
494                    items.iter().flatten().map(|x| x.return_type()).collect();
495
496                bug_assert!(
497                    item_types.iter().all(|x| x == &item_type),
498                    "all items in every cycle of a permutation should have the same type"
499                );
500
501                ReturnType::Permutation(Box::new(item_type))
502            }
503            AbstractLiteral::Matrix(items, _) if items.is_empty() => {
504                ReturnType::Matrix(Box::new(ReturnType::Unknown))
505            }
506            AbstractLiteral::Matrix(items, _) => {
507                let item_type = items[0].return_type();
508
509                // if any items do not have a type, return none.
510                let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
511
512                bug_assert!(
513                    item_types.iter().all(|x| x == &item_type),
514                    "all items in a matrix should have the same type. items: {items} types: {types:#?}",
515                    items = pretty_vec(items),
516                    types = items
517                        .iter()
518                        .map(|x| x.return_type())
519                        .collect::<Vec<ReturnType>>()
520                );
521
522                ReturnType::Matrix(Box::new(item_type))
523            }
524            AbstractLiteral::Tuple(items) => {
525                let mut item_types = vec![];
526                for item in items {
527                    item_types.push(item.return_type());
528                }
529                ReturnType::Tuple(item_types)
530            }
531            AbstractLiteral::Record(items) => {
532                let mut item_types = vec![];
533                for item in items {
534                    item_types.push(item.clone().func_map(|x| x.return_type()));
535                }
536                ReturnType::Record(item_types)
537            }
538            AbstractLiteral::Function(items) => {
539                if items.is_empty() {
540                    return ReturnType::Function(
541                        Box::new(ReturnType::Unknown),
542                        Box::new(ReturnType::Unknown),
543                    );
544                }
545
546                // Check that all items have the same return type
547                let (x1, y1) = &items[0];
548                let (t1, t2) = (x1.return_type(), y1.return_type());
549                for (x, y) in items {
550                    let (tx, ty) = (x.return_type(), y.return_type());
551                    if tx != t1 {
552                        bug!("Expected {t1}, got {x}: {tx}");
553                    }
554                    if ty != t2 {
555                        bug!("Expected {t2}, got {y}: {ty}");
556                    }
557                }
558
559                ReturnType::Function(Box::new(t1), Box::new(t2))
560            }
561            AbstractLiteral::Variant(item) => {
562                // Variants hold multiple possible types. In the case of a literal we know which type it chose
563                ReturnType::Variant(vec![item.as_ref().clone().func_map(|x| x.return_type())])
564            }
565            AbstractLiteral::Relation(items) => {
566                if items.is_empty() {
567                    return ReturnType::Relation(vec![ReturnType::Unknown]);
568                }
569                let mut item_types = vec![];
570                let x1 = &items[0];
571                let size = x1.len();
572                for item in x1 {
573                    item_types.push(item.return_type());
574                }
575                for x in items {
576                    if x.len() != size {
577                        let strs = item_types.iter().map(|x| format!("{}", x)).join(",");
578                        bug!("Expected ({strs}) with length {size}, got size {}", x.len());
579                    }
580                    for i in 1..size {
581                        if let Some(new_type) = x.get(i)
582                            && let Some(old_type) = item_types.get(i)
583                            && new_type.return_type() != *old_type
584                        {
585                            bug!("Expected {old_type}, got {new_type}");
586                        }
587                    }
588                }
589                ReturnType::Relation(item_types)
590            }
591        }
592    }
593}
594
595impl<T> AbstractLiteral<T>
596where
597    T: AbstractLiteralValue,
598{
599    /// Creates a matrix with elements `elems`, with domain `int(1..)`.
600    ///
601    /// This acts as a variable sized list.
602    pub fn matrix_implied_indices(elems: Vec<T>) -> Self {
603        AbstractLiteral::Matrix(elems, GroundDomain::Int(vec![Range::UnboundedR(1)]).into())
604    }
605
606    /// If the AbstractLiteral is a list, returns its elements.
607    ///
608    /// A list is any a matrix with the domain `int(1..)`. This includes matrix literals without
609    /// any explicitly specified domain.
610    pub fn unwrap_list(&self) -> Option<&Vec<T>> {
611        let AbstractLiteral::Matrix(elems, domain) = self else {
612            return None;
613        };
614
615        T::has_implied_list_domain(domain).then_some(elems)
616    }
617
618    /// If this abstract literal is a list, consumes it and returns its elements.
619    pub fn into_list(self) -> Option<Vec<T>> {
620        let AbstractLiteral::Matrix(elems, domain) = self else {
621            return None;
622        };
623
624        T::has_implied_list_domain(&domain).then_some(elems)
625    }
626}
627
628impl<T> Display for AbstractLiteral<T>
629where
630    T: AbstractLiteralValue,
631{
632    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
633        match self {
634            AbstractLiteral::Set(elems) => {
635                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
636                write!(f, "{{{elems_str}}}")
637            }
638            AbstractLiteral::MSet(elems) => {
639                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
640                write!(f, "mset({elems_str})")
641            }
642            AbstractLiteral::Matrix(elems, index_domain) => {
643                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
644                write!(f, "[{elems_str};{index_domain}]")
645            }
646            AbstractLiteral::Tuple(elems) => {
647                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
648                write!(f, "({elems_str})")
649            }
650            AbstractLiteral::Sequence(elems) => {
651                let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
652                write!(f, "sequence({elems_str})")
653            }
654            AbstractLiteral::Partition(parts) => {
655                let elems_str: String = parts
656                    .iter()
657                    .map(|inner| {
658                        let elems_str = inner.iter().map(|x| format!("{x}")).join(",");
659                        format!("{{{}}}", elems_str)
660                    })
661                    .join(", ");
662
663                write!(f, "partition({elems_str})")
664            }
665            AbstractLiteral::Permutation(cycles) => {
666                let cycles_str: String = cycles
667                    .iter()
668                    .map(|cycle| {
669                        let elems_str = cycle.iter().map(|x| format!("{x}")).join(",");
670                        format!("({elems_str})")
671                    })
672                    .join("");
673
674                write!(f, "permutation{cycles_str}")
675            }
676            AbstractLiteral::Record(entries) => {
677                let entries_str: String = entries
678                    .iter()
679                    .map(|entry| format!("{} = {}", entry.name, entry.value))
680                    .join(",");
681                write!(f, "record {{{entries_str}}}")
682            }
683            AbstractLiteral::Function(entries) => {
684                let entries_str: String = entries
685                    .iter()
686                    .map(|entry| format!("{} --> {}", entry.0, entry.1))
687                    .join(",");
688                write!(f, "function({entries_str})")
689            }
690            AbstractLiteral::Variant(entry) => {
691                write!(f, "variant{{{} = {}}}", entry.name, entry.value)
692            }
693            AbstractLiteral::Relation(elems) => {
694                let elems_str: String = elems
695                    .iter()
696                    .map(|x| format!("({})", x.iter().map(|x| format!("{x}")).join(",")))
697                    .join(",");
698                write!(f, "relation({elems_str})")
699            }
700        }
701    }
702}
703
704impl<T> Uniplate for AbstractLiteral<T>
705where
706    T: AbstractLiteralValue + Biplate<AbstractLiteral<T>>,
707{
708    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
709        // walking into T
710        match self {
711            AbstractLiteral::Set(vec) => {
712                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
713                (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
714            }
715            AbstractLiteral::MSet(vec) => {
716                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
717                (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
718            }
719            AbstractLiteral::Matrix(elems, index_domain) => {
720                let index_domain = index_domain.clone();
721                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
722                (
723                    f1_tree,
724                    Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
725                )
726            }
727            AbstractLiteral::Sequence(vec) => {
728                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(vec);
729                (
730                    f1_tree,
731                    Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
732                )
733            }
734            AbstractLiteral::Tuple(elems) => {
735                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
736                (
737                    f1_tree,
738                    Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
739                )
740            }
741            AbstractLiteral::Record(entries) => {
742                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
743                (
744                    f1_tree,
745                    Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
746                )
747            }
748            AbstractLiteral::Function(entries) => {
749                let entry_count = entries.len();
750                let flattened: Vec<T> = entries
751                    .iter()
752                    .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
753                    .collect();
754
755                let (f1_tree, f1_ctx) =
756                    <Vec<T> as Biplate<AbstractLiteral<T>>>::biplate(&flattened);
757                (
758                    f1_tree,
759                    Box::new(move |x| {
760                        let rebuilt = f1_ctx(x);
761                        assert_eq!(
762                            rebuilt.len(),
763                            entry_count * 2,
764                            "number of function literal children should remain unchanged"
765                        );
766
767                        let mut iter = rebuilt.into_iter();
768                        let mut pairs = Vec::with_capacity(entry_count);
769                        while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
770                            pairs.push((lhs, rhs));
771                        }
772
773                        AbstractLiteral::Function(pairs)
774                    }),
775                )
776            }
777            AbstractLiteral::Variant(entries) => {
778                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(entries);
779                (
780                    f1_tree,
781                    Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
782                )
783            }
784            AbstractLiteral::Relation(elems) => {
785                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
786                (
787                    f1_tree,
788                    Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
789                )
790            }
791            AbstractLiteral::Partition(elems) => {
792                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
793                (
794                    f1_tree,
795                    Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
796                )
797            }
798            AbstractLiteral::Permutation(elems) => {
799                let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
800                (
801                    f1_tree,
802                    Box::new(move |x| AbstractLiteral::Permutation(f1_ctx(x))),
803                )
804            }
805        }
806    }
807}
808
809impl<U, To> Biplate<To> for AbstractLiteral<U>
810where
811    To: Uniplate,
812    U: AbstractLiteralValue + Biplate<AbstractLiteral<U>> + Biplate<To>,
813    Field<U>: Biplate<AbstractLiteral<U>> + Biplate<To>,
814{
815    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
816        if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
817            // To ==From => return One(self)
818
819            unsafe {
820                // SAFETY: asserted the type equality above
821                let self_to = std::mem::transmute::<&AbstractLiteral<U>, &To>(self).clone();
822                let tree = Tree::One(self_to);
823                let ctx = Box::new(move |x| {
824                    let Tree::One(x) = x else {
825                        panic!();
826                    };
827
828                    std::mem::transmute::<&To, &AbstractLiteral<U>>(&x).clone()
829                });
830
831                (tree, ctx)
832            }
833        } else {
834            // walking into T
835            match self {
836                AbstractLiteral::Set(vec) => {
837                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
838                    (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
839                }
840                AbstractLiteral::MSet(vec) => {
841                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
842                    (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
843                }
844                AbstractLiteral::Matrix(elems, index_domain) => {
845                    let index_domain = index_domain.clone();
846                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(elems);
847                    (
848                        f1_tree,
849                        Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
850                    )
851                }
852                AbstractLiteral::Sequence(vec) => {
853                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
854                    (
855                        f1_tree,
856                        Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
857                    )
858                }
859                AbstractLiteral::Tuple(elems) => {
860                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
861                    (
862                        f1_tree,
863                        Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
864                    )
865                }
866                AbstractLiteral::Record(entries) => {
867                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
868                    (
869                        f1_tree,
870                        Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
871                    )
872                }
873                AbstractLiteral::Function(entries) => {
874                    let entry_count = entries.len();
875                    let flattened: Vec<U> = entries
876                        .iter()
877                        .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
878                        .collect();
879
880                    let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(&flattened);
881                    (
882                        f1_tree,
883                        Box::new(move |x| {
884                            let rebuilt = f1_ctx(x);
885                            assert_eq!(
886                                rebuilt.len(),
887                                entry_count * 2,
888                                "number of function literal children should remain unchanged"
889                            );
890
891                            let mut iter = rebuilt.into_iter();
892                            let mut pairs = Vec::with_capacity(entry_count);
893                            while let (Some(lhs), Some(rhs)) = (iter.next(), iter.next()) {
894                                pairs.push((lhs, rhs));
895                            }
896
897                            AbstractLiteral::Function(pairs)
898                        }),
899                    )
900                }
901                AbstractLiteral::Variant(entries) => {
902                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
903                    (
904                        f1_tree,
905                        Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
906                    )
907                }
908                AbstractLiteral::Relation(elems) => {
909                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
910                    (
911                        f1_tree,
912                        Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
913                    )
914                }
915                AbstractLiteral::Partition(elems) => {
916                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
917                    (
918                        f1_tree,
919                        Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
920                    )
921                }
922                AbstractLiteral::Permutation(elems) => {
923                    let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
924                    (
925                        f1_tree,
926                        Box::new(move |x| AbstractLiteral::Permutation(f1_ctx(x))),
927                    )
928                }
929            }
930        }
931    }
932
933    fn children_bi_count(&self) -> usize {
934        // Manual `biplate` (not derive): delegate counts to the plated containers so wide
935        // matrices/lists stay O(1) instead of materialising `children_bi`.
936        if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
937            return 1;
938        }
939        match self {
940            AbstractLiteral::Set(v)
941            | AbstractLiteral::MSet(v)
942            | AbstractLiteral::Sequence(v)
943            | AbstractLiteral::Tuple(v)
944            | AbstractLiteral::Matrix(v, _) => <Vec<U> as Biplate<To>>::children_bi_count(v),
945            AbstractLiteral::Record(entries) => {
946                <Vec<Field<U>> as Biplate<To>>::children_bi_count(entries)
947            }
948            AbstractLiteral::Variant(entry) => {
949                <Moo<Field<U>> as Biplate<To>>::children_bi_count(entry)
950            }
951            AbstractLiteral::Relation(elems)
952            | AbstractLiteral::Partition(elems)
953            | AbstractLiteral::Permutation(elems) => {
954                <Vec<Vec<U>> as Biplate<To>>::children_bi_count(elems)
955            }
956            AbstractLiteral::Function(_) => <Self as Biplate<To>>::children_bi(self).len(),
957        }
958    }
959
960    fn try_replace_child_at_bi(&mut self, index: usize, child: To) -> bool {
961        // Same as `children_bi_count`: keep in-place updates for owned vectors (lee-distance).
962        if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
963            if index != 0 {
964                return false;
965            }
966            // SAFETY: TypeId equality means To and AbstractLiteral<U> are the same type.
967            unsafe {
968                let child_as_self = std::mem::transmute_copy::<To, AbstractLiteral<U>>(&child);
969                std::mem::forget(child);
970                *self = child_as_self;
971            }
972            return true;
973        }
974        match self {
975            AbstractLiteral::Set(v)
976            | AbstractLiteral::MSet(v)
977            | AbstractLiteral::Sequence(v)
978            | AbstractLiteral::Tuple(v)
979            | AbstractLiteral::Matrix(v, _) => {
980                <Vec<U> as Biplate<To>>::try_replace_child_at_bi(v, index, child)
981            }
982            AbstractLiteral::Record(entries) => {
983                <Vec<Field<U>> as Biplate<To>>::try_replace_child_at_bi(entries, index, child)
984            }
985            AbstractLiteral::Variant(entry) => {
986                <Moo<Field<U>> as Biplate<To>>::try_replace_child_at_bi(entry, index, child)
987            }
988            AbstractLiteral::Relation(elems)
989            | AbstractLiteral::Partition(elems)
990            | AbstractLiteral::Permutation(elems) => {
991                <Vec<Vec<U>> as Biplate<To>>::try_replace_child_at_bi(elems, index, child)
992            }
993            AbstractLiteral::Function(_) => {
994                let mut children = <Self as Biplate<To>>::children_bi(self);
995                if index >= children.len() {
996                    return false;
997                }
998                children[index] = child;
999                *self = self.with_children_bi(children);
1000                true
1001            }
1002        }
1003    }
1004}
1005
1006impl TryFrom<Literal> for i32 {
1007    type Error = &'static str;
1008
1009    fn try_from(value: Literal) -> Result<Self, Self::Error> {
1010        match value {
1011            Literal::Int(i) => Ok(i),
1012            _ => Err("Cannot convert non-i32 literal to i32"),
1013        }
1014    }
1015}
1016
1017impl TryFrom<Box<Literal>> for i32 {
1018    type Error = &'static str;
1019
1020    fn try_from(value: Box<Literal>) -> Result<Self, Self::Error> {
1021        (*value).try_into()
1022    }
1023}
1024
1025impl TryFrom<&Box<Literal>> for i32 {
1026    type Error = &'static str;
1027
1028    fn try_from(value: &Box<Literal>) -> Result<Self, Self::Error> {
1029        TryFrom::<&Literal>::try_from(value.as_ref())
1030    }
1031}
1032
1033impl TryFrom<&Moo<Literal>> for i32 {
1034    type Error = &'static str;
1035
1036    fn try_from(value: &Moo<Literal>) -> Result<Self, Self::Error> {
1037        TryFrom::<&Literal>::try_from(value.as_ref())
1038    }
1039}
1040
1041impl TryFrom<&Literal> for i32 {
1042    type Error = &'static str;
1043
1044    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
1045        match value {
1046            Literal::Int(i) => Ok(*i),
1047            _ => Err("Cannot convert non-i32 literal to i32"),
1048        }
1049    }
1050}
1051
1052impl TryFrom<Literal> for bool {
1053    type Error = &'static str;
1054
1055    fn try_from(value: Literal) -> Result<Self, Self::Error> {
1056        match value {
1057            Literal::Bool(b) => Ok(b),
1058            _ => Err("Cannot convert non-bool literal to bool"),
1059        }
1060    }
1061}
1062
1063impl TryFrom<&Literal> for bool {
1064    type Error = &'static str;
1065
1066    fn try_from(value: &Literal) -> Result<Self, Self::Error> {
1067        match value {
1068            Literal::Bool(b) => Ok(*b),
1069            _ => Err("Cannot convert non-bool literal to bool"),
1070        }
1071    }
1072}
1073
1074impl From<i32> for Literal {
1075    fn from(i: i32) -> Self {
1076        Literal::Int(i)
1077    }
1078}
1079
1080impl From<bool> for Literal {
1081    fn from(b: bool) -> Self {
1082        Literal::Bool(b)
1083    }
1084}
1085
1086impl From<Literal> for Ustr {
1087    fn from(value: Literal) -> Self {
1088        // TODO: avoid the temporary-allocation of a string by format! here?
1089        Ustr::from(&format!("{value}"))
1090    }
1091}
1092
1093impl From<AbstractLiteral<Literal>> for Literal {
1094    fn from(literal: AbstractLiteral<Literal>) -> Self {
1095        Literal::AbstractLiteral(literal)
1096    }
1097}
1098
1099impl AbstractLiteral<Expression> {
1100    /// If all the elements are literals, returns this as an AbstractLiteral<Literal>.
1101    /// Otherwise, returns `None`.
1102    pub fn into_literals(self) -> Option<AbstractLiteral<Literal>> {
1103        match self {
1104            AbstractLiteral::Set(elements) => {
1105                let literals = elements
1106                    .into_iter()
1107                    .map(|expr| match expr {
1108                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1109                        Expression::AbstractLiteral(_, abslit) => {
1110                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
1111                        }
1112                        _ => None,
1113                    })
1114                    .collect::<Option<Vec<_>>>()?;
1115                Some(AbstractLiteral::Set(literals))
1116            }
1117            AbstractLiteral::MSet(elements) => {
1118                let literals = elements
1119                    .into_iter()
1120                    .map(|expr| match expr {
1121                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1122                        Expression::AbstractLiteral(_, abslit) => {
1123                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
1124                        }
1125                        _ => None,
1126                    })
1127                    .collect::<Option<Vec<_>>>()?;
1128                Some(AbstractLiteral::MSet(literals))
1129            }
1130            AbstractLiteral::Partition(elems) => {
1131                // want to ascertain if every elem in Vec<Vec<Expr>> is a literal. If any are not, return none
1132                // otherwise confirm it is an abslit<lit>
1133                let mut partition: Vec<Vec<_>> = Vec::new();
1134
1135                for part in elems {
1136                    let literals = part
1137                        .into_iter()
1138                        .map(|expr| match expr {
1139                            Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1140                            Expression::AbstractLiteral(_, abslit) => {
1141                                Some(Literal::AbstractLiteral(abslit.into_literals()?))
1142                            }
1143                            _ => None,
1144                        })
1145                        .collect::<Option<Vec<_>>>()?;
1146
1147                    partition.push(literals);
1148                }
1149
1150                Some(AbstractLiteral::Partition(partition))
1151            }
1152            AbstractLiteral::Permutation(elems) => {
1153                let mut permutation: Vec<Vec<_>> = Vec::new();
1154
1155                for cycle in elems {
1156                    let literals = cycle
1157                        .into_iter()
1158                        .map(|expr| match expr {
1159                            Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1160                            Expression::AbstractLiteral(_, abslit) => {
1161                                Some(Literal::AbstractLiteral(abslit.into_literals()?))
1162                            }
1163                            _ => None,
1164                        })
1165                        .collect::<Option<Vec<_>>>()?;
1166
1167                    permutation.push(literals);
1168                }
1169
1170                Some(AbstractLiteral::Permutation(permutation))
1171            }
1172            AbstractLiteral::Matrix(items, domain) => {
1173                let mut literals = vec![];
1174                for item in items {
1175                    let literal = match item {
1176                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1177                        Expression::AbstractLiteral(_, abslit) => {
1178                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
1179                        }
1180                        _ => None,
1181                    }?;
1182                    literals.push(literal);
1183                }
1184
1185                Some(AbstractLiteral::Matrix(literals, domain.resolve().ok()?))
1186            }
1187            AbstractLiteral::Sequence(elements) => {
1188                let literals = elements
1189                    .into_iter()
1190                    .map(|expr| match expr {
1191                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1192                        Expression::AbstractLiteral(_, abslit) => {
1193                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
1194                        }
1195                        _ => None,
1196                    })
1197                    .collect::<Option<Vec<_>>>()?;
1198                Some(AbstractLiteral::Sequence(literals))
1199            }
1200            AbstractLiteral::Tuple(items) => {
1201                let mut literals = vec![];
1202                for item in items {
1203                    let literal = match item {
1204                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1205                        Expression::AbstractLiteral(_, abslit) => {
1206                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
1207                        }
1208                        _ => None,
1209                    }?;
1210                    literals.push(literal);
1211                }
1212
1213                Some(AbstractLiteral::Tuple(literals))
1214            }
1215            AbstractLiteral::Record(entries) => {
1216                let mut literals = vec![];
1217                for entry in entries {
1218                    let literal = match entry.value {
1219                        Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1220                        Expression::AbstractLiteral(_, abslit) => {
1221                            Some(Literal::AbstractLiteral(abslit.into_literals()?))
1222                        }
1223                        _ => None,
1224                    }?;
1225
1226                    literals.push((entry.name, literal));
1227                }
1228                Some(AbstractLiteral::Record(
1229                    literals
1230                        .into_iter()
1231                        .map(|(name, literal)| Field {
1232                            name,
1233                            value: literal,
1234                        })
1235                        .collect(),
1236                ))
1237            }
1238            AbstractLiteral::Function(_) => todo!("Implement into_literals for functions"),
1239            AbstractLiteral::Variant(entry) => {
1240                let literal = match entry.value.clone() {
1241                    Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1242                    Expression::AbstractLiteral(_, abslit) => {
1243                        Some(Literal::AbstractLiteral(abslit.into_literals()?))
1244                    }
1245                    _ => None,
1246                }?;
1247                Some(AbstractLiteral::Variant(Moo::new(Field {
1248                    name: entry.name.clone(),
1249                    value: literal,
1250                })))
1251            }
1252            AbstractLiteral::Relation(tuples) => {
1253                let mut literal_tuples = Vec::with_capacity(tuples.len());
1254                for fields in tuples {
1255                    let literals = fields
1256                        .into_iter()
1257                        .map(|expr| match expr {
1258                            Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
1259                            Expression::AbstractLiteral(_, abslit) => {
1260                                Some(Literal::AbstractLiteral(abslit.into_literals()?))
1261                            }
1262                            _ => None,
1263                        })
1264                        .collect::<Option<Vec<_>>>()?;
1265                    literal_tuples.push(literals);
1266                }
1267                Some(AbstractLiteral::Relation(literal_tuples))
1268            }
1269        }
1270    }
1271}
1272
1273// need display implementations for other types as well
1274impl Display for Literal {
1275    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1276        match &self {
1277            Literal::Int(i) => write!(f, "{i}"),
1278            Literal::Bool(b) => write!(f, "{b}"),
1279            Literal::AbstractLiteral(l) => write!(f, "{l}"),
1280        }
1281    }
1282}
1283
1284#[cfg(test)]
1285mod tests {
1286
1287    use super::*;
1288    use crate::ast::matrix::{flatten, partial_flatten, shape_of};
1289    use crate::ast::{DeclarationPtr, Name};
1290    use crate::{domain_int_ground, into_matrix, matrix, matrix_lit, range};
1291    use uniplate::Uniplate;
1292
1293    #[test]
1294    fn essence_value_ordering_uses_occurrence_lex_for_sets() {
1295        let set = |values: &[i32]| {
1296            Literal::AbstractLiteral(AbstractLiteral::Set(
1297                values.iter().copied().map(Literal::Int).collect(),
1298            ))
1299        };
1300        let ordered = [
1301            set(&[]),
1302            set(&[3]),
1303            set(&[2]),
1304            set(&[2, 3]),
1305            set(&[1]),
1306            set(&[1, 3]),
1307            set(&[1, 2]),
1308            set(&[1, 2, 3]),
1309        ];
1310
1311        for pair in ordered.windows(2) {
1312            assert_eq!(pair[0].essence_cmp(&pair[1]), Ordering::Less);
1313        }
1314    }
1315
1316    #[test]
1317    fn essence_value_ordering_is_lexicographic_for_tuples_and_matrices() {
1318        let tuple = |values: &[i32]| {
1319            Literal::AbstractLiteral(AbstractLiteral::Tuple(
1320                values.iter().copied().map(Literal::Int).collect(),
1321            ))
1322        };
1323        assert_eq!(tuple(&[1, 2]).essence_cmp(&tuple(&[1, 3])), Ordering::Less);
1324        assert_eq!(
1325            tuple(&[1, 2]).essence_cmp(&tuple(&[1, 2, 0])),
1326            Ordering::Less
1327        );
1328
1329        let matrix = |values: &[i32]| {
1330            Literal::AbstractLiteral(AbstractLiteral::Matrix(
1331                values.iter().copied().map(Literal::Int).collect(),
1332                Moo::new(GroundDomain::Int(vec![Range::Bounded(
1333                    1,
1334                    values.len() as i32,
1335                )])),
1336            ))
1337        };
1338        assert_eq!(
1339            matrix(&[1, 2]).essence_cmp(&matrix(&[1, 3])),
1340            Ordering::Less
1341        );
1342    }
1343
1344    #[test]
1345    fn mset_domain_accepts_domain_letting_references() {
1346        let declaration = DeclarationPtr::new_domain_letting(
1347            Name::user("NUM"),
1348            Domain::int(vec![Range::Bounded(1, 999)]),
1349        );
1350        let alias = Domain::reference(declaration).unwrap();
1351        let item = Expression::DomainAnnotation(
1352            Metadata::new(),
1353            Moo::new(Expression::Atomic(
1354                Metadata::new(),
1355                Atom::Literal(Literal::Int(1)),
1356            )),
1357            alias,
1358        );
1359
1360        let domain = AbstractLiteral::MSet(vec![item.clone(), item])
1361            .domain_of()
1362            .unwrap();
1363        let (_, item_domain) = domain.as_mset().unwrap();
1364
1365        assert_eq!(
1366            item_domain.resolve(),
1367            Ok(Moo::new(GroundDomain::Int(vec![Range::Bounded(1, 999)])))
1368        );
1369    }
1370
1371    #[test]
1372    fn matrix_uniplate_universe() {
1373        // Can we traverse through matrices with uniplate?
1374        let my_matrix: AbstractLiteral<Literal> = into_matrix![
1375            vec![Literal::AbstractLiteral(matrix![Literal::Bool(true);Moo::new(GroundDomain::Bool)]); 5];
1376            Moo::new(GroundDomain::Bool)
1377        ];
1378
1379        let expected_index_domains = vec![Moo::new(GroundDomain::Bool); 6];
1380        let actual_index_domains: Vec<Moo<GroundDomain>> =
1381            my_matrix.cata(&move |elem, children| {
1382                let mut res = vec![];
1383                res.extend(children.into_iter().flatten());
1384                if let AbstractLiteral::Matrix(_, index_domain) = elem {
1385                    res.push(index_domain);
1386                }
1387
1388                res
1389            });
1390
1391        assert_eq!(actual_index_domains, expected_index_domains);
1392    }
1393
1394    #[test]
1395    fn matrix_flatten() {
1396        let tensor: AbstractLiteral<Literal> = matrix![
1397            [
1398                // batch 1
1399                [1, 2, 3, 4],
1400                [5, 6, 7, 8],
1401                [9, 10, 11, 12]
1402            ],
1403            [
1404                // batch 2
1405                [13, 14, 15, 16],
1406                [17, 18, 19, 20],
1407                [21, 22, 23, 24]
1408            ]
1409        ];
1410
1411        let actual_elems: Vec<Literal> = flatten(&tensor).cloned().collect();
1412        let expected_elems = (1..25).map(Literal::from).collect::<Vec<_>>();
1413        assert_eq!(actual_elems, expected_elems);
1414    }
1415
1416    #[test]
1417    fn matrix_domain_1d() {
1418        let matrix = matrix_lit![10, 11, 12, 13; domain_int_ground!(1..4)];
1419        let dom = matrix.domain_of();
1420
1421        let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1422        assert_eq!(inner_dom, &domain_int_ground!(10..13));
1423        assert_eq!(idx_doms.len(), 1);
1424        assert_eq!(&idx_doms[0], &domain_int_ground!(1..4));
1425    }
1426
1427    #[test]
1428    fn matrix_domain_2d() {
1429        let matrix = matrix_lit![
1430            [1, 2, 3, 4],
1431            [5, 6, 7, 8];
1432            [
1433                domain_int_ground!(1..2),
1434                domain_int_ground!(1..4)
1435            ]
1436        ];
1437        let dom = matrix.domain_of();
1438
1439        let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1440        assert_eq!(inner_dom, &domain_int_ground!(1..8));
1441        assert_eq!(idx_doms.len(), 2);
1442        assert_eq!(&idx_doms[0], &domain_int_ground!(1..2));
1443        assert_eq!(&idx_doms[1], &domain_int_ground!(1..4));
1444    }
1445
1446    #[test]
1447    fn matrix_shape_3d() {
1448        let tensor: AbstractLiteral<Literal> = matrix![
1449            [
1450                [1, 2, 3, 4],
1451                [5, 6, 7, 8],
1452                [9, 10, 11, 12]
1453            ],
1454            [
1455                [13, 14, 15, 16],
1456                [17, 18, 19, 20],
1457                [21, 22, 23, 24]
1458            ];
1459            [
1460                domain_int_ground!(1..2),
1461                domain_int_ground!(1..3),
1462                domain_int_ground!(1..4)
1463            ]
1464        ];
1465        let shape = shape_of(&tensor).expect("shape_of to work on a 3D matrix");
1466
1467        assert_eq!(shape.size, 24);
1468        assert_eq!(shape.dims, vec![2, 3, 4]);
1469        assert_eq!(shape.strides, vec![12, 4, 1]);
1470        assert_eq!(
1471            shape.idx_doms,
1472            vec![
1473                domain_int_ground!(1..2),
1474                domain_int_ground!(1..3),
1475                domain_int_ground!(1..4)
1476            ]
1477        );
1478    }
1479
1480    #[test]
1481    fn matrix_partial_flatten() {
1482        let tensor: AbstractLiteral<Literal> = matrix![
1483            [
1484                // batch 1
1485                [1, 2, 3, 4],
1486                [5, 6, 7, 8],
1487                [9, 10, 11, 12]
1488            ],
1489            [
1490                // batch 2
1491                [13, 14, 15, 16],
1492                [17, 18, 19, 20],
1493                [21, 22, 23, 24]
1494            ]
1495        ];
1496        assert_eq!(partial_flatten(0, tensor.clone()), tensor);
1497
1498        let expected_flatten_1: AbstractLiteral<Literal> = matrix![
1499            [1, 2, 3, 4],
1500            [5, 6, 7, 8],
1501            [9, 10, 11, 12],
1502            [13, 14, 15, 16],
1503            [17, 18, 19, 20],
1504            [21, 22, 23, 24]
1505        ];
1506        assert_eq!(partial_flatten(1, tensor.clone()), expected_flatten_1);
1507
1508        let expected_flatten_2 =
1509            AbstractLiteral::matrix_implied_indices((1..25).map(Literal::from).collect());
1510        assert_eq!(partial_flatten(2, tensor), expected_flatten_2);
1511    }
1512}