1use std::ops::Not;
2
3use self::Value::{Known, Unknown};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub enum Value<T> {
8 Known(T),
9 Unknown,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub enum Type {
16 Undefined,
17 Null,
18 Bool,
19 Str,
20 Symbol,
21 Num,
22 Obj,
23}
24
25impl Value<Type> {
26 pub fn casted_to_number_on_add(self) -> bool {
27 match self {
28 Known(Type::Bool) | Known(Type::Null) | Known(Type::Num) | Known(Type::Undefined) => {
29 true
30 }
31 _ => false,
32 }
33 }
34}
35
36pub struct UnknownError;
38
39impl<T> Value<T> {
57 pub fn into_result(self) -> Result<T, UnknownError> {
58 match self {
59 Known(v) => Ok(v),
60 Unknown => Err(UnknownError),
61 }
62 }
63}
64
65impl<T> Value<T> {
66 pub fn is_unknown(&self) -> bool {
68 matches!(*self, Unknown)
69 }
70
71 pub fn is_known(&self) -> bool {
73 matches!(*self, Known(..))
74 }
75}
76
77impl Value<bool> {
78 pub fn and(self, other: Self) -> Self {
79 match self {
80 Known(true) => other,
81 Known(false) => Known(false),
82 Unknown => match other {
83 Known(false) => Known(false),
84 _ => Unknown,
85 },
86 }
87 }
88
89 pub fn or(self, other: Self) -> Self {
90 match self {
91 Known(true) => Known(true),
92 Known(false) => other,
93 Unknown => match other {
94 Known(true) => Known(true),
95 _ => Unknown,
96 },
97 }
98 }
99}
100
101impl Not for Value<bool> {
102 type Output = Self;
103
104 fn not(self) -> Self {
105 match self {
106 Value::Known(b) => Value::Known(!b),
107 Value::Unknown => Value::Unknown,
108 }
109 }
110}
111
112pub trait Merge {
113 fn merge(&mut self, rhs: Self);
114}
115
116impl Merge for Option<Value<Type>> {
117 fn merge(&mut self, rhs: Self) {
118 *self = match (*self, rhs) {
119 (None, None) => None,
120 (None, Some(ty)) | (Some(ty), None) => Some(ty),
121 (Some(ty1), Some(ty2)) if ty1 == ty2 => Some(ty1),
122 _ => Some(Unknown),
123 }
124 }
125}