circomspect_program_structure/intermediate_representation/
value_meta.rs1use num_bigint::BigInt;
2use std::collections::HashMap;
3use std::fmt;
4
5use crate::constants::UsefulConstants;
6
7use super::ir::VariableName;
8
9#[derive(Clone)]
10pub struct ValueEnvironment {
11 constants: UsefulConstants,
12 reduces_to: HashMap<VariableName, ValueReduction>,
13}
14
15impl ValueEnvironment {
16 pub fn new(constants: &UsefulConstants) -> ValueEnvironment {
17 ValueEnvironment { constants: constants.clone(), reduces_to: HashMap::new() }
18 }
19
20 pub fn add_variable(&mut self, name: &VariableName, value: &ValueReduction) -> bool {
27 if let Some(previous) = self.reduces_to.insert(name.clone(), value.clone()) {
28 assert_eq!(previous, *value);
29 false
30 } else {
31 true
32 }
33 }
34
35 #[must_use]
36 pub fn get_variable(&self, name: &VariableName) -> Option<&ValueReduction> {
37 self.reduces_to.get(name)
38 }
39
40 pub fn prime(&self) -> &BigInt {
42 self.constants.prime()
43 }
44}
45
46pub trait ValueMeta {
47 fn propagate_values(&mut self, env: &mut ValueEnvironment) -> bool;
50
51 #[must_use]
53 fn is_constant(&self) -> bool;
54
55 #[must_use]
57 fn is_boolean(&self) -> bool;
58
59 #[must_use]
61 fn is_field_element(&self) -> bool;
62
63 #[must_use]
65 fn value(&self) -> Option<&ValueReduction>;
66}
67
68#[derive(Debug, Clone, Hash, PartialEq, Eq)]
69pub enum ValueReduction {
70 Boolean { value: bool },
71 FieldElement { value: BigInt },
72}
73
74impl fmt::Display for ValueReduction {
75 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
76 use ValueReduction::*;
77 match self {
78 Boolean { value } => write!(f, "{value}"),
79 FieldElement { value } => write!(f, "{value}"),
80 }
81 }
82}
83
84#[derive(Default, Clone)]
85pub struct ValueKnowledge {
86 reduces_to: Option<ValueReduction>,
87}
88
89impl ValueKnowledge {
90 #[must_use]
91 pub fn new() -> ValueKnowledge {
92 ValueKnowledge::default()
93 }
94
95 #[must_use]
97 pub fn set_reduces_to(&mut self, reduces_to: ValueReduction) -> bool {
98 let result = self.reduces_to.is_none();
99 self.reduces_to = Some(reduces_to);
100 result
101 }
102
103 #[must_use]
105 pub fn get_reduces_to(&self) -> Option<&ValueReduction> {
106 self.reduces_to.as_ref()
107 }
108
109 #[must_use]
111 pub fn is_constant(&self) -> bool {
112 self.reduces_to.is_some()
113 }
114
115 #[must_use]
117 pub fn is_boolean(&self) -> bool {
118 use ValueReduction::*;
119 matches!(self.reduces_to, Some(Boolean { .. }))
120 }
121
122 #[must_use]
124 pub fn is_field_element(&self) -> bool {
125 use ValueReduction::*;
126 matches!(self.reduces_to, Some(FieldElement { .. }))
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use num_bigint::BigInt;
133
134 use crate::ir::value_meta::ValueReduction;
135
136 use super::ValueKnowledge;
137
138 #[test]
139 fn test_value_knowledge() {
140 let mut value = ValueKnowledge::new();
141 assert!(matches!(value.get_reduces_to(), None));
142
143 let number = ValueReduction::FieldElement { value: BigInt::from(1) };
144 assert!(value.set_reduces_to(number));
145 assert!(matches!(value.get_reduces_to(), Some(ValueReduction::FieldElement { .. })));
146 assert!(value.is_field_element());
147 assert!(!value.is_boolean());
148
149 let boolean = ValueReduction::Boolean { value: true };
150 assert!(!value.set_reduces_to(boolean));
151 assert!(matches!(value.get_reduces_to(), Some(ValueReduction::Boolean { .. })));
152 assert!(!value.is_field_element());
153 assert!(value.is_boolean());
154 }
155}