1use core::borrow::Borrow;
2
3use smallvec::{smallvec, SmallVec};
4
5use super::*;
6use crate::adt::SmallSet;
7
8pub enum ValueRange<'a, const N: usize = 2> {
18    Empty,
20    Owned(SmallVec<[ValueRef; N]>),
22    Borrowed(&'a [ValueRef]),
24    BlockArguments(&'a [BlockArgumentRef]),
26    Operands(&'a [OpOperand]),
28    Results(&'a [OpResultRef]),
30}
31
32impl<const N: usize> Default for ValueRange<'_, N> {
33    fn default() -> Self {
34        Self::Empty
35    }
36}
37
38impl<'values, const N: usize> ValueRange<'values, N> {
39    pub fn is_empty(&self) -> bool {
41        match self {
42            Self::Empty => true,
43            Self::Owned(values) => values.is_empty(),
44            Self::Borrowed(values) => values.is_empty(),
45            Self::BlockArguments(range) => range.is_empty(),
46            Self::Operands(range) => range.is_empty(),
47            Self::Results(range) => range.is_empty(),
48        }
49    }
50
51    pub fn len(&self) -> usize {
53        match self {
54            Self::Empty => 0,
55            Self::Owned(values) => values.len(),
56            Self::Borrowed(values) => values.len(),
57            Self::BlockArguments(range) => range.len(),
58            Self::Operands(range) => range.len(),
59            Self::Results(range) => range.len(),
60        }
61    }
62
63    pub fn slice<'a, 'b: 'a + 'values, R>(&'b self, range: R) -> ValueRange<'a, N>
64    where
65        R: core::slice::SliceIndex<[ValueRef], Output = [ValueRef]>,
66        R: core::slice::SliceIndex<[BlockArgumentRef], Output = [BlockArgumentRef]>,
67        R: core::slice::SliceIndex<[OpOperand], Output = [OpOperand]>,
68        R: core::slice::SliceIndex<[OpResultRef], Output = [OpResultRef]>,
69    {
70        match self {
71            Self::Empty => ValueRange::Empty,
72            Self::Owned(values) => Self::Borrowed(&values[range]),
73            Self::Borrowed(values) => Self::Borrowed(&values[range]),
74            Self::BlockArguments(values) => Self::BlockArguments(&values[range]),
75            Self::Operands(values) => Self::Operands(&values[range]),
76            Self::Results(values) => Self::Results(&values[range]),
77        }
78    }
79
80    pub fn get(&self, index: usize) -> Option<ValueRef> {
82        match self {
83            Self::Empty => None,
84            Self::Owned(values) => values.get(index).cloned(),
85            Self::Borrowed(values) => values.get(index).cloned(),
86            Self::BlockArguments(range) => {
87                range.get(index).map(|operand| operand.borrow().as_value_ref())
88            }
89            Self::Operands(range) => {
90                range.get(index).map(|operand| operand.borrow().as_value_ref())
91            }
92            Self::Results(range) => range.get(index).map(|result| result.borrow().as_value_ref()),
93        }
94    }
95
96    pub fn contains<V>(&self, value: V) -> bool
98    where
99        V: Borrow<ValueRef>,
100    {
101        let value = value.borrow();
102        match self {
103            Self::Empty => false,
104            Self::Owned(values) => values.contains(value),
105            Self::Borrowed(values) => values.contains(value),
106            Self::BlockArguments(args) => args.iter().copied().any(|arg| arg as ValueRef == *value),
107            Self::Operands(operands) => {
108                operands.iter().any(|operand| operand.borrow().as_value_ref() == *value)
109            }
110            Self::Results(results) => {
111                results.iter().copied().any(|result| result as ValueRef == *value)
112            }
113        }
114    }
115
116    pub fn iter(&self) -> ValueRangeIter<'_, N> {
118        match self {
119            Self::Empty => ValueRangeIter::new(ValueRange::Borrowed(&[])),
120            Self::Owned(values) => ValueRangeIter::new(ValueRange::Borrowed(values.as_slice())),
121            Self::Borrowed(values) => ValueRangeIter::new(ValueRange::Borrowed(values)),
122            Self::BlockArguments(values) => ValueRangeIter::new(ValueRange::BlockArguments(values)),
123            Self::Operands(values) => ValueRangeIter::new(ValueRange::Operands(values)),
124            Self::Results(values) => ValueRangeIter::new(ValueRange::Results(values)),
125        }
126    }
127
128    pub fn into_owned(self) -> ValueRange<'static, N> {
130        ValueRange::Owned(self.into_smallvec())
131    }
132
133    pub fn into_smallvec(self) -> SmallVec<[ValueRef; N]> {
135        match self {
136            Self::Empty => smallvec![],
137            Self::Owned(values) => values,
138            Self::Borrowed(values) => SmallVec::from_slice(values),
139            Self::BlockArguments(args) => args.iter().copied().map(|arg| arg as ValueRef).collect(),
140            Self::Operands(operands) => {
141                operands.iter().map(|operand| operand.borrow().as_value_ref()).collect()
142            }
143            Self::Results(results) => {
144                results.iter().copied().map(|result| result as ValueRef).collect()
145            }
146        }
147    }
148
149    pub fn to_vec(&self) -> alloc::vec::Vec<ValueRef> {
151        match self {
152            Self::Empty => Default::default(),
153            Self::Owned(values) => values.to_vec(),
154            Self::Borrowed(values) => values.to_vec(),
155            Self::BlockArguments(args) => args.iter().copied().map(|arg| arg as ValueRef).collect(),
156            Self::Operands(operands) => {
157                operands.iter().map(|operand| operand.borrow().as_value_ref()).collect()
158            }
159            Self::Results(results) => {
160                results.iter().copied().map(|result| result as ValueRef).collect()
161            }
162        }
163    }
164}
165
166impl<const N: usize> core::fmt::Debug for ValueRange<'_, N> {
167    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
168        fmt::Display::fmt(self, f)
169    }
170}
171
172impl<const N: usize> core::fmt::Display for ValueRange<'_, N> {
173    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174        let mut builder = f.debug_list();
175        for value in self.iter() {
176            builder.entry_with(|f| write!(f, "{value}"));
177        }
178
179        builder.finish()
180    }
181}
182
183impl<const N: usize> FromIterator<ValueRef> for ValueRange<'static, N> {
184    fn from_iter<I>(iter: I) -> Self
185    where
186        I: IntoIterator<Item = ValueRef>,
187    {
188        Self::Owned(SmallVec::from_iter(iter))
189    }
190}
191
192impl<const N: usize> FromIterator<BlockArgumentRef> for ValueRange<'static, N> {
193    fn from_iter<I>(iter: I) -> Self
194    where
195        I: IntoIterator<Item = BlockArgumentRef>,
196    {
197        Self::from_iter(iter.into_iter().map(|arg| arg as ValueRef))
198    }
199}
200
201impl<const N: usize> FromIterator<OpResultRef> for ValueRange<'static, N> {
202    fn from_iter<I>(iter: I) -> Self
203    where
204        I: IntoIterator<Item = OpResultRef>,
205    {
206        Self::from_iter(iter.into_iter().map(|result| result as ValueRef))
207    }
208}
209
210impl<const N: usize> FromIterator<OpOperand> for ValueRange<'static, N> {
211    fn from_iter<I>(iter: I) -> Self
212    where
213        I: IntoIterator<Item = OpOperand>,
214    {
215        Self::from_iter(iter.into_iter().map(|operand| operand.borrow().as_value_ref()))
216    }
217}
218
219impl<'a, const N: usize> IntoIterator for ValueRange<'a, N> {
220    type IntoIter = ValueRangeIter<'a, N>;
221    type Item = ValueRef;
222
223    fn into_iter(self) -> Self::IntoIter {
224        ValueRangeIter::new(self)
225    }
226}
227
228impl<'a, 'b: 'a, const N: usize> IntoIterator for &'a ValueRange<'b, N> {
229    type IntoIter = ValueRangeIter<'a, N>;
230    type Item = ValueRef;
231
232    fn into_iter(self) -> Self::IntoIter {
233        self.iter()
234    }
235}
236
237impl<const N: usize> From<SmallVec<[ValueRef; N]>> for ValueRange<'static, N> {
238    fn from(values: SmallVec<[ValueRef; N]>) -> Self {
239        Self::Owned(SmallVec::from_slice(&values))
240    }
241}
242
243impl<'a, const M: usize, const N: usize> From<&'a SmallVec<[ValueRef; M]>> for ValueRange<'a, N> {
244    fn from(values: &'a SmallVec<[ValueRef; M]>) -> Self {
245        Self::Borrowed(values.as_slice())
246    }
247}
248
249impl<const N: usize> From<SmallSet<ValueRef, N>> for ValueRange<'static, N> {
250    fn from(values: SmallSet<ValueRef, N>) -> Self {
251        Self::Owned(values.into_vec())
252    }
253}
254
255impl<'a, const M: usize, const N: usize> From<&'a SmallSet<ValueRef, M>> for ValueRange<'a, N> {
256    fn from(values: &'a SmallSet<ValueRef, M>) -> Self {
257        Self::Borrowed(values.as_slice())
258    }
259}
260
261impl<'a, const N: usize> From<&'a [ValueRef]> for ValueRange<'a, N> {
262    fn from(values: &'a [ValueRef]) -> Self {
263        Self::Borrowed(values)
264    }
265}
266
267impl<'a, const N: usize> From<BlockArgumentRange<'a>> for ValueRange<'a, N> {
268    fn from(range: BlockArgumentRange<'a>) -> Self {
269        Self::BlockArguments(range.as_slice())
270    }
271}
272
273impl<'a, const N: usize> From<&'a [BlockArgumentRef]> for ValueRange<'a, N> {
274    fn from(range: &'a [BlockArgumentRef]) -> Self {
275        Self::BlockArguments(range)
276    }
277}
278
279impl<'a, const N: usize> From<OpOperandRange<'a>> for ValueRange<'a, N> {
280    fn from(range: OpOperandRange<'a>) -> Self {
281        Self::Operands(range.as_slice())
282    }
283}
284
285impl<'a, const N: usize> From<&'a [OpOperand]> for ValueRange<'a, N> {
286    fn from(range: &'a [OpOperand]) -> Self {
287        Self::Operands(range)
288    }
289}
290
291impl<'a, const N: usize> From<OpResultRange<'a>> for ValueRange<'a, N> {
292    fn from(range: OpResultRange<'a>) -> Self {
293        Self::Results(range.as_slice())
294    }
295}
296
297impl<'a, const N: usize> From<&'a [OpResultRef]> for ValueRange<'a, N> {
298    fn from(range: &'a [OpResultRef]) -> Self {
299        Self::Results(range)
300    }
301}
302
303impl<'a, const N: usize> From<SuccessorOperandRange<'a>> for ValueRange<'a, N> {
304    fn from(range: SuccessorOperandRange<'a>) -> Self {
305        Self::from(range.into_forwarded())
306    }
307}
308
309pub trait AsValueRange {
310    fn as_value_range(&self) -> ValueRange<'_, 2>;
311}
312
313impl<T: AsValueRange> AsValueRange for Option<T> {
314    fn as_value_range(&self) -> ValueRange<'_, 2> {
315        match self.as_ref() {
316            Some(values) => values.as_value_range(),
317            None => ValueRange::Empty,
318        }
319    }
320}
321
322impl AsValueRange for [ValueRef] {
323    fn as_value_range(&self) -> ValueRange<'_, 2> {
324        ValueRange::Borrowed(self)
325    }
326}
327
328impl AsValueRange for [BlockArgumentRef] {
329    fn as_value_range(&self) -> ValueRange<'_, 2> {
330        ValueRange::BlockArguments(self)
331    }
332}
333
334impl AsValueRange for [OpOperand] {
335    fn as_value_range(&self) -> ValueRange<'_, 2> {
336        ValueRange::Operands(self)
337    }
338}
339
340impl AsValueRange for [OpResultRef] {
341    fn as_value_range(&self) -> ValueRange<'_, 2> {
342        ValueRange::Results(self)
343    }
344}
345
346impl AsValueRange for alloc::vec::Vec<ValueRef> {
347    fn as_value_range(&self) -> ValueRange<'_, 2> {
348        ValueRange::Borrowed(self.as_slice())
349    }
350}
351
352impl<const N: usize> AsValueRange for SmallVec<[ValueRef; N]> {
353    fn as_value_range(&self) -> ValueRange<'_, 2> {
354        ValueRange::Borrowed(self.as_slice())
355    }
356}
357
358impl AsValueRange for OpOperandStorage {
359    fn as_value_range(&self) -> ValueRange<'_, 2> {
360        ValueRange::Operands(self.all().as_slice())
361    }
362}
363
364impl AsValueRange for OpResultStorage {
365    fn as_value_range(&self) -> ValueRange<'_, 2> {
366        ValueRange::Results(self.all().as_slice())
367    }
368}
369
370impl AsValueRange for OpOperandRange<'_> {
371    fn as_value_range(&self) -> ValueRange<'_, 2> {
372        ValueRange::Operands(self.as_slice())
373    }
374}
375
376impl AsValueRange for OpOperandRangeMut<'_> {
377    fn as_value_range(&self) -> ValueRange<'_, 2> {
378        ValueRange::Operands(self.as_slice())
379    }
380}
381
382impl AsValueRange for OpResultRange<'_> {
383    fn as_value_range(&self) -> ValueRange<'_, 2> {
384        ValueRange::Results(self.as_slice())
385    }
386}
387
388impl AsValueRange for OpResultRangeMut<'_> {
389    fn as_value_range(&self) -> ValueRange<'_, 2> {
390        ValueRange::Results(self.as_slice())
391    }
392}
393
394impl AsValueRange for BlockArgumentRange<'_> {
395    fn as_value_range(&self) -> ValueRange<'_, 2> {
396        ValueRange::BlockArguments(self.as_slice())
397    }
398}
399
400impl AsValueRange for BlockArgumentRangeMut<'_> {
401    fn as_value_range(&self) -> ValueRange<'_, 2> {
402        ValueRange::BlockArguments(self.as_slice())
403    }
404}
405
406pub struct ValueRangeIter<'a, const N: usize> {
408    range: ValueRange<'a, N>,
409    index: usize,
410}
411
412impl<'a, const N: usize> ValueRangeIter<'a, N> {
413    pub fn new(range: ValueRange<'a, N>) -> Self {
414        Self { range, index: 0 }
415    }
416}
417
418impl<const N: usize> core::iter::FusedIterator for ValueRangeIter<'_, N> {}
419impl<const N: usize> ExactSizeIterator for ValueRangeIter<'_, N> {
420    fn len(&self) -> usize {
421        let len = self.range.len();
422        len.saturating_sub(self.index)
423    }
424}
425impl<const N: usize> Iterator for ValueRangeIter<'_, N> {
426    type Item = ValueRef;
427
428    fn next(&mut self) -> Option<Self::Item> {
429        let len = self.range.len();
430        if self.index >= len {
431            return None;
432        }
433
434        let index = self.index;
435        self.index += 1;
436        match &self.range {
437            ValueRange::Empty => None,
438            ValueRange::Owned(values) => values.get(index).cloned(),
439            ValueRange::Borrowed(values) => values.get(index).cloned(),
440            ValueRange::BlockArguments(range) => {
441                range.get(index).map(|o| o.borrow().as_value_ref())
442            }
443            ValueRange::Operands(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
444            ValueRange::Results(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
445        }
446    }
447}
448
449impl<const N: usize> DoubleEndedIterator for ValueRangeIter<'_, N> {
450    fn next_back(&mut self) -> Option<Self::Item> {
451        let len = self.range.len();
452        let index = len.checked_sub(self.index + 1)?;
453
454        self.index += 1;
455        match &self.range {
456            ValueRange::Empty => None,
457            ValueRange::Owned(values) => values.get(index).cloned(),
458            ValueRange::Borrowed(values) => values.get(index).cloned(),
459            ValueRange::BlockArguments(range) => {
460                range.get(index).map(|o| o.borrow().as_value_ref())
461            }
462            ValueRange::Operands(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
463            ValueRange::Results(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
464        }
465    }
466}