swc_ecma_utils/
value.rs

1use std::ops::Not;
2
3use self::Value::{Known, Unknown};
4
5/// Runtime value.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub enum Value<T> {
8    Known(T),
9    /// Not determined at compile time.`
10    Unknown,
11}
12
13/// Type of value.
14#[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
36/// Value could not be determined
37pub struct UnknownError;
38
39// impl<T> Try for Value<T> {
40//     type Ok = T;
41//     type Error = UnknownError;
42//     fn from_ok(t: T) -> Self {
43//         Known(t)
44//     }
45//     fn from_error(_: UnknownError) -> Self {
46//         Unknown
47//     }
48//     fn into_result(self) -> Result<T, UnknownError> {
49//         match self {
50//             Known(t) => Ok(t),
51//             Unknown => Err(UnknownError),
52//         }
53//     }
54// }
55
56impl<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    /// Returns true if the value is not known.
67    pub fn is_unknown(&self) -> bool {
68        matches!(*self, Unknown)
69    }
70
71    /// Returns true if the value is known.
72    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}