1use std::{borrow::Cow, cmp, fmt, iter, ops};
4
5use crate::{arith::Num, PrimitiveType, Type};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub struct LengthVar {
24 index: usize,
25 is_free: bool,
26}
27
28impl fmt::Display for LengthVar {
29 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30 if self.is_free {
31 formatter.write_str("_")
32 } else {
33 formatter.write_str(Self::param_str(self.index).as_ref())
34 }
35 }
36}
37
38impl LengthVar {
39 pub(crate) fn param_str(index: usize) -> Cow<'static, str> {
40 const PARAM_NAMES: &str = "NMLKJI";
41 PARAM_NAMES.get(index..=index).map_or_else(
42 || Cow::from(format!("N{}", index - PARAM_NAMES.len())),
43 Cow::from,
44 )
45 }
46
47 pub const fn param(index: usize) -> Self {
50 Self {
51 index,
52 is_free: false,
53 }
54 }
55
56 pub fn index(self) -> usize {
58 self.index
59 }
60
61 pub fn is_free(self) -> bool {
63 self.is_free
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq)]
69#[non_exhaustive]
70pub enum UnknownLen {
71 Dynamic,
73 Var(LengthVar),
75}
76
77impl fmt::Display for UnknownLen {
78 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
79 match self {
80 Self::Dynamic => formatter.write_str("*"),
81 Self::Var(var) => fmt::Display::fmt(var, formatter),
82 }
83 }
84}
85
86impl ops::Add<usize> for UnknownLen {
87 type Output = TupleLen;
88
89 fn add(self, rhs: usize) -> Self::Output {
90 TupleLen {
91 var: Some(self),
92 exact: rhs,
93 }
94 }
95}
96
97impl UnknownLen {
98 pub const fn param(index: usize) -> Self {
100 Self::Var(LengthVar::param(index))
101 }
102
103 pub(crate) const fn free_var(index: usize) -> Self {
104 Self::Var(LengthVar {
105 index,
106 is_free: true,
107 })
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq)]
135pub struct TupleLen {
136 var: Option<UnknownLen>,
137 exact: usize,
138}
139
140impl fmt::Display for TupleLen {
141 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
142 match (&self.var, self.exact) {
143 (Some(var), 0) => fmt::Display::fmt(var, formatter),
144 (Some(var), exact) => write!(formatter, "{} + {}", var, exact),
145 (None, exact) => fmt::Display::fmt(&exact, formatter),
146 }
147 }
148}
149
150impl ops::Add<usize> for TupleLen {
151 type Output = Self;
152
153 fn add(self, rhs: usize) -> Self::Output {
154 Self {
155 var: self.var,
156 exact: self.exact + rhs,
157 }
158 }
159}
160
161impl From<UnknownLen> for TupleLen {
162 fn from(var: UnknownLen) -> Self {
163 Self {
164 var: Some(var),
165 exact: 0,
166 }
167 }
168}
169
170impl From<usize> for TupleLen {
171 fn from(exact: usize) -> Self {
172 Self { var: None, exact }
173 }
174}
175
176impl TupleLen {
177 pub(crate) const ZERO: Self = Self {
179 var: None,
180 exact: 0,
181 };
182
183 fn is_concrete(&self) -> bool {
184 !matches!(&self.var, Some(UnknownLen::Var(var)) if var.is_free())
185 }
186
187 pub fn components(&self) -> (Option<UnknownLen>, usize) {
189 (self.var, self.exact)
190 }
191
192 pub fn components_mut(&mut self) -> (Option<&mut UnknownLen>, &mut usize) {
194 (self.var.as_mut(), &mut self.exact)
195 }
196}
197
198#[derive(Debug, Clone, Copy, PartialEq)]
200#[non_exhaustive]
201pub enum TupleIndex {
202 Start(usize),
204 Middle,
206 End(usize),
208}
209
210#[derive(Debug, Clone)]
282pub struct Tuple<Prim: PrimitiveType = Num> {
283 start: Vec<Type<Prim>>,
284 middle: Option<Slice<Prim>>,
285 end: Vec<Type<Prim>>,
286}
287
288impl<Prim: PrimitiveType> PartialEq for Tuple<Prim> {
289 fn eq(&self, other: &Self) -> bool {
290 let this_len = self.len();
291 if this_len != other.len() {
292 false
293 } else if let (None, len) = this_len.components() {
294 self.iter(len).zip(other.iter(len)).all(|(x, y)| x == y)
295 } else {
296 self.equal_elements_dyn(other).all(|(x, y)| x == y)
297 }
298 }
299}
300
301impl<Prim: PrimitiveType> fmt::Display for Tuple<Prim> {
302 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
303 if let Some(slice) = self.as_slice() {
304 if let (Some(_), _) = slice.length.components() {
305 return fmt::Display::fmt(slice, formatter);
306 }
307 }
308 self.format_as_tuple(formatter)
309 }
310}
311
312impl<Prim: PrimitiveType> Tuple<Prim> {
313 pub(crate) fn from_parts(
314 start: Vec<Type<Prim>>,
315 middle: Option<Slice<Prim>>,
316 end: Vec<Type<Prim>>,
317 ) -> Self {
318 Self { start, middle, end }
319 }
320
321 pub fn new(start: Vec<Type<Prim>>, middle: Slice<Prim>, end: Vec<Type<Prim>>) -> Self {
323 Self::from_parts(start, Some(middle), end)
324 }
325
326 pub(crate) fn empty() -> Self {
327 Self {
328 start: Vec::new(),
329 middle: None,
330 end: Vec::new(),
331 }
332 }
333
334 pub(crate) fn is_concrete(&self) -> bool {
335 self.start.iter().chain(&self.end).all(Type::is_concrete)
336 && self.middle.as_ref().map_or(true, Slice::is_concrete)
337 }
338
339 pub fn as_slice(&self) -> Option<&Slice<Prim>> {
341 self.middle
342 .as_ref()
343 .filter(|_| self.start.is_empty() && self.end.is_empty())
344 }
345
346 pub(crate) fn format_as_tuple(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
347 formatter.write_str("(")?;
348
349 for (i, element) in self.start.iter().enumerate() {
350 fmt::Display::fmt(element, formatter)?;
351 if i + 1 < self.start.len() || self.middle.is_some() {
352 formatter.write_str(", ")?;
353 }
354 }
355
356 if let Some(middle) = &self.middle {
357 if let (None, len) = middle.length.components() {
358 for i in 0..len {
360 fmt::Display::fmt(&middle.element, formatter)?;
361 if i + 1 < len {
362 formatter.write_str(", ")?;
363 }
364 }
365 } else {
366 formatter.write_str("...")?;
367 fmt::Display::fmt(middle, formatter)?;
368 }
369 }
370 if !self.end.is_empty() {
371 formatter.write_str(", ")?;
372 }
373
374 for (i, element) in self.end.iter().enumerate() {
375 fmt::Display::fmt(element, formatter)?;
376 if i + 1 < self.end.len() {
377 formatter.write_str(", ")?;
378 }
379 }
380
381 formatter.write_str(")")
382 }
383
384 fn resolved_middle_len(&self) -> TupleLen {
385 self.middle
386 .as_ref()
387 .map_or(TupleLen::ZERO, |middle| middle.length)
388 }
389
390 #[allow(clippy::type_complexity)]
392 pub fn parts(&self) -> (&[Type<Prim>], Option<&Slice<Prim>>, &[Type<Prim>]) {
393 (&self.start, self.middle.as_ref(), &self.end)
394 }
395
396 #[allow(clippy::type_complexity)]
398 pub fn parts_mut(
399 &mut self,
400 ) -> (
401 &mut [Type<Prim>],
402 Option<&mut Slice<Prim>>,
403 &mut [Type<Prim>],
404 ) {
405 (&mut self.start, self.middle.as_mut(), &mut self.end)
406 }
407
408 pub fn len(&self) -> TupleLen {
425 let increment = self.start.len() + self.end.len();
426 self.resolved_middle_len() + increment
427 }
428
429 pub fn is_empty(&self) -> bool {
431 self.start.is_empty() && self.end.is_empty() && self.resolved_middle_len() == TupleLen::ZERO
432 }
433
434 pub(crate) fn push(&mut self, element: Type<Prim>) {
435 if self.middle.is_some() {
436 self.end.push(element);
437 } else {
438 self.start.push(element);
439 }
440 }
441
442 pub(crate) fn set_middle(&mut self, element: Type<Prim>, len: TupleLen) {
443 self.middle = Some(Slice::new(element, len));
444 }
445
446 pub(crate) fn iter(&self, total_len: usize) -> impl Iterator<Item = &Type<Prim>> + '_ {
448 let middle_len = total_len - self.start.len() - self.end.len();
449 let middle_element = self.middle.as_ref().map(Slice::element);
450
451 self.start
452 .iter()
453 .chain(iter::repeat_with(move || middle_element.unwrap()).take(middle_len))
454 .chain(&self.end)
455 }
456
457 pub(crate) fn get_element(
459 &self,
460 index: usize,
461 middle_len: TupleLen,
462 ) -> Result<&Type<Prim>, IndexError> {
463 if let Some(element) = self.start.get(index) {
464 Ok(element)
465 } else {
466 self.middle
467 .as_ref()
468 .map_or(Err(IndexError::OutOfBounds), |middle| {
469 let middle_index = index - self.start.len();
470 if middle_index < middle_len.exact {
471 Ok(middle.element.as_ref())
473 } else if middle_len.var.is_none() {
474 let end_index = middle_index - middle_len.exact;
476 self.end.get(end_index).ok_or(IndexError::OutOfBounds)
477 } else {
478 Err(IndexError::NoInfo)
479 }
480 })
481 }
482 }
483
484 pub(crate) fn equal_elements_dyn<'a>(
488 &'a self,
489 other: &'a Self,
490 ) -> impl Iterator<Item = (&'a Type<Prim>, &'a Type<Prim>)> + 'a {
491 let middle_elem = self.middle.as_ref().unwrap().element.as_ref();
492 let other_middle_elem = other.middle.as_ref().unwrap().element.as_ref();
493 let iter = iter::once((middle_elem, other_middle_elem));
494
495 let borders_iter = self
496 .start
497 .iter()
498 .zip(&other.start)
499 .chain(self.end.iter().rev().zip(other.end.iter().rev()));
500 let iter = iter.chain(borders_iter);
501
502 let skip_at_start = cmp::min(self.start.len(), other.start.len());
503 let skip_at_end = cmp::min(self.end.len(), other.end.len());
504 let middle = self
505 .start
506 .iter()
507 .skip(skip_at_start)
508 .chain(self.end.iter().rev().skip(skip_at_end));
509 let iter = iter.chain(middle.map(move |elem| (middle_elem, elem)));
510
511 let other_middle = other
512 .start
513 .iter()
514 .skip(skip_at_start)
515 .chain(other.end.iter().rev().skip(skip_at_end));
516 iter.chain(other_middle.map(move |elem| (middle_elem, elem)))
517 }
518
519 pub fn element_types(&self) -> impl Iterator<Item = (TupleIndex, &Type<Prim>)> + '_ {
539 let middle_element = self
540 .middle
541 .as_ref()
542 .map(|slice| (TupleIndex::Middle, slice.element.as_ref()));
543 let start = self
544 .start
545 .iter()
546 .enumerate()
547 .map(|(i, elem)| (TupleIndex::Start(i), elem));
548 let end = self
549 .end
550 .iter()
551 .enumerate()
552 .map(|(i, elem)| (TupleIndex::End(i), elem));
553 start.chain(middle_element).chain(end)
554 }
555
556 pub(crate) fn element_types_mut(&mut self) -> impl Iterator<Item = &mut Type<Prim>> + '_ {
557 let middle_element = self.middle.as_mut().map(|slice| slice.element.as_mut());
558 self.start
559 .iter_mut()
560 .chain(middle_element)
561 .chain(&mut self.end)
562 }
563}
564
565impl<Prim: PrimitiveType> From<Vec<Type<Prim>>> for Tuple<Prim> {
566 fn from(elements: Vec<Type<Prim>>) -> Self {
567 Self {
568 start: elements,
569 middle: None,
570 end: Vec::new(),
571 }
572 }
573}
574
575#[derive(Debug)]
577pub(crate) enum IndexError {
578 OutOfBounds,
580 NoInfo,
582}
583
584#[derive(Debug, Clone, PartialEq)]
623pub struct Slice<Prim: PrimitiveType = Num> {
624 element: Box<Type<Prim>>,
625 length: TupleLen,
626}
627
628impl<Prim: PrimitiveType> fmt::Display for Slice<Prim> {
629 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
630 if self.length == TupleLen::from(UnknownLen::Dynamic) {
631 write!(formatter, "[{}]", self.element)
632 } else {
633 write!(formatter, "[{}; {}]", self.element, self.length)
634 }
635 }
636}
637
638impl<Prim: PrimitiveType> Slice<Prim> {
639 pub fn new(element: Type<Prim>, length: impl Into<TupleLen>) -> Self {
641 Self {
642 element: Box::new(element),
643 length: length.into(),
644 }
645 }
646
647 pub fn element(&self) -> &Type<Prim> {
649 self.element.as_ref()
650 }
651
652 pub fn len(&self) -> TupleLen {
654 self.length
655 }
656
657 pub(crate) fn len_mut(&mut self) -> &mut TupleLen {
658 &mut self.length
659 }
660
661 pub fn is_empty(&self) -> bool {
663 self.length == TupleLen::ZERO
664 }
665
666 fn is_concrete(&self) -> bool {
667 self.length.is_concrete() && self.element.is_concrete()
668 }
669}
670
671impl<Prim: PrimitiveType> From<Slice<Prim>> for Tuple<Prim> {
672 fn from(slice: Slice<Prim>) -> Self {
673 Self {
674 start: Vec::new(),
675 middle: Some(slice),
676 end: Vec::new(),
677 }
678 }
679}
680
681#[cfg(test)]
682mod tests {
683 use super::*;
684
685 use assert_matches::assert_matches;
686
687 #[test]
688 fn tuple_length_display() {
689 let len = TupleLen::from(3);
690 assert_eq!(len.to_string(), "3");
691 let len = UnknownLen::param(0) + 2;
692 assert_eq!(len.to_string(), "N + 2");
693 }
694
695 #[test]
696 fn slice_display() {
697 let slice = Slice::new(Type::NUM, UnknownLen::param(0));
698 assert_eq!(slice.to_string(), "[Num; N]");
699 let slice = Slice::new(Type::NUM, UnknownLen::free_var(0));
700 assert_eq!(slice.to_string(), "[Num; _]");
701 let slice = Slice::new(Type::NUM, TupleLen::from(3));
702 assert_eq!(slice.to_string(), "[Num; 3]");
703 }
704
705 #[test]
706 fn tuple_display() {
707 let tuple = Tuple::from(vec![Type::NUM, Type::BOOL]);
709 assert_eq!(tuple.to_string(), "(Num, Bool)");
710 let tuple = Tuple::from(Slice::new(Type::NUM, UnknownLen::param(0)));
711 assert_eq!(tuple.to_string(), "[Num; N]");
712 let tuple = Tuple::from(Slice::new(Type::NUM, TupleLen::from(3)));
713 assert_eq!(tuple.to_string(), "(Num, Num, Num)");
714
715 let tuple = Tuple {
716 start: vec![Type::NUM, Type::BOOL],
717 middle: Some(Slice::new(Type::NUM, UnknownLen::param(0))),
718 end: vec![],
719 };
720 assert_eq!(tuple.to_string(), "(Num, Bool, ...[Num; N])");
721
722 let tuple = Tuple {
723 start: vec![Type::NUM, Type::BOOL],
724 middle: Some(Slice::new(Type::NUM, TupleLen::from(2))),
725 end: vec![],
726 };
727 assert_eq!(tuple.to_string(), "(Num, Bool, Num, Num)");
728
729 let tuple = Tuple {
730 start: vec![Type::NUM, Type::BOOL],
731 middle: Some(Slice::new(Type::NUM, UnknownLen::param(0))),
732 end: vec![Type::param(0)],
733 };
734 assert_eq!(tuple.to_string(), "(Num, Bool, ...[Num; N], 'T)");
735 }
736
737 #[test]
738 fn equal_elements_static_two_simple_tuples() {
739 let tuple = Tuple::from(vec![Type::NUM, Type::BOOL, Type::free_var(0)]);
740 let other_tuple = <Tuple>::from(vec![Type::free_var(1), Type::BOOL, Type::free_var(0)]);
741 let equal_elements: Vec<_> = tuple.iter(3).zip(other_tuple.iter(3)).collect();
742
743 assert_eq!(
744 equal_elements,
745 vec![
746 (&Type::NUM, &Type::free_var(1)),
747 (&Type::BOOL, &Type::BOOL),
748 (&Type::free_var(0), &Type::free_var(0)),
749 ]
750 );
751 }
752
753 #[test]
754 fn equal_elements_static_simple_tuple_and_slice() {
755 let tuple = Tuple::from(vec![Type::NUM, Type::BOOL, Type::free_var(0)]);
756 let slice = <Tuple>::from(Slice::new(Type::free_var(1), UnknownLen::free_var(0)));
757 let equal_elements: Vec<_> = tuple.iter(3).zip(slice.iter(3)).collect();
758
759 assert_eq!(
760 equal_elements,
761 vec![
762 (&Type::NUM, &Type::free_var(1)),
763 (&Type::BOOL, &Type::free_var(1)),
764 (&Type::free_var(0), &Type::free_var(1)),
765 ]
766 );
767 }
768
769 #[test]
770 fn equal_elements_static_slice_and_complex_tuple() {
771 let slice = <Tuple>::from(Slice::new(Type::free_var(1), UnknownLen::free_var(0)));
772 let tuple = Tuple {
773 start: vec![Type::NUM],
774 middle: Some(Slice::new(Type::free_var(0), UnknownLen::free_var(1))),
775 end: vec![Type::BOOL, Type::free_var(2)],
776 };
777
778 let mut expected_pairs = vec![
779 (Type::free_var(1), Type::NUM),
780 (Type::free_var(1), Type::BOOL),
781 (Type::free_var(1), Type::free_var(2)),
782 ];
783 let equal_elements: Vec<_> = slice
784 .iter(3)
785 .zip(tuple.iter(3))
786 .map(|(x, y)| (x.clone(), y.clone()))
787 .collect();
788 assert_eq!(equal_elements, expected_pairs);
789
790 let equal_elements: Vec<_> = slice
791 .iter(4)
792 .zip(tuple.iter(4))
793 .map(|(x, y)| (x.clone(), y.clone()))
794 .collect();
795 expected_pairs.insert(1, (Type::free_var(1), Type::free_var(0)));
796 assert_eq!(equal_elements, expected_pairs);
797
798 let equal_elements: Vec<_> = slice
799 .iter(5)
800 .zip(tuple.iter(5))
801 .map(|(x, y)| (x.clone(), y.clone()))
802 .collect();
803 expected_pairs.insert(2, (Type::free_var(1), Type::free_var(0)));
804 assert_eq!(equal_elements, expected_pairs);
805 }
806
807 fn create_test_tuples() -> (Tuple, Tuple) {
808 let tuple = Tuple {
809 start: vec![Type::NUM],
810 middle: Some(Slice::new(Type::free_var(0), UnknownLen::free_var(1))),
811 end: vec![Type::BOOL, Type::free_var(2)],
812 };
813 let other_tuple = Tuple {
814 start: vec![Type::NUM, Type::free_var(3)],
815 middle: Some(Slice::new(Type::BOOL, UnknownLen::free_var(1))),
816 end: vec![Type::free_var(1)],
817 };
818 (tuple, other_tuple)
819 }
820
821 #[test]
822 fn equal_elements_static_two_complex_tuples() {
823 let (tuple, other_tuple) = create_test_tuples();
824
825 let equal_elements: Vec<_> = tuple.iter(3).zip(other_tuple.iter(3)).collect();
826 assert_eq!(
827 equal_elements,
828 vec![
829 (&Type::NUM, &Type::NUM),
830 (&Type::BOOL, &Type::free_var(3)),
831 (&Type::free_var(2), &Type::free_var(1)),
832 ]
833 );
834
835 let equal_elements: Vec<_> = tuple.iter(4).zip(other_tuple.iter(4)).collect();
836 assert_eq!(
837 equal_elements,
838 vec![
839 (&Type::NUM, &Type::NUM),
840 (&Type::free_var(0), &Type::free_var(3)),
841 (&Type::BOOL, &Type::BOOL),
842 (&Type::free_var(2), &Type::free_var(1)),
843 ]
844 );
845 }
846
847 #[test]
848 fn equal_elements_dyn_two_slices() {
849 let slice = Tuple::from(Slice::new(Type::free_var(0), UnknownLen::free_var(0)));
850 let other_slice = Tuple::from(Slice::new(Type::NUM, UnknownLen::free_var(1)));
851 let equal_elements: Vec<_> = slice.equal_elements_dyn(&other_slice).collect();
852
853 assert_eq!(equal_elements, vec![(&Type::free_var(0), &Type::NUM)]);
854 }
855
856 #[test]
857 fn equal_elements_dyn_two_complex_tuples() {
858 let (tuple, other_tuple) = create_test_tuples();
859 let equal_elements: Vec<_> = tuple.equal_elements_dyn(&other_tuple).collect();
860
861 assert_eq!(
862 equal_elements,
863 vec![
864 (&Type::free_var(0), &Type::BOOL),
866 (&Type::NUM, &Type::NUM),
868 (&Type::free_var(2), &Type::free_var(1)),
869 (&Type::free_var(0), &Type::BOOL),
871 (&Type::free_var(0), &Type::free_var(3)),
873 ]
874 );
875 }
876
877 #[test]
878 fn tuple_indexing() {
879 let tuple = Tuple::from(vec![Type::NUM, Type::BOOL]);
881 assert_eq!(*tuple.get_element(0, TupleLen::ZERO).unwrap(), Type::NUM,);
882 assert_eq!(*tuple.get_element(1, TupleLen::ZERO).unwrap(), Type::BOOL,);
883 assert_matches!(
884 tuple.get_element(2, TupleLen::ZERO).unwrap_err(),
885 IndexError::OutOfBounds
886 );
887
888 let tuple = Tuple::from(Slice::new(Type::NUM, UnknownLen::param(0)));
890 assert_eq!(*tuple.get_element(0, TupleLen::from(3)).unwrap(), Type::NUM);
891 assert_matches!(
892 tuple.get_element(3, TupleLen::from(3)).unwrap_err(),
893 IndexError::OutOfBounds
894 );
895 assert_matches!(
896 tuple
897 .get_element(0, UnknownLen::free_var(0).into())
898 .unwrap_err(),
899 IndexError::NoInfo
900 );
901 assert_eq!(
902 *tuple.get_element(0, UnknownLen::free_var(0) + 1).unwrap(),
903 Type::NUM
904 );
905
906 let (tuple, _) = create_test_tuples();
908 assert_eq!(
909 *tuple
910 .get_element(0, UnknownLen::free_var(0).into())
911 .unwrap(),
912 Type::NUM
913 );
914 assert_matches!(
915 tuple
916 .get_element(1, UnknownLen::free_var(0).into())
917 .unwrap_err(),
918 IndexError::NoInfo
919 );
920
921 assert_eq!(*tuple.get_element(1, 2.into()).unwrap(), Type::free_var(0));
922 assert_eq!(*tuple.get_element(3, 2.into()).unwrap(), Type::BOOL);
923 assert_matches!(
924 tuple.get_element(5, 2.into()).unwrap_err(),
925 IndexError::OutOfBounds
926 );
927 }
928}