jetcrab\vm/
value.rs

1use crate::vm::handle::{ArrayHandle, FunctionHandle, ObjectHandle};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6pub enum Value {
7    Number(f64),
8    String(String),
9    Boolean(bool),
10    Object(ObjectHandle),
11    Array(ArrayHandle),
12    Function(FunctionHandle),
13    Null,
14    Undefined,
15}
16
17impl Value {
18    pub fn is_primitive(&self) -> bool {
19        matches!(
20            self,
21            Value::Number(_)
22                | Value::String(_)
23                | Value::Boolean(_)
24                | Value::Null
25                | Value::Undefined
26        )
27    }
28
29    pub fn as_number(&self) -> Option<f64> {
30        if let Value::Number(n) = self {
31            Some(*n)
32        } else {
33            None
34        }
35    }
36
37    pub fn as_bool(&self) -> Option<bool> {
38        if let Value::Boolean(b) = self {
39            Some(*b)
40        } else {
41            None
42        }
43    }
44
45    pub fn as_string(&self) -> Option<&str> {
46        if let Value::String(s) = self {
47            Some(s)
48        } else {
49            None
50        }
51    }
52
53    pub fn to_number(&self) -> f64 {
54        match self {
55            Value::Number(n) => *n,
56            Value::Boolean(b) => {
57                if *b {
58                    1.0
59                } else {
60                    0.0
61                }
62            }
63            Value::String(s) => s.parse::<f64>().unwrap_or(f64::NAN),
64            Value::Null => 0.0,
65            Value::Undefined => f64::NAN,
66            _ => f64::NAN,
67        }
68    }
69
70    pub fn to_string_value(&self) -> String {
71        match self {
72            Value::Number(n) => n.to_string(),
73            Value::Boolean(b) => b.to_string(),
74            Value::String(s) => s.clone(),
75            Value::Null => "null".to_string(),
76            Value::Undefined => "undefined".to_string(),
77            Value::Object(_) => "[object Object]".to_string(),
78            Value::Array(_) => "[object Array]".to_string(),
79            Value::Function(_) => "[function]".to_string(),
80        }
81    }
82
83    pub fn to_boolean(&self) -> bool {
84        match self {
85            Value::Boolean(b) => *b,
86            Value::Number(n) => *n != 0.0 && !n.is_nan(),
87            Value::String(s) => !s.is_empty(),
88            Value::Null | Value::Undefined => false,
89            _ => true,
90        }
91    }
92
93    pub fn is_truthy(&self) -> bool {
94        self.to_boolean()
95    }
96
97    pub fn is_falsy(&self) -> bool {
98        !self.to_boolean()
99    }
100}
101
102impl fmt::Display for Value {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        write!(f, "{}", self.to_string_value())
105    }
106}
107
108impl From<f64> for Value {
109    fn from(n: f64) -> Self {
110        Value::Number(n)
111    }
112}
113
114impl From<String> for Value {
115    fn from(s: String) -> Self {
116        Value::String(s)
117    }
118}
119
120impl From<bool> for Value {
121    fn from(b: bool) -> Self {
122        Value::Boolean(b)
123    }
124}