midenc_hir/
attributes.rs

1mod overflow;
2mod visibility;
3
4use alloc::{boxed::Box, collections::BTreeMap, vec, vec::Vec};
5use core::{any::Any, borrow::Borrow, fmt};
6
7pub use self::{overflow::Overflow, visibility::Visibility};
8use crate::{interner::Symbol, Immediate};
9
10pub mod markers {
11    use midenc_hir_symbol::symbols;
12
13    use super::*;
14
15    pub const INLINE: Attribute = Attribute {
16        name: symbols::Inline,
17        value: None,
18        intrinsic: false,
19    };
20}
21
22/// An [AttributeSet] is a uniqued collection of attributes associated with some IR entity
23#[derive(Debug, Default, Clone)]
24pub struct AttributeSet(Vec<Attribute>);
25impl FromIterator<Attribute> for AttributeSet {
26    fn from_iter<T>(attrs: T) -> Self
27    where
28        T: IntoIterator<Item = Attribute>,
29    {
30        let mut map = BTreeMap::default();
31        for attr in attrs.into_iter() {
32            map.insert(attr.name, (attr.value, attr.intrinsic));
33        }
34        Self(
35            map.into_iter()
36                .map(|(name, (value, intrinsic))| Attribute {
37                    name,
38                    value,
39                    intrinsic,
40                })
41                .collect(),
42        )
43    }
44}
45impl FromIterator<(Symbol, Option<Box<dyn AttributeValue>>)> for AttributeSet {
46    fn from_iter<T>(attrs: T) -> Self
47    where
48        T: IntoIterator<Item = (Symbol, Option<Box<dyn AttributeValue>>)>,
49    {
50        let mut map = BTreeMap::default();
51        for (name, value) in attrs.into_iter() {
52            map.insert(name, value);
53        }
54        Self(
55            map.into_iter()
56                .map(|(name, value)| Attribute {
57                    name,
58                    value,
59                    intrinsic: false,
60                })
61                .collect(),
62        )
63    }
64}
65impl AttributeSet {
66    /// Get a new, empty [AttributeSet]
67    pub const fn new() -> Self {
68        Self(Vec::new())
69    }
70
71    /// Insert a new [Attribute] in this set by `name` and `value`
72    pub fn insert(&mut self, name: impl Into<Symbol>, value: Option<impl AttributeValue>) {
73        self.set(Attribute {
74            name: name.into(),
75            value: value.map(|v| Box::new(v) as Box<dyn AttributeValue>),
76            intrinsic: false,
77        });
78    }
79
80    /// Adds `attr` to this set
81    pub fn set(&mut self, attr: Attribute) {
82        match self.0.binary_search_by_key(&attr.name, |attr| attr.name) {
83            Ok(index) => {
84                self.0[index].value = attr.value;
85            }
86            Err(index) => {
87                if index == self.0.len() {
88                    self.0.push(attr);
89                } else {
90                    self.0.insert(index, attr);
91                }
92            }
93        }
94    }
95
96    pub fn mark_intrinsic(&mut self, key: impl Into<Symbol>) {
97        let key = key.into();
98        if let Ok(index) = self.0.binary_search_by_key(&key, |attr| attr.name) {
99            self.0[index].intrinsic = true;
100        }
101    }
102
103    /// Remove an [Attribute] by name from this set
104    pub fn remove(&mut self, name: impl Into<Symbol>) {
105        let name = name.into();
106        match self.0.binary_search_by_key(&name, |attr| attr.name) {
107            Ok(index) if index + 1 == self.0.len() => {
108                self.0.pop();
109            }
110            Ok(index) => {
111                self.0.remove(index);
112            }
113            Err(_) => (),
114        }
115    }
116
117    /// Determine if the named [Attribute] is present in this set
118    pub fn has(&self, key: impl Into<Symbol>) -> bool {
119        let key = key.into();
120        self.0.binary_search_by_key(&key, |attr| attr.name).is_ok()
121    }
122
123    /// Get the [AttributeValue] associated with the named [Attribute]
124    pub fn get_any(&self, key: impl Into<Symbol>) -> Option<&dyn AttributeValue> {
125        let key = key.into();
126        match self.0.binary_search_by_key(&key, |attr| attr.name) {
127            Ok(index) => self.0[index].value.as_deref(),
128            Err(_) => None,
129        }
130    }
131
132    /// Get the [AttributeValue] associated with the named [Attribute]
133    pub fn get_any_mut(&mut self, key: impl Into<Symbol>) -> Option<&mut dyn AttributeValue> {
134        let key = key.into();
135        match self.0.binary_search_by_key(&key, |attr| attr.name) {
136            Ok(index) => self.0[index].value.as_deref_mut(),
137            Err(_) => None,
138        }
139    }
140
141    /// Get the value associated with the named [Attribute] as a value of type `V`, or `None`.
142    pub fn get<V>(&self, key: impl Into<Symbol>) -> Option<&V>
143    where
144        V: AttributeValue,
145    {
146        self.get_any(key).and_then(|v| v.downcast_ref::<V>())
147    }
148
149    /// Get the value associated with the named [Attribute] as a mutable value of type `V`, or
150    /// `None`.
151    pub fn get_mut<V>(&mut self, key: impl Into<Symbol>) -> Option<&mut V>
152    where
153        V: AttributeValue,
154    {
155        self.get_any_mut(key).and_then(|v| v.downcast_mut::<V>())
156    }
157
158    /// Iterate over each [Attribute] in this set
159    pub fn iter(&self) -> impl Iterator<Item = &Attribute> + '_ {
160        self.0.iter()
161    }
162}
163
164impl Eq for AttributeSet {}
165impl PartialEq for AttributeSet {
166    fn eq(&self, other: &Self) -> bool {
167        if self.0.len() != other.0.len() {
168            return false;
169        }
170
171        for attr in self.0.iter() {
172            if !other.has(attr.name) {
173                return false;
174            }
175
176            let other_value = other.get_any(attr.name);
177            if attr.value() != other_value {
178                return false;
179            }
180        }
181
182        true
183    }
184}
185
186impl core::hash::Hash for AttributeSet {
187    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
188        self.0.len().hash(state);
189
190        for attr in self.0.iter() {
191            attr.hash(state);
192        }
193    }
194}
195
196/// An [Attribute] associates some data with a well-known identifier (name).
197///
198/// Attributes are used for representing metadata that helps guide compilation,
199/// but which is not part of the code itself. For example, `cfg` flags in Rust
200/// are an example of something which you could represent using an [Attribute].
201/// They can also be used to store documentation, source locations, and more.
202#[derive(Debug, Hash)]
203pub struct Attribute {
204    /// The name of this attribute
205    pub name: Symbol,
206    /// The value associated with this attribute
207    pub value: Option<Box<dyn AttributeValue>>,
208    /// This attribute represents an intrinsic property of an operation
209    pub intrinsic: bool,
210}
211impl Clone for Attribute {
212    fn clone(&self) -> Self {
213        Self {
214            name: self.name,
215            value: self.value.as_ref().map(|v| v.clone_value()),
216            intrinsic: self.intrinsic,
217        }
218    }
219}
220impl Attribute {
221    pub fn new(name: impl Into<Symbol>, value: Option<impl AttributeValue>) -> Self {
222        Self {
223            name: name.into(),
224            value: value.map(|v| Box::new(v) as Box<dyn AttributeValue>),
225            intrinsic: false,
226        }
227    }
228
229    pub fn intrinsic(name: impl Into<Symbol>, value: Option<impl AttributeValue>) -> Self {
230        Self {
231            name: name.into(),
232            value: value.map(|v| Box::new(v) as Box<dyn AttributeValue>),
233            intrinsic: true,
234        }
235    }
236
237    pub fn value(&self) -> Option<&dyn AttributeValue> {
238        self.value.as_deref()
239    }
240
241    pub fn value_as<V>(&self) -> Option<&V>
242    where
243        V: AttributeValue,
244    {
245        match self.value.as_deref() {
246            Some(value) => value.downcast_ref::<V>(),
247            None => None,
248        }
249    }
250}
251
252pub trait AttributeValue:
253    Any + fmt::Debug + crate::AttrPrinter + crate::DynPartialEq + crate::DynHash + 'static
254{
255    fn as_any(&self) -> &dyn Any;
256    fn as_any_mut(&mut self) -> &mut dyn Any;
257    fn clone_value(&self) -> Box<dyn AttributeValue>;
258}
259
260impl dyn AttributeValue {
261    pub fn is<T: AttributeValue>(&self) -> bool {
262        self.as_any().is::<T>()
263    }
264
265    pub fn downcast<T: AttributeValue>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
266        if self.is::<T>() {
267            let ptr = Box::into_raw(self);
268            Ok(unsafe { Box::from_raw(ptr.cast()) })
269        } else {
270            Err(self)
271        }
272    }
273
274    pub fn downcast_ref<T: AttributeValue>(&self) -> Option<&T> {
275        self.as_any().downcast_ref::<T>()
276    }
277
278    pub fn downcast_mut<T: AttributeValue>(&mut self) -> Option<&mut T> {
279        self.as_any_mut().downcast_mut::<T>()
280    }
281
282    pub fn as_bool(&self) -> Option<bool> {
283        if let Some(imm) = self.downcast_ref::<Immediate>() {
284            imm.as_bool()
285        } else {
286            self.downcast_ref::<bool>().copied()
287        }
288    }
289
290    pub fn as_u32(&self) -> Option<u32> {
291        if let Some(imm) = self.downcast_ref::<Immediate>() {
292            imm.as_u32()
293        } else {
294            self.downcast_ref::<u32>().copied()
295        }
296    }
297
298    pub fn as_immediate(&self) -> Option<Immediate> {
299        self.downcast_ref::<Immediate>().copied()
300    }
301}
302
303impl core::hash::Hash for dyn AttributeValue {
304    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
305        use crate::DynHash;
306
307        let hashable = self as &dyn DynHash;
308        hashable.dyn_hash(state);
309    }
310}
311
312impl Eq for dyn AttributeValue {}
313impl PartialEq for dyn AttributeValue {
314    fn eq(&self, other: &Self) -> bool {
315        use crate::DynPartialEq;
316
317        let partial_eqable = self as &dyn DynPartialEq;
318        partial_eqable.dyn_eq(other as &dyn DynPartialEq)
319    }
320}
321
322#[derive(Clone)]
323pub struct ArrayAttr<T> {
324    values: Vec<T>,
325}
326impl<T> Default for ArrayAttr<T> {
327    fn default() -> Self {
328        Self {
329            values: Default::default(),
330        }
331    }
332}
333impl<T> FromIterator<T> for ArrayAttr<T> {
334    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
335        Self {
336            values: Vec::<T>::from_iter(iter),
337        }
338    }
339}
340impl<T> ArrayAttr<T> {
341    pub fn is_empty(&self) -> bool {
342        self.values.is_empty()
343    }
344
345    pub fn len(&self) -> usize {
346        self.values.len()
347    }
348
349    pub fn iter(&self) -> core::slice::Iter<'_, T> {
350        self.values.iter()
351    }
352
353    pub fn push(&mut self, value: T) {
354        self.values.push(value);
355    }
356
357    pub fn remove(&mut self, index: usize) -> T {
358        self.values.remove(index)
359    }
360}
361impl<T> ArrayAttr<T>
362where
363    T: Eq,
364{
365    pub fn contains(&self, value: &T) -> bool {
366        self.values.contains(value)
367    }
368}
369impl<T> Eq for ArrayAttr<T> where T: Eq {}
370impl<T> PartialEq for ArrayAttr<T>
371where
372    T: PartialEq,
373{
374    fn eq(&self, other: &Self) -> bool {
375        self.values == other.values
376    }
377}
378impl<T> fmt::Debug for ArrayAttr<T>
379where
380    T: fmt::Debug,
381{
382    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383        f.debug_set().entries(self.values.iter()).finish()
384    }
385}
386impl<T> crate::formatter::PrettyPrint for ArrayAttr<T>
387where
388    T: crate::formatter::PrettyPrint,
389{
390    fn render(&self) -> crate::formatter::Document {
391        use crate::formatter::*;
392
393        let entries = self.values.iter().fold(Document::Empty, |acc, v| match acc {
394            Document::Empty => v.render(),
395            _ => acc + const_text(", ") + v.render(),
396        });
397        if self.values.is_empty() {
398            const_text("[]")
399        } else {
400            const_text("[") + entries + const_text("]")
401        }
402    }
403}
404impl<T> core::hash::Hash for ArrayAttr<T>
405where
406    T: core::hash::Hash,
407{
408    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
409        <Vec<T> as core::hash::Hash>::hash(&self.values, state);
410    }
411}
412impl<T> AttributeValue for ArrayAttr<T>
413where
414    T: fmt::Debug + crate::formatter::PrettyPrint + Clone + Eq + core::hash::Hash + 'static,
415{
416    #[inline(always)]
417    fn as_any(&self) -> &dyn Any {
418        self as &dyn Any
419    }
420
421    #[inline(always)]
422    fn as_any_mut(&mut self) -> &mut dyn Any {
423        self as &mut dyn Any
424    }
425
426    #[inline]
427    fn clone_value(&self) -> Box<dyn AttributeValue> {
428        Box::new(self.clone())
429    }
430}
431
432#[derive(Clone)]
433pub struct SetAttr<K> {
434    values: Vec<K>,
435}
436impl<K> Default for SetAttr<K> {
437    fn default() -> Self {
438        Self {
439            values: Default::default(),
440        }
441    }
442}
443impl<K> SetAttr<K>
444where
445    K: Ord + Clone,
446{
447    pub fn insert(&mut self, key: K) -> bool {
448        match self.values.binary_search_by(|k| key.cmp(k)) {
449            Ok(index) => {
450                self.values[index] = key;
451                false
452            }
453            Err(index) => {
454                self.values.insert(index, key);
455                true
456            }
457        }
458    }
459
460    pub fn contains(&self, key: &K) -> bool {
461        self.values.binary_search_by(|k| key.cmp(k)).is_ok()
462    }
463
464    pub fn iter(&self) -> core::slice::Iter<'_, K> {
465        self.values.iter()
466    }
467
468    pub fn remove<Q>(&mut self, key: &Q) -> Option<K>
469    where
470        K: Borrow<Q>,
471        Q: ?Sized + Ord,
472    {
473        match self.values.binary_search_by(|k| key.cmp(k.borrow())) {
474            Ok(index) => Some(self.values.remove(index)),
475            Err(_) => None,
476        }
477    }
478}
479impl<K> Eq for SetAttr<K> where K: Eq {}
480impl<K> PartialEq for SetAttr<K>
481where
482    K: PartialEq,
483{
484    fn eq(&self, other: &Self) -> bool {
485        self.values == other.values
486    }
487}
488impl<K> fmt::Debug for SetAttr<K>
489where
490    K: fmt::Debug,
491{
492    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493        f.debug_set().entries(self.values.iter()).finish()
494    }
495}
496impl<K> crate::formatter::PrettyPrint for SetAttr<K>
497where
498    K: crate::formatter::PrettyPrint,
499{
500    fn render(&self) -> crate::formatter::Document {
501        use crate::formatter::*;
502
503        let entries = self.values.iter().fold(Document::Empty, |acc, k| match acc {
504            Document::Empty => k.render(),
505            _ => acc + const_text(", ") + k.render(),
506        });
507        if self.values.is_empty() {
508            const_text("{}")
509        } else {
510            const_text("{") + entries + const_text("}")
511        }
512    }
513}
514impl<K> core::hash::Hash for SetAttr<K>
515where
516    K: core::hash::Hash,
517{
518    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
519        <Vec<K> as core::hash::Hash>::hash(&self.values, state);
520    }
521}
522impl<K> AttributeValue for SetAttr<K>
523where
524    K: fmt::Debug + crate::formatter::PrettyPrint + Clone + Eq + core::hash::Hash + 'static,
525{
526    #[inline(always)]
527    fn as_any(&self) -> &dyn Any {
528        self as &dyn Any
529    }
530
531    #[inline(always)]
532    fn as_any_mut(&mut self) -> &mut dyn Any {
533        self as &mut dyn Any
534    }
535
536    #[inline]
537    fn clone_value(&self) -> Box<dyn AttributeValue> {
538        Box::new(self.clone())
539    }
540}
541
542#[derive(Clone)]
543pub struct DictAttr<K, V> {
544    values: Vec<(K, V)>,
545}
546impl<K, V> Default for DictAttr<K, V> {
547    fn default() -> Self {
548        Self { values: vec![] }
549    }
550}
551impl<K, V> DictAttr<K, V>
552where
553    K: Ord,
554    V: Clone,
555{
556    pub fn insert(&mut self, key: K, value: V) {
557        match self.values.binary_search_by(|(k, _)| key.cmp(k)) {
558            Ok(index) => {
559                self.values[index].1 = value;
560            }
561            Err(index) => {
562                self.values.insert(index, (key, value));
563            }
564        }
565    }
566
567    pub fn contains_key<Q>(&self, key: &Q) -> bool
568    where
569        K: Borrow<Q>,
570        Q: ?Sized + Ord,
571    {
572        self.values.binary_search_by(|(k, _)| key.cmp(k.borrow())).is_ok()
573    }
574
575    pub fn get<Q>(&self, key: &Q) -> Option<&V>
576    where
577        K: Borrow<Q>,
578        Q: ?Sized + Ord,
579    {
580        match self.values.binary_search_by(|(k, _)| key.cmp(k.borrow())) {
581            Ok(index) => Some(&self.values[index].1),
582            Err(_) => None,
583        }
584    }
585
586    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
587    where
588        K: Borrow<Q>,
589        Q: ?Sized + Ord,
590    {
591        match self.values.binary_search_by(|(k, _)| key.cmp(k.borrow())) {
592            Ok(index) => Some(self.values.remove(index).1),
593            Err(_) => None,
594        }
595    }
596
597    pub fn iter(&self) -> core::slice::Iter<'_, (K, V)> {
598        self.values.iter()
599    }
600}
601impl<K, V> Eq for DictAttr<K, V>
602where
603    K: Eq,
604    V: Eq,
605{
606}
607impl<K, V> PartialEq for DictAttr<K, V>
608where
609    K: PartialEq,
610    V: PartialEq,
611{
612    fn eq(&self, other: &Self) -> bool {
613        self.values == other.values
614    }
615}
616impl<K, V> fmt::Debug for DictAttr<K, V>
617where
618    K: fmt::Debug,
619    V: fmt::Debug,
620{
621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622        f.debug_map()
623            .entries(self.values.iter().map(|entry| (&entry.0, &entry.1)))
624            .finish()
625    }
626}
627impl<K, V> crate::formatter::PrettyPrint for DictAttr<K, V>
628where
629    K: crate::formatter::PrettyPrint,
630    V: crate::formatter::PrettyPrint,
631{
632    fn render(&self) -> crate::formatter::Document {
633        use crate::formatter::*;
634
635        let entries = self.values.iter().fold(Document::Empty, |acc, (k, v)| match acc {
636            Document::Empty => k.render() + const_text(" = ") + v.render(),
637            _ => acc + const_text(", ") + k.render() + const_text(" = ") + v.render(),
638        });
639        if self.values.is_empty() {
640            const_text("{}")
641        } else {
642            const_text("{") + entries + const_text("}")
643        }
644    }
645}
646impl<K, V> core::hash::Hash for DictAttr<K, V>
647where
648    K: core::hash::Hash,
649    V: core::hash::Hash,
650{
651    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
652        <Vec<(K, V)> as core::hash::Hash>::hash(&self.values, state);
653    }
654}
655impl<K, V> AttributeValue for DictAttr<K, V>
656where
657    K: fmt::Debug + crate::formatter::PrettyPrint + Clone + Eq + core::hash::Hash + 'static,
658    V: fmt::Debug + crate::formatter::PrettyPrint + Clone + Eq + core::hash::Hash + 'static,
659{
660    #[inline(always)]
661    fn as_any(&self) -> &dyn Any {
662        self as &dyn Any
663    }
664
665    #[inline(always)]
666    fn as_any_mut(&mut self) -> &mut dyn Any {
667        self as &mut dyn Any
668    }
669
670    #[inline]
671    fn clone_value(&self) -> Box<dyn AttributeValue> {
672        Box::new(self.clone())
673    }
674}
675
676#[macro_export]
677macro_rules! define_attr_type {
678    ($T:ty) => {
679        impl $crate::AttributeValue for $T {
680            #[inline(always)]
681            fn as_any(&self) -> &dyn core::any::Any {
682                self as &dyn core::any::Any
683            }
684
685            #[inline(always)]
686            fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
687                self as &mut dyn core::any::Any
688            }
689
690            #[inline]
691            fn clone_value(&self) -> ::alloc::boxed::Box<dyn $crate::AttributeValue> {
692                ::alloc::boxed::Box::new(self.clone())
693            }
694        }
695    };
696}
697
698define_attr_type!(bool);
699define_attr_type!(u8);
700define_attr_type!(i8);
701define_attr_type!(u16);
702define_attr_type!(i16);
703define_attr_type!(u32);
704define_attr_type!(core::num::NonZeroU32);
705define_attr_type!(i32);
706define_attr_type!(u64);
707define_attr_type!(i64);
708define_attr_type!(usize);
709define_attr_type!(isize);
710define_attr_type!(Symbol);
711define_attr_type!(super::Immediate);
712define_attr_type!(super::Type);