1 use serde::{Deserialize, Serialize};
2 use std::{fmt, iter::FusedIterator, ops::Range};
4 pub trait DisplayOptionIdx {
5 type Type: fmt::Display;
6 fn display_option_idx(self) -> Self::Type;
9 macro_rules! define_index {
12 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
20 pub const fn new(value: usize) -> Self {
23 pub const fn get(self) -> usize {
26 pub const fn next(self) -> Self {
28 value: self.value + 1,
31 pub const fn prev(self) -> Self {
33 value: self.value - 1,
39 #[derive(Copy, Clone)]
40 pub struct DisplayOptionIdxImpl(Option<$name>);
42 impl fmt::Debug for DisplayOptionIdxImpl {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 fmt::Display::fmt(self, f)
48 impl fmt::Display for DisplayOptionIdxImpl {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 None => write!(f, "none"),
56 impl DisplayOptionIdx for Option<$name> {
57 type Type = DisplayOptionIdxImpl;
59 fn display_option_idx(self) -> Self::Type {
60 DisplayOptionIdxImpl(self)
67 define_index!(SSAValIdx);
68 define_index!(InstIdx);
69 define_index!(BlockIdx);
71 impl fmt::Display for SSAValIdx {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(f, "v{}", self.get())
77 impl fmt::Display for InstIdx {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(f, "inst{}", self.get())
83 impl fmt::Display for BlockIdx {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 write!(f, "blk{}", self.get())
90 pub const ENTRY_BLOCK: BlockIdx = BlockIdx::new(0);
93 /// range of instruction indexes from `start` inclusive to `end` exclusive.
94 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
95 pub struct InstRange {
100 impl fmt::Display for InstRange {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "inst{}..{}", self.start.get(), self.end.get())
106 impl IntoIterator for InstRange {
108 type IntoIter = InstRangeIter;
109 fn into_iter(self) -> Self::IntoIter {
115 pub const fn iter(self) -> InstRangeIter {
116 InstRangeIter(self.start.get()..self.end.get())
118 pub const fn is_empty(self) -> bool {
119 self.start.get() >= self.end.get()
121 pub const fn first(self) -> Option<InstIdx> {
122 Some(const_try_opt!(self.split_first()).0)
124 pub const fn last(self) -> Option<InstIdx> {
125 Some(const_try_opt!(self.split_last()).0)
127 pub const fn split_first(self) -> Option<(InstIdx, InstRange)> {
134 start: self.start.next(),
140 pub const fn split_last(self) -> Option<(InstIdx, InstRange)> {
148 end: self.end.prev(),
153 pub const fn len(self) -> usize {
157 self.end.get() - self.start.get()
162 #[derive(Clone, Debug)]
163 pub struct InstRangeIter(Range<usize>);
166 pub const fn range(self) -> InstRange {
168 start: InstIdx::new(self.0.start),
169 end: InstIdx::new(self.0.end),
174 impl Iterator for InstRangeIter {
177 fn next(&mut self) -> Option<Self::Item> {
178 self.0.next().map(InstIdx::new)
181 fn size_hint(&self) -> (usize, Option<usize>) {
182 let v = self.0.len();
186 fn count(self) -> usize
193 fn last(self) -> Option<Self::Item>
197 self.0.last().map(InstIdx::new)
200 fn nth(&mut self, n: usize) -> Option<Self::Item> {
201 self.0.nth(n).map(InstIdx::new)
205 impl FusedIterator for InstRangeIter {}
207 impl DoubleEndedIterator for InstRangeIter {
208 fn next_back(&mut self) -> Option<Self::Item> {
209 self.0.next_back().map(InstIdx::new)
212 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
213 self.0.nth_back(n).map(InstIdx::new)
217 impl ExactSizeIterator for InstRangeIter {
218 fn len(&self) -> usize {