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#[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 pub const fn new() -> Self {
68 Self(Vec::new())
69 }
70
71 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 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 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 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 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 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 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 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 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#[derive(Debug, Hash)]
203pub struct Attribute {
204 pub name: Symbol,
206 pub value: Option<Box<dyn AttributeValue>>,
208 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);