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