From 8a50965f2e2f47a6f23a3d4bf759951ed54bee54 Mon Sep 17 00:00:00 2001 From: Sofia Date: Sat, 21 Mar 2026 15:38:35 +0200 Subject: [PATCH] Update how result_or_metamethod-functions work --- src/vm/mod.rs | 207 +++++++++++++++--------------------------------- src/vm/value.rs | 2 +- 2 files changed, 63 insertions(+), 146 deletions(-) diff --git a/src/vm/mod.rs b/src/vm/mod.rs index b61efdf..81c34fb 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -890,7 +890,7 @@ impl ClosureRunner { "__concat", lhs, rhs, - )??), + )?), ); } @@ -903,7 +903,7 @@ impl ClosureRunner { "__add", lhs, rhs, - )??), + )?), ); } Instruction::Sub(res, lhs, rhs) => { @@ -915,7 +915,7 @@ impl ClosureRunner { "__sub", lhs, rhs, - )??), + )?), ); } Instruction::Mult(res, lhs, rhs) => { @@ -927,7 +927,7 @@ impl ClosureRunner { "__mult", lhs, rhs, - )??), + )?), ); } Instruction::Div(res, lhs, rhs) => { @@ -939,7 +939,7 @@ impl ClosureRunner { "__div", lhs, rhs, - )??), + )?), ); } Instruction::IDiv(res, lhs, rhs) => { @@ -951,7 +951,7 @@ impl ClosureRunner { "__idiv", lhs, rhs, - )??), + )?), ); } Instruction::Mod(res, lhs, rhs) => { @@ -963,7 +963,7 @@ impl ClosureRunner { "__mod", lhs, rhs, - )??), + )?), ); } Instruction::Exp(res, lhs, rhs) => { @@ -975,7 +975,7 @@ impl ClosureRunner { "__exp", lhs, rhs, - )??), + )?), ); } @@ -988,7 +988,7 @@ impl ClosureRunner { "__band", lhs, rhs, - )??), + )?), ); } Instruction::BitOr(res, lhs, rhs) => { @@ -1000,7 +1000,7 @@ impl ClosureRunner { "__bor", lhs, rhs, - )??), + )?), ); } Instruction::BitXOr(res, lhs, rhs) => { @@ -1012,7 +1012,7 @@ impl ClosureRunner { "__bxor", lhs, rhs, - )??), + )?), ); } Instruction::BitSRight(res, lhs, rhs) => { @@ -1024,7 +1024,7 @@ impl ClosureRunner { "__shr", lhs, rhs, - )??), + )?), ); } Instruction::BitSLeft(res, lhs, rhs) => { @@ -1036,33 +1036,24 @@ impl ClosureRunner { "__shl", lhs, rhs, - )??), + )?), ); } Instruction::Equal(res, lhs, rhs) => { let (lhs, rhs) = self.lhs_and_rhs(lhs, rhs); - - let metatable = match (&lhs, &rhs) { - (Value::Table { metatable, .. }, _) => Some(metatable), - (_, Value::Table { metatable, .. }) => Some(metatable), - _ => todo!(), - }; - - let value = if let Some(metatable) = metatable { - match self.call_metamethod( - metatable, - "__eq", - vec![lhs.clone(), rhs.clone()], - ) { - Ok(value) => StackValue::Value(extract_ret_value(value)?), - Err(_) => StackValue::Value(lhs.eq(&rhs)?), - } - } else { - StackValue::Value(lhs.eq(&rhs)?) - }; - - self.set_stack(*res, value); + self.set_stack( + *res, + StackValue::Value(Value::Boolean(LuaBool( + self.result_or_metamethod_binop( + lhs.eq(&rhs), + "__eq", + lhs.clone(), + rhs.clone(), + )? + .is_truthy(), + ))), + ); } Instruction::LessThan(res, lhs, rhs) => { let (lhs, rhs) = self.lhs_and_rhs(lhs, rhs); @@ -1074,7 +1065,7 @@ impl ClosureRunner { "__lt", lhs.clone(), rhs.clone(), - )?? + )? .is_truthy(), ))), ); @@ -1089,7 +1080,7 @@ impl ClosureRunner { "__le", lhs.clone(), rhs.clone(), - )?? + )? .is_truthy(), ))), ); @@ -1116,7 +1107,7 @@ impl ClosureRunner { value.unm(), "__unm", value.clone(), - )??), + )?), ); } Instruction::Len(res, reg) => { @@ -1125,24 +1116,14 @@ impl ClosureRunner { .get(reg) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - match &value { - Value::Table { metatable, .. } => { - match self.call_metamethod(&metatable, "__len", vec![value.clone()]) { - Ok(result) => { - self.set_stack( - *res, - StackValue::Value(result?.first().unwrap().clone()), - ); - } - Err(_) => { - self.set_stack(*res, StackValue::Value(value.len()?)); - } - } - } - _ => { - self.set_stack(*res, StackValue::Value(value.len()?)); - } - } + self.set_stack( + *res, + StackValue::Value(self.result_or_metamethod_unop( + value.len(), + "__len", + value.clone(), + )?), + ); } Instruction::Not(res, reg) => { self.set_stack( @@ -1217,32 +1198,16 @@ impl ClosureRunner { value: Result, metamethod: &str, param: Value, - ) -> Result, RuntimeError> { - match value { - Ok(value) => Ok(Ok(value)), - Err(_) => match ¶m { - Value::Table { metatable, .. } => { - if metatable - .borrow() - .contains_key(&IndexableValue::String(metamethod.to_owned())) - { - Ok(extract_ret_value(self.call_metamethod( - metatable, - metamethod, - vec![param.clone()], - )?)) - } else { - Err(RuntimeError::InvalidUnop( - metamethod.to_owned(), - param.clone(), - )) - } - } - _ => Err(RuntimeError::InvalidUnop( - metamethod.to_owned(), - param.clone(), - )), - }, + ) -> Result { + let metatable = extract_metatable(¶m); + + if let Some(metatable) = metatable { + match self.call_metamethod(metatable, metamethod, vec![param.clone()]) { + Ok(value) => extract_ret_value(value), + Err(_) => value, + } + } else { + value } } @@ -1252,71 +1217,16 @@ impl ClosureRunner { metamethod: &str, lhs: Value, rhs: Value, - ) -> Result, RuntimeError> { - match value { - Ok(value) => Ok(Ok(value)), - Err(_) => { - if let Value::Table { metatable, .. } = &lhs { - if metatable - .borrow() - .contains_key(&IndexableValue::String(metamethod.to_owned())) - { - Ok(extract_ret_value(self.call_metamethod( - &metatable, - metamethod, - vec![lhs.clone(), rhs], - )?)) - } else { - if let Value::Table { metatable, .. } = &rhs { - if metatable - .borrow() - .contains_key(&IndexableValue::String(metamethod.to_owned())) - { - Ok(extract_ret_value(self.call_metamethod( - &metatable, - metamethod, - vec![lhs, rhs.clone()], - )?)) - } else { - Err(RuntimeError::InvalidBinop( - metamethod.to_owned(), - lhs.clone(), - rhs.clone(), - )) - } - } else { - Err(RuntimeError::InvalidBinop( - metamethod.to_owned(), - lhs.clone(), - rhs.clone(), - )) - } - } - } else if let Value::Table { metatable, .. } = &rhs { - if metatable - .borrow() - .contains_key(&IndexableValue::String(metamethod.to_owned())) - { - Ok(extract_ret_value(self.call_metamethod( - &metatable, - metamethod, - vec![lhs, rhs.clone()], - )?)) - } else { - Err(RuntimeError::InvalidBinop( - metamethod.to_owned(), - lhs.clone(), - rhs.clone(), - )) - } - } else { - Err(RuntimeError::InvalidBinop( - metamethod.to_owned(), - lhs.clone(), - rhs.clone(), - )) - } + ) -> Result { + let metatable = extract_metatable(&lhs).or(extract_metatable(&rhs)); + + if let Some(metatable) = metatable { + match self.call_metamethod(metatable, metamethod, vec![lhs.clone(), rhs.clone()]) { + Ok(value) => extract_ret_value(value), + Err(_) => value, } + } else { + value } } @@ -1372,6 +1282,13 @@ impl ClosureRunner { } } +fn extract_metatable(value: &Value) -> Option<&Table> { + match value { + Value::Table { metatable, .. } => Some(metatable), + _ => None, + } +} + fn extract_ret_value(values: Result, RuntimeError>) -> Result { values.map(|v| v.into_iter().next().unwrap()) } diff --git a/src/vm/value.rs b/src/vm/value.rs index 9584591..852f6a6 100644 --- a/src/vm/value.rs +++ b/src/vm/value.rs @@ -198,7 +198,7 @@ impl Display for Value { Value::Integer(lua_integer) => Display::fmt(&lua_integer.0, f), Value::Boolean(lua_bool) => Display::fmt(&lua_bool.0, f), Value::RustFunction(ref_cell) => { - write!(f, "", ref_cell.borrow().as_indexable()) + write!(f, "", ref_cell.borrow().as_indexable()) } Value::Function(closure) => write!(f, "", closure.prototype), Value::Nil => write!(f, "nil"),