lua_ir/
luaval.rs

1use crate::number::LuaNumber;
2use crate::FloatType;
3use crate::IntType;
4use crate::LuaFunction;
5use crate::LuaString;
6use crate::LuaTable;
7use crate::LuaThread;
8use crate::RuntimeError;
9
10use std::cell::RefCell;
11use std::rc::Rc;
12
13/// for local variables and upvalues.
14#[derive(Debug, Clone)]
15pub enum RefOrValue {
16    Ref(Rc<RefCell<LuaValue>>),
17    Value(LuaValue),
18}
19impl Default for RefOrValue {
20    fn default() -> Self {
21        RefOrValue::Value(LuaValue::Nil)
22    }
23}
24
25#[derive(Debug, Clone)]
26pub enum LuaValue {
27    Nil,
28    Boolean(bool),
29    Number(LuaNumber),
30    String(LuaString),
31    Table(Rc<RefCell<LuaTable>>),
32    Function(Rc<RefCell<LuaFunction>>),
33    UserData(Rc<RefCell<LuaUserData>>),
34    Thread(Rc<RefCell<LuaThread>>),
35}
36impl std::hash::Hash for LuaValue {
37    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
38        std::mem::discriminant(self).hash(state);
39
40        match self {
41            LuaValue::Nil => {
42                unreachable!("hash for nil; this should be filtered out");
43            }
44            LuaValue::Boolean(b) => b.hash(state),
45            LuaValue::Number(n) => n.hash(state),
46            LuaValue::String(s) => s.hash(state),
47            LuaValue::Table(t) => Rc::as_ptr(t).hash(state),
48            LuaValue::Function(f) => Rc::as_ptr(f).hash(state),
49            LuaValue::UserData(u) => Rc::as_ptr(u).hash(state),
50            LuaValue::Thread(t) => Rc::as_ptr(t).hash(state),
51        }
52    }
53}
54impl std::cmp::PartialEq for LuaValue {
55    fn eq(&self, other: &Self) -> bool {
56        match (self, other) {
57            (LuaValue::Nil, LuaValue::Nil) => true,
58            (LuaValue::Boolean(a), LuaValue::Boolean(b)) => a == b,
59            (LuaValue::Number(a), LuaValue::Number(b)) => a == b,
60            (LuaValue::String(a), LuaValue::String(b)) => a == b,
61            (LuaValue::Table(a), LuaValue::Table(b)) => Rc::ptr_eq(a, b),
62            (LuaValue::Function(a), LuaValue::Function(b)) => Rc::ptr_eq(a, b),
63            (LuaValue::UserData(a), LuaValue::UserData(b)) => Rc::ptr_eq(a, b),
64            (LuaValue::Thread(a), LuaValue::Thread(b)) => Rc::ptr_eq(a, b),
65            _ => false,
66        }
67    }
68}
69impl std::cmp::Eq for LuaValue {}
70
71impl std::fmt::Display for LuaValue {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        match self {
74            LuaValue::Nil => write!(f, "nil"),
75            LuaValue::Boolean(b) => write!(f, "{}", b),
76            LuaValue::Number(n) => write!(f, "{}", n),
77            LuaValue::String(s) => write!(f, "{}", s),
78            LuaValue::Table(t) => {
79                write!(f, "table: {:p}", Rc::as_ptr(t))
80            }
81            LuaValue::Function(func) => write!(f, "function: {:p}", Rc::as_ptr(func)),
82            LuaValue::UserData(userdata) => write!(f, "userdata: {:p}", Rc::as_ptr(userdata)),
83            LuaValue::Thread(thread) => write!(f, "thread: {:p}", Rc::as_ptr(thread)),
84        }
85    }
86}
87
88impl LuaValue {
89    /// construct a LuaString from a static string.
90    pub fn from_static_str(s: &'static str) -> Self {
91        LuaValue::String(LuaString::from_static_str(s))
92    }
93    /// construct a LuaString from a static u8 slice.
94    pub fn from_static_slice(s: &'static [u8]) -> Self {
95        LuaValue::String(LuaString::from_static(s))
96    }
97
98    /// get the type of this value as a string.
99    pub fn type_str(&self) -> &'static str {
100        match self {
101            LuaValue::Nil => "nil",
102            LuaValue::Boolean(_) => "boolean",
103            LuaValue::Number(_) => "number",
104            LuaValue::String(_) => "string",
105            LuaValue::Table(_) => "table",
106            LuaValue::Function(_) => "function",
107            LuaValue::Thread(_) => "thread",
108            LuaValue::UserData(_) => "userdata",
109        }
110    }
111
112    /// convert this value to a boolean.
113    pub fn to_bool(&self) -> bool {
114        match self {
115            LuaValue::Nil | LuaValue::Boolean(false) => false,
116            _ => true,
117        }
118    }
119
120    /// try convert this value to a number.
121    pub fn try_to_int(&self) -> Result<IntType, RuntimeError> {
122        self.try_to_number()?.try_to_int()
123    }
124    /// try convert this value to a number.
125    pub fn try_to_number(&self) -> Result<LuaNumber, RuntimeError> {
126        match self {
127            LuaValue::Number(n) => Ok(*n),
128            LuaValue::String(s) => s.try_to_number(),
129            _ => Err(RuntimeError::Expected("number", Some(self.type_str()))),
130        }
131    }
132
133    pub fn is_nil(&self) -> bool {
134        match self {
135            LuaValue::Nil => true,
136            _ => false,
137        }
138    }
139    pub fn is_nan(&self) -> bool {
140        match self {
141            LuaValue::Number(n) => n.is_nan(),
142            _ => false,
143        }
144    }
145}
146
147impl Default for LuaValue {
148    fn default() -> Self {
149        LuaValue::Nil
150    }
151}
152
153impl From<()> for LuaValue {
154    fn from(_: ()) -> Self {
155        LuaValue::Nil
156    }
157}
158impl From<bool> for LuaValue {
159    fn from(b: bool) -> Self {
160        LuaValue::Boolean(b)
161    }
162}
163impl From<IntType> for LuaValue {
164    fn from(n: IntType) -> Self {
165        LuaValue::Number(LuaNumber::Int(n))
166    }
167}
168impl From<FloatType> for LuaValue {
169    fn from(n: FloatType) -> Self {
170        LuaValue::Number(LuaNumber::Float(n))
171    }
172}
173impl From<LuaNumber> for LuaValue {
174    fn from(n: LuaNumber) -> Self {
175        LuaValue::Number(n)
176    }
177}
178impl From<Vec<u8>> for LuaValue {
179    fn from(v: Vec<u8>) -> Self {
180        LuaValue::String(LuaString::from_vec(v))
181    }
182}
183impl From<String> for LuaValue {
184    fn from(s: String) -> Self {
185        LuaValue::String(LuaString::from_string(s))
186    }
187}
188impl From<&'static str> for LuaValue {
189    fn from(s: &'static str) -> Self {
190        LuaValue::String(LuaString::from_str(s))
191    }
192}
193impl From<&'static [u8]> for LuaValue {
194    fn from(s: &'static [u8]) -> Self {
195        LuaValue::String(LuaString::from_slice(s))
196    }
197}
198impl From<LuaString> for LuaValue {
199    fn from(s: LuaString) -> Self {
200        LuaValue::String(s)
201    }
202}
203impl From<LuaTable> for LuaValue {
204    fn from(t: LuaTable) -> Self {
205        LuaValue::Table(Rc::new(RefCell::new(t)))
206    }
207}
208impl From<LuaFunction> for LuaValue {
209    fn from(f: LuaFunction) -> Self {
210        LuaValue::Function(Rc::new(RefCell::new(f)))
211    }
212}
213impl From<LuaUserData> for LuaValue {
214    fn from(u: LuaUserData) -> Self {
215        LuaValue::UserData(Rc::new(RefCell::new(u)))
216    }
217}
218impl From<LuaThread> for LuaValue {
219    fn from(t: LuaThread) -> Self {
220        LuaValue::Thread(Rc::new(RefCell::new(t)))
221    }
222}
223
224#[derive(Debug, Clone)]
225pub struct LuaUserData {}