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