1 use serde::{de::DeserializeOwned, Deserialize, Serialize};
2 use std::{fmt, hash::Hash, iter::FusedIterator, ops::Range};
4 pub trait DisplayOptionIdx {
5 type Type: fmt::Display;
6 fn display_option_idx(self) -> Self::Type;
9 pub trait IndexTy: Copy + fmt::Debug + Ord + Hash + Serialize + DeserializeOwned {
10 fn new(value: usize) -> Self;
11 fn get(self) -> usize;
12 fn next(self) -> Self {
13 Self::new(self.get() + 1)
15 fn prev(self) -> Self {
16 Self::new(self.get() - 1)
20 #[derive(Debug, Clone)]
21 pub struct RangeIter<T: IndexTy>(pub Range<T>);
23 impl<T: IndexTy> RangeIter<T> {
24 pub fn as_usize_range(&self) -> Range<usize> {
25 self.0.start.get()..self.0.end.get()
27 pub fn from_usize_range(range: Range<usize>) -> Self {
28 Self(T::new(range.start)..T::new(range.end))
30 pub fn with_self_as_usize_range<R, F: FnOnce(&mut Range<usize>) -> R>(&mut self, f: F) -> R {
31 let mut range = self.as_usize_range();
32 let retval = f(&mut range);
33 *self = Self::from_usize_range(range);
38 impl<T: IndexTy> Iterator for RangeIter<T> {
41 fn next(&mut self) -> Option<Self::Item> {
42 self.with_self_as_usize_range(|r| r.next().map(T::new))
45 fn size_hint(&self) -> (usize, Option<usize>) {
46 self.as_usize_range().size_hint()
49 fn nth(&mut self, n: usize) -> Option<Self::Item> {
50 self.with_self_as_usize_range(|r| r.nth(n).map(T::new))
53 fn fold<B, F>(self, init: B, mut f: F) -> B
55 F: FnMut(B, Self::Item) -> B,
58 .fold(init, move |a, v| f(a, T::new(v)))
62 impl<T: IndexTy> FusedIterator for RangeIter<T> {}
64 impl<T: IndexTy> ExactSizeIterator for RangeIter<T> {
65 fn len(&self) -> usize {
66 self.as_usize_range().len()
70 impl<T: IndexTy> DoubleEndedIterator for RangeIter<T> {
71 fn next_back(&mut self) -> Option<Self::Item> {
72 self.with_self_as_usize_range(|r| r.next_back().map(T::new))
75 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
76 self.with_self_as_usize_range(|r| r.nth_back(n).map(T::new))
79 fn rfold<B, F>(self, init: B, mut f: F) -> B
81 F: FnMut(B, Self::Item) -> B,
84 .rfold(init, move |a, v| f(a, T::new(v)))
88 macro_rules! define_index {
91 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
98 impl IndexTy for $name {
99 fn new(value: usize) -> Self {
102 fn get(self) -> usize {
108 pub const fn new(value: usize) -> Self {
111 pub const fn get(self) -> usize {
114 pub const fn next(self) -> Self {
116 value: self.value + 1,
119 pub const fn prev(self) -> Self {
121 value: self.value - 1,
127 #[derive(Copy, Clone)]
128 pub struct DisplayOptionIdxImpl(Option<$name>);
130 impl fmt::Debug for DisplayOptionIdxImpl {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 fmt::Display::fmt(self, f)
136 impl fmt::Display for DisplayOptionIdxImpl {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 None => write!(f, "none"),
144 impl DisplayOptionIdx for Option<$name> {
145 type Type = DisplayOptionIdxImpl;
147 fn display_option_idx(self) -> Self::Type {
148 DisplayOptionIdxImpl(self)
155 define_index!(SSAValIdx);
156 define_index!(InstIdx);
157 define_index!(BlockIdx);
158 define_index!(BlockParamIdx);
159 define_index!(OperandIdx);
161 impl fmt::Display for SSAValIdx {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 write!(f, "v{}", self.get())
167 impl fmt::Display for InstIdx {
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 write!(f, "inst{}", self.get())
173 impl fmt::Display for BlockIdx {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 write!(f, "blk{}", self.get())
179 impl fmt::Display for BlockParamIdx {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 write!(f, "bparam{}", self.get())
185 impl fmt::Display for OperandIdx {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(f, "operand{}", self.get())
192 pub const ENTRY_BLOCK: BlockIdx = BlockIdx::new(0);
195 /// range of instruction indexes from `start` inclusive to `end` exclusive.
196 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
197 pub struct InstRange {
202 impl fmt::Display for InstRange {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 write!(f, "inst{}..{}", self.start.get(), self.end.get())
208 impl IntoIterator for InstRange {
210 type IntoIter = InstRangeIter;
211 fn into_iter(self) -> Self::IntoIter {
217 pub const fn iter(self) -> InstRangeIter {
218 InstRangeIter(self.start.get()..self.end.get())
220 pub const fn is_empty(self) -> bool {
221 self.start.get() >= self.end.get()
223 pub const fn first(self) -> Option<InstIdx> {
224 Some(const_try_opt!(self.split_first()).0)
226 pub const fn last(self) -> Option<InstIdx> {
227 Some(const_try_opt!(self.split_last()).0)
229 pub const fn split_first(self) -> Option<(InstIdx, InstRange)> {
236 start: self.start.next(),
242 pub const fn split_last(self) -> Option<(InstIdx, InstRange)> {
250 end: self.end.prev(),
255 pub const fn len(self) -> usize {
259 self.end.get() - self.start.get()
264 #[derive(Clone, Debug)]
265 pub struct InstRangeIter(Range<usize>);
268 pub const fn range(self) -> InstRange {
270 start: InstIdx::new(self.0.start),
271 end: InstIdx::new(self.0.end),
276 impl Iterator for InstRangeIter {
279 fn next(&mut self) -> Option<Self::Item> {
280 self.0.next().map(InstIdx::new)
283 fn size_hint(&self) -> (usize, Option<usize>) {
284 let v = self.0.len();
288 fn count(self) -> usize
295 fn last(self) -> Option<Self::Item>
299 self.0.last().map(InstIdx::new)
302 fn nth(&mut self, n: usize) -> Option<Self::Item> {
303 self.0.nth(n).map(InstIdx::new)
307 impl FusedIterator for InstRangeIter {}
309 impl DoubleEndedIterator for InstRangeIter {
310 fn next_back(&mut self) -> Option<Self::Item> {
311 self.0.next_back().map(InstIdx::new)
314 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
315 self.0.nth_back(n).map(InstIdx::new)
319 impl ExactSizeIterator for InstRangeIter {
320 fn len(&self) -> usize {