1use funcmap::FuncMap;
2use itertools::Itertools;
3use serde::{Deserialize, Serialize};
4use std::fmt::{Debug, Display, Formatter};
5use std::hash::Hash;
6use ustr::Ustr;
7
8use super::{
9 Atom, Domain, DomainPtr, Expression, GroundDomain, Metadata, Moo, PartitionAttr, Range,
10 ReturnType, SetAttr, Typeable, domains::HasDomain, domains::Int, records::Field,
11};
12use crate::ast::domains::{MSetAttr, SequenceAttr};
13use crate::ast::pretty::pretty_vec;
14use crate::bug;
15use polyquine::Quine;
16use 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)]
27pub enum Literal {
29 Int(i32),
30 Bool(bool),
31 #[allow(clippy::enum_variant_names)]
33 AbstractLiteral(AbstractLiteral<Literal>),
34}
35
36impl HasDomain for Literal {
37 fn domain_of(&self) -> DomainPtr {
38 match self {
39 Literal::Int(i) => Domain::int(vec![Range::Single(*i)]),
40 Literal::Bool(_) => Domain::bool(),
41 Literal::AbstractLiteral(abstract_literal) => abstract_literal.domain_of(),
42 }
43 }
44}
45
46pub 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}
59impl AbstractLiteralValue for Expression {
60 type Dom = DomainPtr;
61}
62impl 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)]
68pub enum AbstractLiteral<T: AbstractLiteralValue> {
69 Set(Vec<T>),
70
71 MSet(Vec<T>),
72
73 Matrix(Vec<T>, T::Dom),
75
76 Tuple(Vec<T>),
78
79 Record(Vec<Field<T>>),
80
81 Sequence(Vec<T>),
82
83 Function(Vec<(T, T)>),
84
85 Variant(Moo<Field<T>>),
87
88 Partition(Vec<Vec<T>>),
90 Relation(Vec<Vec<T>>),
91}
92
93impl AbstractLiteral<Expression> {
95 pub fn domain_of(&self) -> Option<DomainPtr> {
96 match self {
97 AbstractLiteral::Set(items) => {
98 let item_domains: Vec<DomainPtr> = items
100 .iter()
101 .map(|x| x.domain_of())
102 .collect::<Option<Vec<DomainPtr>>>()?;
103
104 let mut item_domain_iter = item_domains.iter().cloned();
106 let first_item = item_domain_iter.next()?;
107 let item_domain = item_domains
108 .iter()
109 .try_fold(first_item, |x, y| x.union(y))
110 .expect("taking the union of all item domains of a set literal should succeed");
111
112 Some(Domain::set(SetAttr::<Int>::default(), item_domain))
113 }
114
115 AbstractLiteral::MSet(items) => {
116 let item_domains: Vec<DomainPtr> = items
118 .iter()
119 .map(|x| x.domain_of())
120 .collect::<Option<Vec<DomainPtr>>>()?;
121
122 let mut item_domain_iter = item_domains.iter().cloned();
124 let first_item = item_domain_iter.next()?;
125 let item_domain = item_domains
126 .iter()
127 .try_fold(first_item, |x, y| x.union(y))
128 .expect("taking the union of all item domains of a set literal should succeed");
129
130 Some(Domain::mset(MSetAttr::<Int>::default(), item_domain))
131 }
132
133 AbstractLiteral::Sequence(elems) => {
134 let item_domains: Vec<DomainPtr> = elems
135 .iter()
136 .map(|x| x.domain_of())
137 .collect::<Option<Vec<DomainPtr>>>()?;
138
139 let mut item_domain_iter = item_domains.iter().cloned();
142 let first_item = item_domain_iter.next()?;
143 let item_domain = item_domains
144 .iter()
145 .try_fold(first_item, |x, y| x.union(y))
146 .expect("taking the union of all item domains of a set literal should succeed");
147
148 Some(Domain::sequence(
149 SequenceAttr::<Int>::default(),
150 item_domain,
151 ))
152 }
153
154 AbstractLiteral::Partition(items) => {
155 let item_domains: Vec<DomainPtr> = items
159 .iter()
160 .flatten()
161 .map(|x| x.domain_of())
162 .collect::<Option<Vec<DomainPtr>>>()?;
163
164 let mut item_domain_iter = item_domains.iter().cloned();
166 let first_item = item_domain_iter.next()?;
167 let item_domain = item_domains
168 .iter()
169 .try_fold(first_item, |x, y| x.union(y))
170 .expect("taking the union of all item domains of a partition literal should succeed");
171
172 Some(Domain::partition(
173 PartitionAttr::<Int>::default(),
174 item_domain,
175 ))
176 }
177
178 AbstractLiteral::Matrix(items, _) => {
179 let item_domains = items
181 .iter()
182 .map(|x| x.domain_of())
183 .collect::<Option<Vec<DomainPtr>>>()?;
184
185 let mut item_domain_iter = item_domains.iter().cloned();
187
188 let first_item = item_domain_iter.next()?;
189
190 let item_domain = item_domains
191 .iter()
192 .try_fold(first_item, |x, y| x.union(y))
193 .expect(
194 "taking the union of all item domains of a matrix literal should succeed",
195 );
196
197 let mut new_index_domain = vec![];
198
199 let mut e = Expression::AbstractLiteral(Metadata::new(), self.clone());
201 while let Expression::AbstractLiteral(_, AbstractLiteral::Matrix(elems, idx)) = e {
202 assert!(
203 idx.as_matrix().is_none(),
204 "n-dimensional matrix literals should be represented as a matrix inside a matrix, got {idx}"
205 );
206 new_index_domain.push(idx);
207 e = elems[0].clone();
208 }
209 Some(Domain::matrix(item_domain, new_index_domain))
210 }
211 AbstractLiteral::Tuple(_) => None,
212 AbstractLiteral::Record(_) => None,
213 AbstractLiteral::Function(_) => None,
214 AbstractLiteral::Variant(_) => None,
215 AbstractLiteral::Relation(_) => None,
216 }
217 }
218}
219
220impl HasDomain for AbstractLiteral<Literal> {
221 fn domain_of(&self) -> DomainPtr {
222 Domain::from_literal_vec(&[Literal::AbstractLiteral(self.clone())])
223 .expect("abstract literals should be correctly typed")
224 }
225}
226
227impl Typeable for AbstractLiteral<Expression> {
228 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 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 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 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 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 AbstractLiteral::Matrix(items, _) if items.is_empty() => {
296 ReturnType::Matrix(Box::new(ReturnType::Unknown))
297 }
298 AbstractLiteral::Matrix(items, _) => {
299 let item_type = items[0].return_type();
300
301 let item_types: Vec<ReturnType> = items.iter().map(|x| x.return_type()).collect();
303
304 assert!(
305 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 ReturnType::Matrix(Box::new(item_type))
315 }
316 AbstractLiteral::Tuple(items) => {
317 let mut item_types = vec![];
318 for item in items {
319 item_types.push(item.return_type());
320 }
321 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 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 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 }
385}
386
387impl<T> AbstractLiteral<T>
388where
389 T: AbstractLiteralValue,
390{
391 pub fn matrix_implied_indices(elems: Vec<T>) -> Self {
395 AbstractLiteral::Matrix(elems, GroundDomain::Int(vec![Range::UnboundedR(1)]).into())
396 }
397
398 pub fn unwrap_list(&self) -> Option<&Vec<T>> {
403 let AbstractLiteral::Matrix(elems, domain) = self else {
404 return None;
405 };
406
407 let domain: DomainPtr = domain.clone().into();
408 let Some(GroundDomain::Int(ranges)) = domain.as_ground() else {
409 return None;
410 };
411
412 let [Range::UnboundedR(1)] = ranges[..] else {
413 return None;
414 };
415
416 Some(elems)
417 }
418}
419
420impl<T> Display for AbstractLiteral<T>
421where
422 T: AbstractLiteralValue,
423{
424 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
425 match self {
426 AbstractLiteral::Set(elems) => {
427 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
428 write!(f, "{{{elems_str}}}")
429 }
430 AbstractLiteral::MSet(elems) => {
431 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
432 write!(f, "mset({elems_str})")
433 }
434 AbstractLiteral::Matrix(elems, index_domain) => {
435 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
436 write!(f, "[{elems_str};{index_domain}]")
437 }
438 AbstractLiteral::Tuple(elems) => {
439 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
440 write!(f, "({elems_str})")
441 }
442 AbstractLiteral::Sequence(elems) => {
443 let elems_str: String = elems.iter().map(|x| format!("{x}")).join(",");
444 write!(f, "sequence({elems_str})")
445 }
446 AbstractLiteral::Partition(parts) => {
447 let elems_str: String = parts
448 .iter()
449 .map(|inner| {
450 let elems_str = inner.iter().map(|x| format!("{x}")).join(",");
451 format!("{{{}}}", elems_str)
452 })
453 .join(", ");
454
455 write!(f, "partition({elems_str})")
456 }
457 AbstractLiteral::Record(entries) => {
458 let entries_str: String = entries
459 .iter()
460 .map(|entry| format!("{} = {}", entry.name, entry.value))
461 .join(",");
462 write!(f, "record {{{entries_str}}}")
463 }
464 AbstractLiteral::Function(entries) => {
465 let entries_str: String = entries
466 .iter()
467 .map(|entry| format!("{} --> {}", entry.0, entry.1))
468 .join(",");
469 write!(f, "function({entries_str})")
470 }
471 AbstractLiteral::Variant(entry) => {
472 write!(f, "variant{{{} = {}}}", entry.name, entry.value)
473 }
474 AbstractLiteral::Relation(elems) => {
475 let elems_str: String = elems
476 .iter()
477 .map(|x| format!("({})", x.iter().map(|x| format!("{x}")).join(",")))
478 .join(",");
479 write!(f, "relation({elems_str})")
480 }
481 }
482 }
483}
484
485impl<T> Uniplate for AbstractLiteral<T>
486where
487 T: AbstractLiteralValue + Biplate<AbstractLiteral<T>>,
488{
489 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
490 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 AbstractLiteral::Matrix(elems, index_domain) => {
501 let index_domain = index_domain.clone();
502 let (f1_tree, f1_ctx) = <_ as Biplate<AbstractLiteral<T>>>::biplate(elems);
503 (
504 f1_tree,
505 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 }
581}
582
583impl<U, To> Biplate<To> for AbstractLiteral<U>
584where
585 To: Uniplate,
586 U: AbstractLiteralValue + Biplate<AbstractLiteral<U>> + Biplate<To>,
587 Field<U>: Biplate<AbstractLiteral<U>> + Biplate<To>,
588{
589 fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
590 if std::any::TypeId::of::<To>() == std::any::TypeId::of::<AbstractLiteral<U>>() {
591 unsafe {
594 let self_to = std::mem::transmute::<&AbstractLiteral<U>, &To>(self).clone();
596 let tree = Tree::One(self_to);
597 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 (tree, ctx)
606 }
607 } else {
608 match self {
610 AbstractLiteral::Set(vec) => {
611 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
612 (f1_tree, Box::new(move |x| AbstractLiteral::Set(f1_ctx(x))))
613 }
614 AbstractLiteral::MSet(vec) => {
615 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
616 (f1_tree, Box::new(move |x| AbstractLiteral::MSet(f1_ctx(x))))
617 }
618 AbstractLiteral::Matrix(elems, index_domain) => {
619 let index_domain = index_domain.clone();
620 let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(elems);
621 (
622 f1_tree,
623 Box::new(move |x| AbstractLiteral::Matrix(f1_ctx(x), index_domain.clone())),
624 )
625 }
626 AbstractLiteral::Sequence(vec) => {
627 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(vec);
628 (
629 f1_tree,
630 Box::new(move |x| AbstractLiteral::Sequence(f1_ctx(x))),
631 )
632 }
633 AbstractLiteral::Tuple(elems) => {
634 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
635 (
636 f1_tree,
637 Box::new(move |x| AbstractLiteral::Tuple(f1_ctx(x))),
638 )
639 }
640 AbstractLiteral::Record(entries) => {
641 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
642 (
643 f1_tree,
644 Box::new(move |x| AbstractLiteral::Record(f1_ctx(x))),
645 )
646 }
647 AbstractLiteral::Function(entries) => {
648 let entry_count = entries.len();
649 let flattened: Vec<U> = entries
650 .iter()
651 .flat_map(|(lhs, rhs)| [lhs.clone(), rhs.clone()])
652 .collect();
653
654 let (f1_tree, f1_ctx) = <Vec<U> as Biplate<To>>::biplate(&flattened);
655 (
656 f1_tree,
657 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 AbstractLiteral::Variant(entries) => {
676 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(entries);
677 (
678 f1_tree,
679 Box::new(move |x| AbstractLiteral::Variant(f1_ctx(x))),
680 )
681 }
682 AbstractLiteral::Relation(elems) => {
683 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
684 (
685 f1_tree,
686 Box::new(move |x| AbstractLiteral::Relation(f1_ctx(x))),
687 )
688 }
689 AbstractLiteral::Partition(elems) => {
690 let (f1_tree, f1_ctx) = <_ as Biplate<To>>::biplate(elems);
691 (
692 f1_tree,
693 Box::new(move |x| AbstractLiteral::Partition(f1_ctx(x))),
694 )
695 }
696 }
697 }
698 }
699}
700
701impl TryFrom<Literal> for i32 {
702 type Error = &'static str;
703
704 fn try_from(value: Literal) -> Result<Self, Self::Error> {
705 match value {
706 Literal::Int(i) => Ok(i),
707 _ => Err("Cannot convert non-i32 literal to i32"),
708 }
709 }
710}
711
712impl 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
720impl TryFrom<&Box<Literal>> for i32 {
721 type Error = &'static str;
722
723 fn try_from(value: &Box<Literal>) -> Result<Self, Self::Error> {
724 TryFrom::<&Literal>::try_from(value.as_ref())
725 }
726}
727
728impl 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
736impl TryFrom<&Literal> for i32 {
737 type Error = &'static str;
738
739 fn try_from(value: &Literal) -> Result<Self, Self::Error> {
740 match value {
741 Literal::Int(i) => Ok(*i),
742 _ => Err("Cannot convert non-i32 literal to i32"),
743 }
744 }
745}
746
747impl TryFrom<Literal> for bool {
748 type Error = &'static str;
749
750 fn try_from(value: Literal) -> Result<Self, Self::Error> {
751 match value {
752 Literal::Bool(b) => Ok(b),
753 _ => Err("Cannot convert non-bool literal to bool"),
754 }
755 }
756}
757
758impl TryFrom<&Literal> for bool {
759 type Error = &'static str;
760
761 fn try_from(value: &Literal) -> Result<Self, Self::Error> {
762 match value {
763 Literal::Bool(b) => Ok(*b),
764 _ => Err("Cannot convert non-bool literal to bool"),
765 }
766 }
767}
768
769impl From<i32> for Literal {
770 fn from(i: i32) -> Self {
771 Literal::Int(i)
772 }
773}
774
775impl From<bool> for Literal {
776 fn from(b: bool) -> Self {
777 Literal::Bool(b)
778 }
779}
780
781impl From<Literal> for Ustr {
782 fn from(value: Literal) -> Self {
783 Ustr::from(&format!("{value}"))
785 }
786}
787
788impl From<AbstractLiteral<Literal>> for Literal {
789 fn from(literal: AbstractLiteral<Literal>) -> Self {
790 Literal::AbstractLiteral(literal)
791 }
792}
793
794impl AbstractLiteral<Expression> {
795 pub fn into_literals(self) -> Option<AbstractLiteral<Literal>> {
798 match self {
799 AbstractLiteral::Set(elements) => {
800 let literals = elements
801 .into_iter()
802 .map(|expr| match expr {
803 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
804 Expression::AbstractLiteral(_, abslit) => {
805 Some(Literal::AbstractLiteral(abslit.into_literals()?))
806 }
807 _ => None,
808 })
809 .collect::<Option<Vec<_>>>()?;
810 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 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 AbstractLiteral::Matrix(items, domain) => {
848 let mut literals = vec![];
849 for item in items {
850 let literal = match item {
851 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
852 Expression::AbstractLiteral(_, abslit) => {
853 Some(Literal::AbstractLiteral(abslit.into_literals()?))
854 }
855 _ => None,
856 }?;
857 literals.push(literal);
858 }
859
860 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 AbstractLiteral::Tuple(items) => {
876 let mut literals = vec![];
877 for item in items {
878 let literal = match item {
879 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
880 Expression::AbstractLiteral(_, abslit) => {
881 Some(Literal::AbstractLiteral(abslit.into_literals()?))
882 }
883 _ => None,
884 }?;
885 literals.push(literal);
886 }
887
888 Some(AbstractLiteral::Tuple(literals))
889 }
890 AbstractLiteral::Record(entries) => {
891 let mut literals = vec![];
892 for entry in entries {
893 let literal = match entry.value {
894 Expression::Atomic(_, Atom::Literal(lit)) => Some(lit),
895 Expression::AbstractLiteral(_, abslit) => {
896 Some(Literal::AbstractLiteral(abslit.into_literals()?))
897 }
898 _ => None,
899 }?;
900
901 literals.push((entry.name, literal));
902 }
903 Some(AbstractLiteral::Record(
904 literals
905 .into_iter()
906 .map(|(name, literal)| Field {
907 name,
908 value: literal,
909 })
910 .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 }
930}
931
932impl Display for Literal {
934 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
935 match &self {
936 Literal::Int(i) => write!(f, "{i}"),
937 Literal::Bool(b) => write!(f, "{b}"),
938 Literal::AbstractLiteral(l) => write!(f, "{l}"),
939 }
940 }
941}
942
943#[cfg(test)]
944mod 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 fn matrix_uniplate_universe() {
953 let my_matrix: AbstractLiteral<Literal> = into_matrix![
955 vec![Literal::AbstractLiteral(matrix![Literal::Bool(true);Moo::new(GroundDomain::Bool)]); 5];
956 Moo::new(GroundDomain::Bool)
957 ];
958
959 let expected_index_domains = vec![Moo::new(GroundDomain::Bool); 6];
960 let actual_index_domains: Vec<Moo<GroundDomain>> =
961 my_matrix.cata(&move |elem, children| {
962 let mut res = vec![];
963 res.extend(children.into_iter().flatten());
964 if let AbstractLiteral::Matrix(_, index_domain) = elem {
965 res.push(index_domain);
966 }
967
968 res
969 });
970
971 assert_eq!(actual_index_domains, expected_index_domains);
972 }
973
974 #[test]
975 fn matrix_flatten() {
976 let tensor: AbstractLiteral<Literal> = matrix![
977 [
978 [1, 2, 3, 4],
980 [5, 6, 7, 8],
981 [9, 10, 11, 12]
982 ],
983 [
984 [13, 14, 15, 16],
986 [17, 18, 19, 20],
987 [21, 22, 23, 24]
988 ]
989 ];
990
991 let actual_elems: Vec<Literal> = flatten(&tensor).cloned().collect();
992 let expected_elems = (1..25).map(Literal::from).collect::<Vec<_>>();
993 assert_eq!(actual_elems, expected_elems);
994 }
995
996 #[test]
997 fn matrix_domain_1d() {
998 let matrix = matrix_lit![10, 11, 12, 13; domain_int_ground!(1..4)];
999 let dom = matrix.domain_of();
1000
1001 let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1002 assert_eq!(inner_dom, &domain_int_ground!(10..13));
1003 assert_eq!(idx_doms.len(), 1);
1004 assert_eq!(&idx_doms[0], &domain_int_ground!(1..4));
1005 }
1006
1007 #[test]
1008 fn matrix_domain_2d() {
1009 let matrix = matrix_lit![
1010 [1, 2, 3, 4],
1011 [5, 6, 7, 8];
1012 [
1013 domain_int_ground!(1..2),
1014 domain_int_ground!(1..4)
1015 ]
1016 ];
1017 let dom = matrix.domain_of();
1018
1019 let (inner_dom, idx_doms) = dom.as_matrix_ground().expect("must be ground matrix");
1020 assert_eq!(inner_dom, &domain_int_ground!(1..8));
1021 assert_eq!(idx_doms.len(), 2);
1022 assert_eq!(&idx_doms[0], &domain_int_ground!(1..2));
1023 assert_eq!(&idx_doms[1], &domain_int_ground!(1..4));
1024 }
1025
1026 #[test]
1027 fn matrix_shape_3d() {
1028 let tensor: AbstractLiteral<Literal> = matrix![
1029 [
1030 [1, 2, 3, 4],
1031 [5, 6, 7, 8],
1032 [9, 10, 11, 12]
1033 ],
1034 [
1035 [13, 14, 15, 16],
1036 [17, 18, 19, 20],
1037 [21, 22, 23, 24]
1038 ];
1039 [
1040 domain_int_ground!(1..2),
1041 domain_int_ground!(1..3),
1042 domain_int_ground!(1..4)
1043 ]
1044 ];
1045 let shape = shape_of(&tensor).expect("shape_of to work on a 3D matrix");
1046
1047 assert_eq!(shape.size, 24);
1048 assert_eq!(shape.dims, vec![2, 3, 4]);
1049 assert_eq!(shape.strides, vec![12, 4, 1]);
1050 assert_eq!(
1051 shape.idx_doms,
1052 vec![
1053 domain_int_ground!(1..2),
1054 domain_int_ground!(1..3),
1055 domain_int_ground!(1..4)
1056 ]
1057 );
1058 }
1059
1060 #[test]
1061 fn matrix_partial_flatten() {
1062 let tensor: AbstractLiteral<Literal> = matrix![
1063 [
1064 [1, 2, 3, 4],
1066 [5, 6, 7, 8],
1067 [9, 10, 11, 12]
1068 ],
1069 [
1070 [13, 14, 15, 16],
1072 [17, 18, 19, 20],
1073 [21, 22, 23, 24]
1074 ]
1075 ];
1076 assert_eq!(partial_flatten(0, tensor.clone()), tensor);
1077
1078 let expected_flatten_1: AbstractLiteral<Literal> = matrix![
1079 [1, 2, 3, 4],
1080 [5, 6, 7, 8],
1081 [9, 10, 11, 12],
1082 [13, 14, 15, 16],
1083 [17, 18, 19, 20],
1084 [21, 22, 23, 24]
1085 ];
1086 assert_eq!(partial_flatten(1, tensor.clone()), expected_flatten_1);
1087
1088 let expected_flatten_2 =
1089 AbstractLiteral::matrix_implied_indices((1..25).map(Literal::from).collect());
1090 assert_eq!(partial_flatten(2, tensor), expected_flatten_2);
1091 }
1092}