1use crate::closure::LuaClosure;
4use crate::gc::GcRef;
5use crate::string::LuaString;
6use crate::userdata::LuaUserData;
7use std::ffi::c_void;
8
9pub use crate::table::LuaTable;
10
11#[derive(Debug, Clone, Copy)]
13pub enum LuaValue {
14 Nil,
15 Bool(bool),
16 Int(i64),
17 Float(f64),
18 Str(GcRef<LuaString>),
19 Table(GcRef<LuaTable>),
20 Function(LuaClosure),
21 UserData(GcRef<LuaUserData>),
22 LightUserData(*mut c_void),
23 Thread(GcRef<LuaThread>),
24}
25
26impl LuaValue {
27 pub fn type_tag(&self) -> crate::LuaType {
28 use crate::LuaType::*;
29 match self {
30 LuaValue::Nil => Nil,
31 LuaValue::Bool(_) => Boolean,
32 LuaValue::Int(_) => Number,
33 LuaValue::Float(_) => Number,
34 LuaValue::Str(_) => String,
35 LuaValue::Table(_) => Table,
36 LuaValue::Function(_) => Function,
37 LuaValue::UserData(_) => UserData,
38 LuaValue::LightUserData(_) => LightUserData,
39 LuaValue::Thread(_) => Thread,
40 }
41 }
42
43 pub fn type_name(&self) -> &'static str {
44 match self {
45 LuaValue::Nil => "nil",
46 LuaValue::Bool(_) => "boolean",
47 LuaValue::Int(_) => "number",
48 LuaValue::Float(_) => "number",
49 LuaValue::Str(_) => "string",
50 LuaValue::Table(_) => "table",
51 LuaValue::Function(_) => "function",
52 LuaValue::UserData(_) => "userdata",
53 LuaValue::LightUserData(_) => "userdata",
54 LuaValue::Thread(_) => "thread",
55 }
56 }
57
58 pub fn is_nil(&self) -> bool {
59 matches!(self, LuaValue::Nil)
60 }
61 pub fn is_falsy(&self) -> bool {
62 matches!(self, LuaValue::Nil | LuaValue::Bool(false))
63 }
64 pub fn is_truthy(&self) -> bool {
65 !self.is_falsy()
66 }
67 pub fn is_collectable(&self) -> bool {
68 matches!(
69 self,
70 LuaValue::Str(_)
71 | LuaValue::Table(_)
72 | LuaValue::Function(_)
73 | LuaValue::UserData(_)
74 | LuaValue::Thread(_)
75 )
76 }
77
78 pub fn as_int(&self) -> Option<i64> {
79 match self {
80 LuaValue::Int(i) => Some(*i),
81 _ => None,
82 }
83 }
84 pub fn as_float(&self) -> Option<f64> {
85 match self {
86 LuaValue::Float(f) => Some(*f),
87 _ => None,
88 }
89 }
90 pub fn as_string(&self) -> Option<&GcRef<LuaString>> {
91 match self {
92 LuaValue::Str(s) => Some(s),
93 _ => None,
94 }
95 }
96 pub fn as_table(&self) -> Option<&GcRef<LuaTable>> {
97 match self {
98 LuaValue::Table(t) => Some(t),
99 _ => None,
100 }
101 }
102}
103
104impl Default for LuaValue {
105 fn default() -> Self {
106 LuaValue::Nil
107 }
108}
109
110impl PartialEq for LuaValue {
111 fn eq(&self, other: &Self) -> bool {
112 match (self, other) {
113 (LuaValue::Nil, LuaValue::Nil) => true,
114 (LuaValue::Bool(a), LuaValue::Bool(b)) => a == b,
115 (LuaValue::Int(a), LuaValue::Int(b)) => a == b,
116 (LuaValue::Float(a), LuaValue::Float(b)) => a == b,
117 (LuaValue::Str(a), LuaValue::Str(b)) => {
118 GcRef::ptr_eq(a, b) || (a.hash() == b.hash() && a.as_bytes() == b.as_bytes())
119 }
120 (LuaValue::Table(a), LuaValue::Table(b)) => GcRef::ptr_eq(a, b),
121 (LuaValue::Function(a), LuaValue::Function(b)) => closure_eq(a, b),
122 (LuaValue::UserData(a), LuaValue::UserData(b)) => GcRef::ptr_eq(a, b),
123 (LuaValue::LightUserData(a), LuaValue::LightUserData(b)) => a == b,
124 (LuaValue::Thread(a), LuaValue::Thread(b)) => GcRef::ptr_eq(a, b),
125 _ => false,
126 }
127 }
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132pub enum F2Imod {
133 Floor,
134 Ceil,
135 Round,
136}
137
138fn closure_eq(a: &LuaClosure, b: &LuaClosure) -> bool {
142 match (a, b) {
143 (LuaClosure::Lua(x), LuaClosure::Lua(y)) => GcRef::ptr_eq(x, y),
144 (LuaClosure::C(x), LuaClosure::C(y)) => GcRef::ptr_eq(x, y),
145 (LuaClosure::LightC(x), LuaClosure::LightC(y)) => x == y,
146 _ => false,
147 }
148}
149
150#[derive(Debug)]
162pub struct LuaThread {
163 pub id: u64,
164}
165impl LuaThread {
166 pub fn new(id: u64) -> Self {
167 LuaThread { id }
168 }
169 pub fn placeholder() -> Self {
170 LuaThread { id: 0 }
171 }
172}
173
174