midenc_hir/ir/effects/
interface.rs

1use smallvec::SmallVec;
2
3use super::*;
4use crate::{SymbolRef, ValueRef};
5
6pub trait EffectOpInterface<T: Effect> {
7    /// Return the set all of the operation's effects
8    fn effects(&self) -> EffectIterator<T>;
9    /// Returns true if this operation has no effects
10    fn has_no_effect(&self) -> bool {
11        self.effects().is_empty()
12    }
13    /// Return the set of effect instances that operate on the provided value
14    fn effects_on_value(&self, value: ValueRef) -> ValueEffectIterator<T> {
15        EffectIterator::for_value(self.effects(), value)
16    }
17    /// Return the set of effect instances that operate on the provided symbol
18    fn effects_on_symbol(&self, symbol: SymbolRef) -> SymbolEffectIterator<T> {
19        EffectIterator::for_symbol(self.effects(), symbol)
20    }
21    /// Return the set of effect instances that operate on the provided resource
22    fn effects_on_resource<'a, 'b: 'a>(
23        &self,
24        resource: &'b dyn Resource,
25    ) -> ResourceEffectIterator<'b, T> {
26        EffectIterator::for_resource(self.effects(), resource)
27    }
28}
29
30impl<T: Effect> dyn EffectOpInterface<T> {
31    /// Return the set all of the operation's effects that correspond to effect type `T`
32    pub fn effects_of_type<E>(&self) -> impl Iterator<Item = EffectInstance<T>> + '_
33    where
34        E: Effect,
35    {
36        self.effects().filter(|instance| (instance.effect() as &dyn Any).is::<E>())
37    }
38
39    /// Returns true if the operation exhibits the given effect.
40    pub fn has_effect<E>(&self) -> bool
41    where
42        E: Any,
43    {
44        self.effects().any(|instance| (instance.effect() as &dyn Any).is::<E>())
45    }
46
47    /// Returns true if the operation only exhibits the given effect.
48    pub fn only_has_effect<E>(&self) -> bool
49    where
50        E: Any,
51    {
52        let mut effects = self.effects();
53        !effects.is_empty() && effects.all(|instance| (instance.effect() as &dyn Any).is::<E>())
54    }
55}
56
57pub struct EffectIterator<T> {
58    effects: smallvec::IntoIter<[EffectInstance<T>; 4]>,
59}
60impl<T> EffectIterator<T> {
61    pub fn from_smallvec(effects: SmallVec<[EffectInstance<T>; 4]>) -> Self {
62        Self {
63            effects: effects.into_iter(),
64        }
65    }
66
67    pub fn new(effects: impl IntoIterator<Item = EffectInstance<T>>) -> Self {
68        let effects = effects.into_iter().collect::<SmallVec<[_; 4]>>();
69        Self {
70            effects: effects.into_iter(),
71        }
72    }
73
74    pub const fn for_value(effects: Self, value: ValueRef) -> ValueEffectIterator<T> {
75        ValueEffectIterator {
76            iter: effects,
77            value,
78        }
79    }
80
81    pub const fn for_symbol(effects: Self, symbol: SymbolRef) -> SymbolEffectIterator<T> {
82        SymbolEffectIterator {
83            iter: effects,
84            symbol,
85        }
86    }
87
88    pub const fn for_resource(
89        effects: Self,
90        resource: &dyn Resource,
91    ) -> ResourceEffectIterator<'_, T> {
92        ResourceEffectIterator {
93            iter: effects,
94            resource,
95        }
96    }
97
98    #[inline]
99    pub fn as_slice(&self) -> &[EffectInstance<T>] {
100        self.effects.as_slice()
101    }
102}
103impl<T> core::iter::FusedIterator for EffectIterator<T> {}
104impl<T> ExactSizeIterator for EffectIterator<T> {
105    fn is_empty(&self) -> bool {
106        self.effects.is_empty()
107    }
108
109    fn len(&self) -> usize {
110        self.effects.len()
111    }
112}
113impl<T> Iterator for EffectIterator<T> {
114    type Item = EffectInstance<T>;
115
116    #[inline]
117    fn next(&mut self) -> Option<Self::Item> {
118        self.effects.next()
119    }
120}
121
122pub struct ValueEffectIterator<T> {
123    iter: EffectIterator<T>,
124    value: ValueRef,
125}
126impl<T> core::iter::FusedIterator for ValueEffectIterator<T> {}
127impl<T> Iterator for ValueEffectIterator<T> {
128    type Item = EffectInstance<T>;
129
130    fn next(&mut self) -> Option<Self::Item> {
131        while let Some(instance) = self.iter.next() {
132            if instance.value().is_some_and(|v| v == self.value) {
133                return Some(instance);
134            }
135        }
136
137        None
138    }
139}
140
141pub struct SymbolEffectIterator<T> {
142    iter: EffectIterator<T>,
143    symbol: SymbolRef,
144}
145impl<T> core::iter::FusedIterator for SymbolEffectIterator<T> {}
146impl<T> Iterator for SymbolEffectIterator<T> {
147    type Item = EffectInstance<T>;
148
149    fn next(&mut self) -> Option<Self::Item> {
150        while let Some(instance) = self.iter.next() {
151            if instance.symbol().is_some_and(|s| s == self.symbol) {
152                return Some(instance);
153            }
154        }
155
156        None
157    }
158}
159
160pub struct ResourceEffectIterator<'a, T> {
161    iter: EffectIterator<T>,
162    resource: &'a dyn Resource,
163}
164impl<T> core::iter::FusedIterator for ResourceEffectIterator<'_, T> {}
165impl<T> Iterator for ResourceEffectIterator<'_, T> {
166    type Item = EffectInstance<T>;
167
168    fn next(&mut self) -> Option<Self::Item> {
169        #[allow(clippy::while_let_on_iterator)]
170        while let Some(instance) = self.iter.next() {
171            if instance.resource().dyn_eq(self.resource) {
172                return Some(instance);
173            }
174        }
175
176        None
177    }
178}