calyx_frontend/
attributes.rs1use super::Attribute;
2use crate::InlineAttributes;
3use calyx_utils::{CalyxResult, GPosIdx, WithPos};
4use linked_hash_map::LinkedHashMap;
5use std::convert::TryFrom;
6
7#[derive(Debug, Clone, Default)]
8struct HeapAttrInfo {
10 attrs: LinkedHashMap<Attribute, u64>,
11 span: GPosIdx,
12}
13
14#[derive(Default, Debug, Clone)]
16#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
17pub struct Attributes {
18 inl: InlineAttributes,
20 hinfo: Box<HeapAttrInfo>,
22}
23
24impl TryFrom<Vec<(Attribute, u64)>> for Attributes {
25 type Error = calyx_utils::Error;
26
27 fn try_from(v: Vec<(Attribute, u64)>) -> CalyxResult<Self> {
28 let mut attrs = Attributes::default();
29 for (k, v) in v {
30 if attrs.has(k) {
31 return Err(Self::Error::malformed_structure(format!(
32 "Multiple entries for attribute: {}",
33 k
34 )));
35 }
36 attrs.insert(k, v);
37 }
38 Ok(attrs)
39 }
40}
41
42impl WithPos for Attributes {
43 fn copy_span(&self) -> GPosIdx {
44 self.hinfo.span
45 }
46}
47
48pub trait GetAttributes {
50 fn get_attributes(&self) -> &Attributes;
52
53 fn get_mut_attributes(&mut self) -> &mut Attributes;
55}
56
57impl Attributes {
58 pub fn insert<A>(&mut self, key: A, val: u64)
60 where
61 A: Into<Attribute>,
62 {
63 match key.into() {
64 Attribute::Bool(b) => {
65 assert!(
66 val == 1,
67 "{} is a boolean attribute and can only have a value of 1",
68 b.as_ref(),
69 );
70 self.inl.insert(b);
71 }
72 attr => {
73 self.hinfo.attrs.insert(attr, val);
74 }
75 }
76 }
77
78 pub fn get<A>(&self, key: A) -> Option<u64>
80 where
81 A: Into<Attribute>,
82 {
83 match key.into() {
84 Attribute::Bool(b) => {
85 if self.inl.has(b) {
86 Some(1)
87 } else {
88 None
89 }
90 }
91 attr => self.hinfo.attrs.get(&attr).cloned(),
92 }
93 }
94
95 pub fn has<A>(&self, key: A) -> bool
97 where
98 A: Into<Attribute>,
99 {
100 match key.into() {
101 Attribute::Bool(b) => self.inl.has(b),
102 attr => self.hinfo.attrs.contains_key(&attr),
103 }
104 }
105
106 pub fn is_empty(&self) -> bool {
108 self.inl.is_empty() && self.hinfo.attrs.is_empty()
109 }
110
111 pub fn remove<A>(&mut self, key: A)
113 where
114 A: Into<Attribute>,
115 {
116 match key.into() {
117 Attribute::Bool(b) => {
118 self.inl.remove(b);
119 }
120 attr => {
121 self.hinfo.attrs.remove(&attr);
122 }
123 }
124 }
125
126 pub fn add_span(mut self, span: GPosIdx) -> Self {
128 self.hinfo.span = span;
129 self
130 }
131
132 pub fn to_string_with<F>(&self, sep: &'static str, fmt: F) -> String
133 where
134 F: Fn(String, u64) -> String,
135 {
136 if self.is_empty() {
137 return String::default();
138 }
139
140 self.hinfo
141 .attrs
142 .iter()
143 .map(|(k, v)| fmt(k.to_string(), *v))
144 .chain(self.inl.iter().map(|k| fmt(k.as_ref().to_string(), 1)))
145 .collect::<Vec<_>>()
146 .join(sep)
147 }
148}
149
150#[cfg(feature = "serialize")]
151impl serde::Serialize for HeapAttrInfo {
152 fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
153 where
154 S: serde::Serializer,
155 {
156 ser.collect_map(self.to_owned().attrs.iter())
157 }
158}