mck/value/
param_valuation.rs

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        // we order from lowest True (ground value) to greatest False
129        // prefer False, then Unknown, then Dependent, then True
130
131        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        // we order from lowest False (ground value) to greatest True
147        // prefer True, then Unknown, then Dependent, then False
148
149        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}