use std::{cell::RefCell, rc::Rc};
use hashbrown::HashMap;
use crate::{
error::ErrorTypes,
function::{Closure, FunctionObject, NativeObject},
lua::Lua,
table::Table,
userdata::UserData,
};
pub enum Value {
Nil,
Integer(i64),
Number(f64),
Bool(bool),
Infinity(bool),
String(Box<String>),
Table(Rc<RefCell<Table>>),
Function(Rc<FunctionObject>), Closure(Rc<Closure>),
NativeFunction(Rc<NativeObject>),
UserData(Rc<dyn UserData>),
}
pub enum ReferneceStore {
Table(HashMap<Value, Value>),
}
pub struct Reference<T> {
pub value: Rc<T>,
pub id: usize,
}
impl std::fmt::Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::Integer(i) => write!(f, "{}", i),
Value::Number(n) => write!(f, "{}", n),
Value::Bool(b) => write!(f, "{}", b),
Value::Nil => write!(f, "nil"),
Value::String(s) => write!(f, "\"{}\"", s),
Value::Infinity(_) => write!(f, "inf"),
Value::NativeFunction(_) => write!(f, "native_function"),
Value::Closure(c) => write!(f, "(clojure= {})", c.function),
Value::Function(ff) => write!(f, "{}", ff),
Value::Table(t) => write!(f, "{}", t.borrow().to_string()),
Value::UserData(u) => write!(f, "{}", u.to_string()),
}
}
}
impl core::fmt::Debug for Value {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self)
}
}
impl Value {
pub fn to_error(&self) -> ErrorTypes {
match self {
Value::Integer(_) => ErrorTypes::Integer,
Value::Number(_) => ErrorTypes::Number,
Value::Bool(_) => ErrorTypes::Bool,
Value::Nil => ErrorTypes::Nil,
Value::String(_) => ErrorTypes::String,
Value::Infinity(_) => ErrorTypes::Infinity,
Value::NativeFunction(_) => ErrorTypes::NativeFunction,
Value::Function { .. } => ErrorTypes::Function,
Value::Closure(_) => ErrorTypes::Closure,
Value::Table(_) => ErrorTypes::Table,
Value::UserData(_) => ErrorTypes::UserData,
}
}
pub fn force_to_int(&mut self, n: i64) {
*self = Value::Integer(n);
}
}
impl Clone for Value {
fn clone(&self) -> Self {
match self {
Value::Integer(i) => Value::Integer(*i),
Value::Number(n) => Value::Number(*n),
Value::Bool(b) => Value::Bool(*b),
Value::Nil => Value::Nil,
Value::String(s) => Value::String(s.clone()),
Value::Infinity(b) => Value::Infinity(*b),
Value::NativeFunction(f) => Value::NativeFunction(f.clone()),
Value::Function(r) => Value::Function(Rc::clone(r)),
Value::Closure(c) => Value::Closure(Rc::clone(c)),
Value::Table(t) => Value::Table(Rc::clone(t)),
Value::UserData(u) => Value::UserData(Rc::clone(u)),
}
}
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Integer(i), Value::Integer(j)) => i == j,
(Value::Number(i), Value::Number(j)) => i == j,
(Value::Bool(i), Value::Bool(j)) => i == j,
(Value::Nil, Value::Nil) => true,
(Value::String(i), Value::String(j)) => i == j,
(Value::Infinity(i), Value::Infinity(j)) => i == j,
(Value::NativeFunction(i), Value::NativeFunction(j)) => {
i.function as *const fn(&mut Lua, Vec<Value>) -> Value
== j.function as *const fn(&mut Lua, Vec<Value>) -> Value
}
(Value::Function(i), Value::Function(j)) => Rc::ptr_eq(i, j),
(Value::Table(i), Value::Table(j)) => Rc::ptr_eq(&i, &j),
_ => false,
}
}
}
impl Default for Value {
fn default() -> Self {
Value::Nil
}
}
impl core::hash::Hash for Value {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
core::mem::discriminant(self).hash(state);
}
}
impl Eq for Value {}