From 71c11e87e5793fdac8d64e66ed7ffcf262592b03 Mon Sep 17 00:00:00 2001 From: Sofia Date: Sat, 21 Mar 2026 14:56:06 +0200 Subject: [PATCH] Add __call metamethod --- src/vm/mod.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/src/vm/mod.rs b/src/vm/mod.rs index d3f7637..0f52d57 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -653,7 +653,9 @@ impl ClosureRunner { "__index", vec![value.unwrap().clone(), index_value.clone()], ) { - Ok(value) => StackValue::Value(value), + Ok(value) => { + StackValue::Value(value.first().unwrap().clone()) + } Err(_) => StackValue::Value(Value::Nil), } } @@ -773,7 +775,7 @@ impl ClosureRunner { .get(func_reg) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - match value { + match &value { Value::RustFunction(func) => { let ret_values = func.borrow_mut().execute(params)?; if *ret_len != 0 { @@ -807,6 +809,34 @@ impl ClosureRunner { } self.inner = Some(Box::new(closure.run(params))); } + Value::Table { metatable, .. } => { + let mut metamethod_params = vec![value.clone()]; + metamethod_params.extend(params); + let ret_values = + self.call_metamethod(&metatable, "__call", metamethod_params)?; + + if *ret_len != 0 { + for i in 0..=(*ret_len - 2) { + self.set_stack( + *func_reg + i, + StackValue::Value( + ret_values + .get(i as usize) + .cloned() + .unwrap_or(Value::Nil), + ), + ); + } + } else { + for (i, value) in ret_values.iter().enumerate() { + self.set_stack( + *func_reg + i as u16 + 1, + StackValue::Value(value.clone()), + ); + } + self.top = *func_reg + ret_values.len() as u16; + } + } _ => return Err(RuntimeError::TriedCallingNonFunction(value.clone())), } } @@ -1019,6 +1049,8 @@ impl ClosureRunner { "__eq", vec![lhs.clone(), rhs.clone()], )? + .first() + .unwrap() .is_truthy(), ))), ); @@ -1093,7 +1125,10 @@ impl ClosureRunner { Value::Table { metatable, .. } => { match self.call_metamethod(&metatable, "__len", vec![value.clone()]) { Ok(result) => { - self.set_stack(*res, StackValue::Value(result)); + self.set_stack( + *res, + StackValue::Value(result.first().unwrap().clone()), + ); } Err(_) => { self.set_stack(*res, StackValue::Value(value.len()?)); @@ -1187,7 +1222,11 @@ impl ClosureRunner { .borrow() .contains_key(&IndexableValue::String(metamethod.to_owned())) { - self.call_metamethod(metatable, metamethod, vec![param.clone()]) + Ok(self + .call_metamethod(metatable, metamethod, vec![param.clone()])? + .into_iter() + .next() + .unwrap()) } else { Err(RuntimeError::InvalidUnop( metamethod.to_owned(), @@ -1218,14 +1257,26 @@ impl ClosureRunner { .borrow() .contains_key(&IndexableValue::String(metamethod.to_owned())) { - self.call_metamethod(&metatable, metamethod, vec![lhs.clone(), rhs]) + Ok(self + .call_metamethod(&metatable, metamethod, vec![lhs.clone(), rhs])? + .into_iter() + .next() + .unwrap()) } else { if let Value::Table { metatable, .. } = &rhs { if metatable .borrow() .contains_key(&IndexableValue::String(metamethod.to_owned())) { - self.call_metamethod(&metatable, metamethod, vec![lhs, rhs.clone()]) + Ok(self + .call_metamethod( + &metatable, + metamethod, + vec![lhs, rhs.clone()], + )? + .into_iter() + .next() + .unwrap()) } else { Err(RuntimeError::InvalidBinop( metamethod.to_owned(), @@ -1246,7 +1297,11 @@ impl ClosureRunner { .borrow() .contains_key(&IndexableValue::String(metamethod.to_owned())) { - self.call_metamethod(&metatable, metamethod, vec![lhs, rhs.clone()]) + Ok(self + .call_metamethod(&metatable, metamethod, vec![lhs, rhs.clone()])? + .into_iter() + .next() + .unwrap()) } else { Err(RuntimeError::InvalidBinop( metamethod.to_owned(), @@ -1270,7 +1325,7 @@ impl ClosureRunner { metatable: &Table, metamethod: &str, params: Vec, - ) -> Result { + ) -> Result, RuntimeError> { if let Some(value) = metatable .borrow() .get(&IndexableValue::String(metamethod.to_owned())) @@ -1278,7 +1333,7 @@ impl ClosureRunner { match value { Value::RustFunction(function) => { let result = function.borrow_mut().execute(params)?; - Ok(result.into_iter().next().unwrap()) + Ok(result) } Value::Function(closure) => { let mut runnable = closure.run(params); @@ -1288,7 +1343,7 @@ impl ClosureRunner { return_value = runnable.next()?; return_value.is_none() } {} - Ok(return_value.unwrap().into_iter().next().unwrap()) + Ok(return_value.unwrap()) } _ => Err(RuntimeError::MetafunctionNotCallable(value.clone())), }