circomspect_program_structure/intermediate_representation/
variable_meta.rs1use std::fmt;
2use std::collections::HashSet;
3
4use super::ir::{AccessType, Meta, VariableName};
5
6#[derive(Clone, Hash, PartialEq, Eq)]
8pub struct VariableUse {
9 meta: Meta,
10 name: VariableName,
11 access: Vec<AccessType>,
12}
13
14impl VariableUse {
15 pub fn new(meta: &Meta, name: &VariableName, access: &[AccessType]) -> VariableUse {
16 VariableUse { meta: meta.clone(), name: name.clone(), access: access.to_owned() }
17 }
18
19 pub fn meta(&self) -> &Meta {
20 &self.meta
21 }
22
23 pub fn name(&self) -> &VariableName {
24 &self.name
25 }
26
27 pub fn access(&self) -> &Vec<AccessType> {
28 &self.access
29 }
30}
31
32impl fmt::Display for VariableUse {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 write!(f, "{}", self.name)?;
35 for access in &self.access {
36 write!(f, "{access}")?;
37 }
38 Ok(())
39 }
40}
41
42pub type VariableUses = HashSet<VariableUse>;
43
44pub trait VariableMeta {
45 fn cache_variable_use(&mut self);
50
51 #[must_use]
53 fn locals_read(&self) -> &VariableUses;
54
55 #[must_use]
57 fn locals_written(&self) -> &VariableUses;
58
59 #[must_use]
62 fn signals_read(&self) -> &VariableUses;
63
64 #[must_use]
67 fn signals_written(&self) -> &VariableUses;
68
69 #[must_use]
72 fn components_read(&self) -> &VariableUses;
73
74 #[must_use]
78 fn components_written(&self) -> &VariableUses;
79
80 #[must_use]
83 fn variables_read<'a>(&'a self) -> Box<dyn Iterator<Item = &'a VariableUse> + 'a> {
84 let locals_read = self.locals_read().iter();
85 let signals_read = self.signals_read().iter();
86 let components_read = self.components_read().iter();
87 Box::new(locals_read.chain(signals_read).chain(components_read))
88 }
89
90 #[must_use]
93 fn variables_written<'a>(&'a self) -> Box<dyn Iterator<Item = &'a VariableUse> + 'a> {
94 let locals_written = self.locals_written().iter();
95 let signals_written = self.signals_written().iter();
96 let components_written = self.components_written().iter();
97 Box::new(locals_written.chain(signals_written).chain(components_written))
98 }
99
100 #[must_use]
102 fn variables_used<'a>(&'a self) -> Box<dyn Iterator<Item = &'a VariableUse> + 'a> {
103 Box::new(self.variables_read().chain(self.variables_written()))
104 }
105}
106
107#[derive(Default, Clone)]
108pub struct VariableKnowledge {
109 locals_read: Option<VariableUses>,
110 locals_written: Option<VariableUses>,
111 signals_read: Option<VariableUses>,
112 signals_written: Option<VariableUses>,
113 components_read: Option<VariableUses>,
114 components_written: Option<VariableUses>,
115}
116
117impl VariableKnowledge {
118 #[must_use]
119 pub fn new() -> VariableKnowledge {
120 VariableKnowledge::default()
121 }
122
123 pub fn set_locals_read(&mut self, uses: &VariableUses) -> &mut VariableKnowledge {
124 self.locals_read = Some(uses.clone());
125 self
126 }
127
128 pub fn set_locals_written(&mut self, uses: &VariableUses) -> &mut VariableKnowledge {
129 self.locals_written = Some(uses.clone());
130 self
131 }
132
133 pub fn set_signals_read(&mut self, uses: &VariableUses) -> &mut VariableKnowledge {
134 self.signals_read = Some(uses.clone());
135 self
136 }
137
138 pub fn set_signals_written(&mut self, uses: &VariableUses) -> &mut VariableKnowledge {
139 self.signals_written = Some(uses.clone());
140 self
141 }
142
143 pub fn set_components_read(&mut self, uses: &VariableUses) -> &mut VariableKnowledge {
144 self.components_read = Some(uses.clone());
145 self
146 }
147
148 pub fn set_components_written(&mut self, uses: &VariableUses) -> &mut VariableKnowledge {
149 self.components_written = Some(uses.clone());
150 self
151 }
152
153 #[must_use]
154 pub fn locals_read(&self) -> &VariableUses {
155 self.locals_read.as_ref().expect("variable knowledge must be initialized before it is read")
156 }
157
158 #[must_use]
159 pub fn locals_written(&self) -> &VariableUses {
160 self.locals_written
161 .as_ref()
162 .expect("variable knowledge must be initialized before it is read")
163 }
164
165 #[must_use]
166 pub fn signals_read(&self) -> &VariableUses {
167 self.signals_read
168 .as_ref()
169 .expect("variable knowledge must be initialized before it is read")
170 }
171
172 #[must_use]
173 pub fn signals_written(&self) -> &VariableUses {
174 self.signals_written
175 .as_ref()
176 .expect("variable knowledge must be initialized before it is read")
177 }
178
179 #[must_use]
180 pub fn components_read(&self) -> &VariableUses {
181 self.components_read
182 .as_ref()
183 .expect("variable knowledge must be initialized before it is read")
184 }
185
186 #[must_use]
187 pub fn components_written(&self) -> &VariableUses {
188 self.components_written
189 .as_ref()
190 .expect("variable knowledge must be initialized before it is read")
191 }
192
193 #[must_use]
194 pub fn variables_read<'a>(&'a self) -> Box<dyn Iterator<Item = &'a VariableUse> + 'a> {
195 let locals_read = self.locals_read().iter();
196 let signals_read = self.signals_read().iter();
197 let components_read = self.components_read().iter();
198 Box::new(locals_read.chain(signals_read).chain(components_read))
199 }
200
201 #[must_use]
202 pub fn variables_written<'a>(&'a self) -> Box<dyn Iterator<Item = &'a VariableUse> + 'a> {
203 let locals_written = self.locals_written().iter();
204 let signals_written = self.signals_written().iter();
205 let components_written = self.components_written().iter();
206 Box::new(locals_written.chain(signals_written).chain(components_written))
207 }
208
209 #[must_use]
210 pub fn variables_used<'a>(&'a self) -> Box<dyn Iterator<Item = &'a VariableUse> + 'a> {
211 let variables_read = self.variables_read();
212 let variables_written = self.variables_written();
213 Box::new(variables_read.chain(variables_written))
214 }
215}