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

View File

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