diff --git a/src/vm/mod.rs b/src/vm/mod.rs index d93a392..d3f7637 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -566,28 +566,60 @@ impl ClosureRunner { .unwrap_or(Value::Nil); } Instruction::SetTable(tablereg, indexreg, valuereg) => { - let table = self.stack.get(tablereg); - match table { + let table_value = self.stack.get(tablereg); + match table_value { Some(value) => { let mut table = value.borrow_mut(); - if let Value::Table { contents, .. } = &mut *table { + if let Value::Table { + contents, + metatable, + } = &mut *table + { let index_value = self .stack .get(indexreg) .map(|v| v.borrow().clone()) - .unwrap_or(Value::Nil) - .as_indexable()?; + .unwrap_or(Value::Nil); let value = self .stack .get(valuereg) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - match value { - Value::Nil => { - contents.borrow_mut().remove(&index_value); + if contents + .borrow() + .contains_key(&index_value.clone().as_indexable()?) + { + match value { + Value::Nil => { + contents + .borrow_mut() + .remove(&index_value.as_indexable()?); + } + _ => { + contents + .borrow_mut() + .insert(index_value.as_indexable()?, value); + } } - _ => { - contents.borrow_mut().insert(index_value, value); + } else { + match self.call_metamethod( + metatable, + "__newindex", + vec![table_value.unwrap().borrow().clone()], + ) { + Ok(_) => {} + Err(_) => match value { + Value::Nil => { + contents + .borrow_mut() + .remove(&index_value.as_indexable()?); + } + _ => { + contents + .borrow_mut() + .insert(index_value.as_indexable()?, value); + } + }, } } } else {