1#![allow(clippy::doc_markdown)]
14#![allow(clippy::used_underscore_binding)]
15
16use std::fmt::Debug;
17use std::ops::Range;
18use index_vec::Idx;
19use more_asserts::assert_gt;
20use pretty_assertions::assert_eq;
21use std::iter;
22
23
24pub type IdxRangeIter<I> = iter::Map<Range<usize>, fn(usize) -> I>;
25
26macro_rules! id_type {
27 ($name:ident($type:ident)) => {
28 ::index_vec::define_index_type! {
30 pub struct $name = $type;
31
32 DISPLAY_FORMAT = "{}";
33
34 DEBUG_FORMAT = stringify!(<$name {}>);
35
36 IMPL_RAW_CONVERSIONS = true;
37 }
38 };
39}
40
41id_type!(BranchId(u16));
42
43id_type!(NetId(u16));
44
45id_type!(PortId(u16));
46
47id_type!(ParameterId(u32));
48
49id_type!(VariableId(u32));
50
51id_type!(ModuleId(u16));
52
53id_type!(FunctionId(u16));
54
55id_type!(DisciplineId(u16));
56
57id_type!(ExpressionId(u32));
58id_type!(RealExpressionId(u32));
59id_type!(IntegerExpressionId(u32));
60id_type!(StringExpressionId(u32));
61
62id_type!(BlockId(u16));
63
64id_type!(AttributeId(u16));
65
66id_type!(StatementId(u32));
67
68id_type!(NatureId(u16));
69
70#[derive(Clone, Debug)]
71pub struct IdRange<I: Idx>(pub Range<I>);
72
73impl<I: Idx> IdRange<I> {
74 pub fn enter_back(&mut self, sub_range: &Self) -> Self {
75 if cfg!(debug_assertions) && self.len() != 0 {
76 assert_eq!(self.0.end, sub_range.0.end);
77 assert_gt!(sub_range.0.start, self.0.start);
78 }
79
80 self.0.end = sub_range.0.start;
81
82 sub_range.clone()
83 }
84}
85
86impl<I: Idx> Iterator for IdRange<I> {
87 type Item = I;
88
89 #[inline]
90 fn next(&mut self) -> Option<Self::Item> {
91 if self.0.start < self.0.end {
92 let res = self.0.start;
93 self.0.start = I::from_usize(self.0.start.index() + 1);
94 Some(res)
95 } else {
96 None
97 }
98 }
99
100 #[inline]
101 fn size_hint(&self) -> (usize, Option<usize>) {
102 let len = self.len();
103 (len, Some(len))
104 }
105
106 #[inline]
107 fn count(self) -> usize {
108 self.len()
109 }
110
111 #[inline]
112 fn last(mut self) -> Option<Self::Item> {
113 self.next_back()
114 }
115
116 #[inline]
117 fn max(self) -> Option<Self::Item> {
118 self.last()
119 }
120
121 #[inline]
122 fn min(self) -> Option<Self::Item> {
123 Some(self.0.start)
124 }
125
126 fn nth(&mut self, n: usize) -> Option<Self::Item> {
127 let new_start = I::from_usize(self.0.start.index() + n);
128 if new_start < self.0.end {
129 self.0.start = I::from_usize(new_start.index() + 1);
130 Some(new_start)
131 } else {
132 self.0.start = self.0.end;
133 None
134 }
135 }
136}
137
138impl<I: Idx> ExactSizeIterator for IdRange<I> {
139 fn len(&self) -> usize {
140 self.0.end.index() - self.0.start.index()
141 }
142}
143
144impl<I: Idx> DoubleEndedIterator for IdRange<I> {
145 fn next_back(&mut self) -> Option<Self::Item> {
146 if self.0.start < self.0.end {
147 self.0.end = I::from_usize(self.0.end.index() - 1);
148 Some(self.0.end)
149 } else {
150 None
151 }
152 }
153
154 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
155 let new_end = I::from_usize(self.0.end.index() - n);
156 if self.0.start < new_end {
157 self.0.end = I::from_usize(new_end.index() - 1);
158 Some(new_end)
159 } else {
160 self.0.end = self.0.start;
161 None
162 }
163 }
164}
165
166#[macro_export]
187macro_rules! impl_id_type {
188 ($name:ident in $container:ident::$sub_container:ident -> $type:ty) => {
189 impl ::std::ops::Index<$name> for $container {
190 type Output = $type;
191 fn index(&self, index: $name) -> &Self::Output {
192 &self.$sub_container[index]
193 }
194 }
195
196 impl ::std::ops::IndexMut<$name> for $container {
197 fn index_mut(&mut self, index: $name) -> &mut Self::Output {
198 &mut self.$sub_container[index]
199 }
200 }
201
202 impl ::std::ops::Index<Range<$name>> for $container {
203 type Output = ::index_vec::IndexSlice<$name, [$type]>;
204 fn index(&self, range: Range<$name>) -> &Self::Output {
205 &self.$sub_container[range]
206 }
207 }
208
209 impl ::std::ops::IndexMut<Range<$name>> for $container {
210 fn index_mut(&mut self, range: Range<$name>) -> &mut Self::Output {
211 &mut self.$sub_container[range]
212 }
213 }
214
215 impl ::std::ops::Index<$crate::ir::ids::IdRange<$name>> for $container {
216 type Output = ::index_vec::IndexSlice<$name, [$type]>;
217 fn index(&self, range: $crate::ir::ids::IdRange<$name>) -> &Self::Output {
218 &self.$sub_container[range.0]
219 }
220 }
221
222 impl ::std::ops::IndexMut<$crate::ir::ids::IdRange<$name>> for $container {
223 fn index_mut(&mut self, range: $crate::ir::ids::IdRange<$name>) -> &mut Self::Output {
224 &mut self.$sub_container[range.0]
225 }
226 }
227 };
228}