1use std::{
2 cmp::Ordering,
3 fmt::Display,
4 ops::{BitAnd, BitOr, BitXor, Not},
5};
6
7use serde::{Deserialize, Serialize};
8
9use crate::{misc::Join, value::ThreeValued};
10
11#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
12pub enum KnownParamValuation {
13 False,
14 True,
15 Dependent,
16}
17
18#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
19pub enum ParamValuation {
20 False,
21 True,
22 Dependent,
23 Unknown,
24}
25
26impl Not for ParamValuation {
27 type Output = Self;
28
29 fn not(self) -> Self {
30 match self {
31 ParamValuation::False => ParamValuation::True,
32 ParamValuation::True => ParamValuation::False,
33 ParamValuation::Dependent => ParamValuation::Dependent,
34 ParamValuation::Unknown => ParamValuation::Unknown,
35 }
36 }
37}
38
39impl BitAnd for ParamValuation {
40 type Output = Self;
41
42 fn bitand(self, rhs: Self) -> Self {
43 if self.upward_bitand_ordering(&rhs).is_ge() {
44 self
45 } else {
46 rhs
47 }
48 }
49}
50
51impl BitOr for ParamValuation {
52 type Output = Self;
53
54 fn bitor(self, rhs: Self) -> Self {
55 if self.upward_bitor_ordering(&rhs).is_ge() {
56 self
57 } else {
58 rhs
59 }
60 }
61}
62
63impl BitXor for ParamValuation {
64 type Output = Self;
65
66 fn bitxor(self, rhs: Self) -> Self::Output {
67 match (self, rhs) {
68 (ParamValuation::Dependent, _) | (_, ParamValuation::Dependent) => {
69 ParamValuation::Dependent
70 }
71 (ParamValuation::Unknown, _) | (_, ParamValuation::Unknown) => ParamValuation::Unknown,
72 (ParamValuation::False, ParamValuation::False)
73 | (ParamValuation::True, ParamValuation::True) => ParamValuation::True,
74 (ParamValuation::False, ParamValuation::True)
75 | (ParamValuation::True, ParamValuation::False) => ParamValuation::False,
76 }
77 }
78}
79
80impl ParamValuation {
81 pub fn from_bool(value: bool) -> Self {
82 if value {
83 Self::True
84 } else {
85 Self::False
86 }
87 }
88
89 pub fn from_three_valued(three_valued: ThreeValued) -> Self {
90 match three_valued {
91 ThreeValued::False => ParamValuation::False,
92 ThreeValued::True => ParamValuation::True,
93 ThreeValued::Unknown => ParamValuation::Unknown,
94 }
95 }
96
97 pub fn try_into_bool(self) -> Option<bool> {
98 match self {
99 ParamValuation::False => Some(false),
100 ParamValuation::True => Some(true),
101 ParamValuation::Dependent | ParamValuation::Unknown => None,
102 }
103 }
104
105 pub fn is_unknown(&self) -> bool {
106 matches!(self, ParamValuation::Unknown)
107 }
108
109 pub fn is_known(&self) -> bool {
110 !self.is_unknown()
111 }
112
113 pub fn can_be_true(&self) -> bool {
114 matches!(
115 self,
116 ParamValuation::True | ParamValuation::Dependent | ParamValuation::Unknown
117 )
118 }
119
120 pub fn can_be_false(&self) -> bool {
121 matches!(
122 self,
123 ParamValuation::False | ParamValuation::Dependent | ParamValuation::Unknown
124 )
125 }
126
127 pub fn upward_bitand_ordering(self, rhs: &Self) -> Ordering {
128 match (self, rhs) {
132 (ParamValuation::False, ParamValuation::False) => Ordering::Equal,
133 (ParamValuation::False, _) => Ordering::Greater,
134 (_, ParamValuation::False) => Ordering::Less,
135 (ParamValuation::Unknown, ParamValuation::Unknown) => Ordering::Equal,
136 (ParamValuation::Unknown, _) => Ordering::Greater,
137 (_, ParamValuation::Unknown) => Ordering::Less,
138 (ParamValuation::Dependent, ParamValuation::Dependent) => Ordering::Equal,
139 (ParamValuation::Dependent, ParamValuation::True) => Ordering::Greater,
140 (ParamValuation::True, ParamValuation::Dependent) => Ordering::Less,
141 (ParamValuation::True, ParamValuation::True) => Ordering::Equal,
142 }
143 }
144
145 pub fn upward_bitor_ordering(self, rhs: &Self) -> Ordering {
146 match (self, rhs) {
150 (ParamValuation::True, ParamValuation::True) => Ordering::Equal,
151 (ParamValuation::True, _) => Ordering::Greater,
152 (_, ParamValuation::True) => Ordering::Less,
153 (ParamValuation::Unknown, ParamValuation::Unknown) => Ordering::Equal,
154 (ParamValuation::Unknown, _) => Ordering::Greater,
155 (_, ParamValuation::Unknown) => Ordering::Less,
156 (ParamValuation::Dependent, ParamValuation::Dependent) => Ordering::Equal,
157 (ParamValuation::Dependent, ParamValuation::False) => Ordering::Greater,
158 (ParamValuation::False, ParamValuation::Dependent) => Ordering::Less,
159 (ParamValuation::False, ParamValuation::False) => Ordering::Equal,
160 }
161 }
162}
163
164impl Join for ParamValuation {
165 fn join(self, other: &Self) -> Self {
166 match (self, other) {
167 (ParamValuation::Dependent, _) | (_, ParamValuation::Dependent) => {
168 ParamValuation::Dependent
169 }
170 (ParamValuation::Unknown, _) | (_, ParamValuation::Unknown) => ParamValuation::Unknown,
171 (ParamValuation::False, ParamValuation::True)
172 | (ParamValuation::True, ParamValuation::False) => ParamValuation::Unknown,
173 (ParamValuation::False, ParamValuation::False) => ParamValuation::False,
174 (ParamValuation::True, ParamValuation::True) => ParamValuation::True,
175 }
176 }
177}
178
179impl Display for ParamValuation {
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 let str = match self {
182 ParamValuation::False => "false",
183 ParamValuation::True => "true",
184 ParamValuation::Dependent => "dependent",
185 ParamValuation::Unknown => "unknown",
186 };
187 write!(f, "{}", str)
188 }
189}