use crate::closure::LuaClosure;
use crate::gc::GcRef;
use crate::string::LuaString;
use crate::userdata::LuaUserData;
use std::ffi::c_void;
pub use crate::table::LuaTable;
#[derive(Debug, Clone, Copy)]
pub enum LuaValue {
Nil,
Bool(bool),
Int(i64),
Float(f64),
Str(GcRef<LuaString>),
Table(GcRef<LuaTable>),
Function(LuaClosure),
UserData(GcRef<LuaUserData>),
LightUserData(*mut c_void),
Thread(GcRef<LuaThread>),
}
impl LuaValue {
pub fn type_tag(&self) -> crate::LuaType {
use crate::LuaType::*;
match self {
LuaValue::Nil => Nil,
LuaValue::Bool(_) => Boolean,
LuaValue::Int(_) => Number,
LuaValue::Float(_) => Number,
LuaValue::Str(_) => String,
LuaValue::Table(_) => Table,
LuaValue::Function(_) => Function,
LuaValue::UserData(_) => UserData,
LuaValue::LightUserData(_) => LightUserData,
LuaValue::Thread(_) => Thread,
}
}
pub fn type_name(&self) -> &'static str {
match self {
LuaValue::Nil => "nil",
LuaValue::Bool(_) => "boolean",
LuaValue::Int(_) => "number",
LuaValue::Float(_) => "number",
LuaValue::Str(_) => "string",
LuaValue::Table(_) => "table",
LuaValue::Function(_) => "function",
LuaValue::UserData(_) => "userdata",
LuaValue::LightUserData(_) => "userdata",
LuaValue::Thread(_) => "thread",
}
}
pub fn is_nil(&self) -> bool { matches!(self, LuaValue::Nil) }
pub fn is_falsy(&self) -> bool { matches!(self, LuaValue::Nil | LuaValue::Bool(false)) }
pub fn is_truthy(&self) -> bool { !self.is_falsy() }
pub fn is_collectable(&self) -> bool {
matches!(self,
LuaValue::Str(_) | LuaValue::Table(_) | LuaValue::Function(_) |
LuaValue::UserData(_) | LuaValue::Thread(_))
}
pub fn as_int(&self) -> Option<i64> {
match self { LuaValue::Int(i) => Some(*i), _ => None }
}
pub fn as_float(&self) -> Option<f64> {
match self { LuaValue::Float(f) => Some(*f), _ => None }
}
pub fn as_string(&self) -> Option<&GcRef<LuaString>> {
match self { LuaValue::Str(s) => Some(s), _ => None }
}
pub fn as_table(&self) -> Option<&GcRef<LuaTable>> {
match self { LuaValue::Table(t) => Some(t), _ => None }
}
}
impl Default for LuaValue {
fn default() -> Self { LuaValue::Nil }
}
impl PartialEq for LuaValue {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(LuaValue::Nil, LuaValue::Nil) => true,
(LuaValue::Bool(a), LuaValue::Bool(b)) => a == b,
(LuaValue::Int(a), LuaValue::Int(b)) => a == b,
(LuaValue::Float(a), LuaValue::Float(b)) => a == b,
(LuaValue::Str(a), LuaValue::Str(b)) => GcRef::ptr_eq(a, b) || a.as_bytes() == b.as_bytes(),
(LuaValue::Table(a), LuaValue::Table(b)) => GcRef::ptr_eq(a, b),
(LuaValue::Function(a), LuaValue::Function(b)) => closure_eq(a, b),
(LuaValue::UserData(a), LuaValue::UserData(b)) => GcRef::ptr_eq(a, b),
(LuaValue::LightUserData(a), LuaValue::LightUserData(b)) => a == b,
(LuaValue::Thread(a), LuaValue::Thread(b)) => GcRef::ptr_eq(a, b),
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum F2Imod {
Floor,
Ceil,
Round,
}
fn closure_eq(a: &LuaClosure, b: &LuaClosure) -> bool {
match (a, b) {
(LuaClosure::Lua(x), LuaClosure::Lua(y)) => GcRef::ptr_eq(x, y),
(LuaClosure::C(x), LuaClosure::C(y)) => GcRef::ptr_eq(x, y),
(LuaClosure::LightC(x), LuaClosure::LightC(y)) => x == y,
_ => false,
}
}
#[derive(Debug)]
pub struct LuaThread {
pub id: u64,
}
impl LuaThread {
pub fn new(id: u64) -> Self { LuaThread { id } }
pub fn placeholder() -> Self { LuaThread { id: 0 } }
}