Add metatable to Tables

This commit is contained in:
Sofia 2026-03-20 20:25:17 +02:00
parent 4ac41e7df1
commit 232a729fe2
2 changed files with 26 additions and 17 deletions

View File

@ -474,7 +474,10 @@ impl ClosureRunner {
{
self.set_stack(
*reg,
StackValue::Value(Value::Table(self.closure.environment.clone())),
StackValue::Value(Value::Table {
contents: self.closure.environment.clone(),
metatable: Box::new(Value::Nil),
}),
);
} else {
let environment = self.closure.environment.borrow_mut().clone();
@ -507,7 +510,7 @@ impl ClosureRunner {
match table {
Some(value) => {
let mut table = value.borrow_mut();
if let Value::Table(table) = &mut *table {
if let Value::Table { contents, .. } = &mut *table {
let index_value = self
.stack
.get(indexreg)
@ -521,10 +524,10 @@ impl ClosureRunner {
.unwrap_or(Value::Nil);
match value {
Value::Nil => {
table.borrow_mut().remove(&index_value);
contents.borrow_mut().remove(&index_value);
}
_ => {
table.borrow_mut().insert(index_value, value);
contents.borrow_mut().insert(index_value, value);
}
}
} else {
@ -538,8 +541,8 @@ impl ClosureRunner {
let value = match self.stack.get(tablereg).cloned() {
Some(value) => {
let table = value.borrow();
if let Value::Table(table) = &*table {
let table = table.borrow();
if let Value::Table { contents, .. } = &*table {
let table = contents.borrow();
let index_value = self
.stack
.get(indexreg)
@ -567,12 +570,12 @@ impl ClosureRunner {
match table {
Some(value) => {
let mut table = value.borrow_mut();
if let Value::Table(table) = &mut *table {
if let Value::Table { contents, .. } = &mut *table {
let mut counter = *start_idx as i64;
for i in self.function_register..self.top {
let value = self.get_stack(i + 1);
match value {
StackValue::Value(value) => table.borrow_mut().insert(
StackValue::Value(value) => contents.borrow_mut().insert(
IndexableValue::Integer(LuaInteger(counter)),
value.clone(),
),
@ -589,7 +592,10 @@ impl ClosureRunner {
Instruction::NewTable(reg) => {
self.set_stack(
*reg,
StackValue::Value(Value::Table(Rc::new(RefCell::new(HashMap::new())))),
StackValue::Value(Value::Table {
contents: Rc::new(RefCell::new(HashMap::new())),
metatable: Box::new(Value::Nil),
}),
);
}
Instruction::Jmp(b) => {

View File

@ -136,7 +136,10 @@ pub enum Value {
RustFunction(Rc<RefCell<dyn RustFunction>>),
Function(Closure),
Nil,
Table(Table),
Table {
contents: Table,
metatable: Box<Value>,
},
}
impl Value {
@ -151,7 +154,7 @@ impl Value {
}
Value::Function(closure) => Ok(IndexableValue::Function(closure.prototype)),
Value::Nil => Err(RuntimeError::InvalidTableIndex(self)),
Value::Table(_) => Err(RuntimeError::InvalidTableIndex(self)),
Value::Table { .. } => Err(RuntimeError::InvalidTableIndex(self)),
}
}
@ -201,7 +204,7 @@ impl Display for Value {
}
Value::Function(closure) => write!(f, "<function({})>", closure.prototype),
Value::Nil => write!(f, "nil"),
Value::Table(_) => write!(f, "<table>"),
Value::Table { .. } => write!(f, "<table>"),
}
}
}
@ -514,8 +517,8 @@ impl Value {
pub fn len(&self) -> Result<Value, RuntimeError> {
match self {
Value::String(value) => Ok(Self::Integer(LuaInteger(value.len() as i64))),
Value::Table(table) => {
let table = table.borrow();
Value::Table { contents, .. } => {
let table = contents.borrow();
let mut int_indexes = table
.keys()
.filter(|v| match v {
@ -585,7 +588,7 @@ impl Value {
Value::RustFunction(_) => true,
Value::Function(_) => true,
Value::Nil => false,
Value::Table(_) => true,
Value::Table { .. } => true,
}
}
}
@ -602,9 +605,9 @@ impl Debug for Value {
.debug_tuple(&format!("Function({})", closure.prototype))
.finish(),
Value::Nil => write!(f, "Nil"),
Value::Table(hash_map) => {
Value::Table { contents, .. } => {
let mut table = f.debug_struct("Table");
for (key, value) in hash_map.borrow().iter() {
for (key, value) in contents.borrow().iter() {
table.field(&format!("{:?}", key), value);
}
table.finish()