Add better error messages to metamethods

This commit is contained in:
Sofia 2026-03-20 21:31:39 +02:00
parent 526d8ada47
commit b4918e7312

View File

@ -224,8 +224,8 @@ pub enum RuntimeError {
InvalidUnop(String, Value), InvalidUnop(String, Value),
#[error("Metatable is not a table: {0:?}")] #[error("Metatable is not a table: {0:?}")]
MetatableNotTable(Value), MetatableNotTable(Value),
#[error("Metafunction not found: {0}")] #[error("Metafunction not found: {0} for {1:?}")]
MetafunctionNotFound(String), MetafunctionNotFound(String, Value),
#[error("Metafunction is not callable: {0:?}")] #[error("Metafunction is not callable: {0:?}")]
MetafunctionNotCallable(Value), MetafunctionNotCallable(Value),
#[error("Unable to perform {0:?} operator to {1:?}")] #[error("Unable to perform {0:?} operator to {1:?}")]
@ -1139,7 +1139,17 @@ impl ClosureRunner {
Ok(value) => Ok(value), Ok(value) => Ok(value),
Err(_) => match &param { Err(_) => match &param {
Value::Table { metatable, .. } => { Value::Table { metatable, .. } => {
self.call_metamethod(metatable, metamethod, vec![param.clone()]) if metatable
.borrow()
.contains_key(&IndexableValue::String(metamethod.to_owned()))
{
self.call_metamethod(metatable, metamethod, vec![param.clone()])
} else {
Err(RuntimeError::InvalidUnop(
metamethod.to_owned(),
param.clone(),
))
}
} }
_ => Err(RuntimeError::InvalidUnop( _ => Err(RuntimeError::InvalidUnop(
metamethod.to_owned(), metamethod.to_owned(),
@ -1158,15 +1168,56 @@ impl ClosureRunner {
) -> Result<Value, RuntimeError> { ) -> Result<Value, RuntimeError> {
match value { match value {
Ok(value) => Ok(value), Ok(value) => Ok(value),
Err(_) => match (&lhs, &rhs) { Err(_) => {
(Value::Table { metatable, .. }, _) => { if let Value::Table { metatable, .. } = &lhs {
self.call_metamethod(metatable, metamethod, vec![lhs.clone(), rhs.clone()]) if metatable
.borrow()
.contains_key(&IndexableValue::String(metamethod.to_owned()))
{
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()))
{
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()))
{
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(),
))
} }
(_, Value::Table { metatable, .. }) => { }
self.call_metamethod(metatable, metamethod, vec![lhs.clone(), rhs.clone()])
}
_ => Err(RuntimeError::InvalidBinop(metamethod.to_owned(), lhs, rhs)),
},
} }
} }
@ -1198,7 +1249,10 @@ impl ClosureRunner {
_ => Err(RuntimeError::MetafunctionNotCallable(value.clone())), _ => Err(RuntimeError::MetafunctionNotCallable(value.clone())),
} }
} else { } else {
Err(RuntimeError::MetafunctionNotFound(metamethod.to_owned())) Err(RuntimeError::MetafunctionNotFound(
metamethod.to_owned(),
params.get(0).unwrap().clone(),
))
} }
} }