Update how result_or_metamethod-functions work
This commit is contained in:
parent
76fa290988
commit
8a50965f2e
207
src/vm/mod.rs
207
src/vm/mod.rs
@ -890,7 +890,7 @@ impl ClosureRunner {
|
|||||||
"__concat",
|
"__concat",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -903,7 +903,7 @@ impl ClosureRunner {
|
|||||||
"__add",
|
"__add",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::Sub(res, lhs, rhs) => {
|
Instruction::Sub(res, lhs, rhs) => {
|
||||||
@ -915,7 +915,7 @@ impl ClosureRunner {
|
|||||||
"__sub",
|
"__sub",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::Mult(res, lhs, rhs) => {
|
Instruction::Mult(res, lhs, rhs) => {
|
||||||
@ -927,7 +927,7 @@ impl ClosureRunner {
|
|||||||
"__mult",
|
"__mult",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::Div(res, lhs, rhs) => {
|
Instruction::Div(res, lhs, rhs) => {
|
||||||
@ -939,7 +939,7 @@ impl ClosureRunner {
|
|||||||
"__div",
|
"__div",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::IDiv(res, lhs, rhs) => {
|
Instruction::IDiv(res, lhs, rhs) => {
|
||||||
@ -951,7 +951,7 @@ impl ClosureRunner {
|
|||||||
"__idiv",
|
"__idiv",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::Mod(res, lhs, rhs) => {
|
Instruction::Mod(res, lhs, rhs) => {
|
||||||
@ -963,7 +963,7 @@ impl ClosureRunner {
|
|||||||
"__mod",
|
"__mod",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::Exp(res, lhs, rhs) => {
|
Instruction::Exp(res, lhs, rhs) => {
|
||||||
@ -975,7 +975,7 @@ impl ClosureRunner {
|
|||||||
"__exp",
|
"__exp",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -988,7 +988,7 @@ impl ClosureRunner {
|
|||||||
"__band",
|
"__band",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::BitOr(res, lhs, rhs) => {
|
Instruction::BitOr(res, lhs, rhs) => {
|
||||||
@ -1000,7 +1000,7 @@ impl ClosureRunner {
|
|||||||
"__bor",
|
"__bor",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::BitXOr(res, lhs, rhs) => {
|
Instruction::BitXOr(res, lhs, rhs) => {
|
||||||
@ -1012,7 +1012,7 @@ impl ClosureRunner {
|
|||||||
"__bxor",
|
"__bxor",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::BitSRight(res, lhs, rhs) => {
|
Instruction::BitSRight(res, lhs, rhs) => {
|
||||||
@ -1024,7 +1024,7 @@ impl ClosureRunner {
|
|||||||
"__shr",
|
"__shr",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::BitSLeft(res, lhs, rhs) => {
|
Instruction::BitSLeft(res, lhs, rhs) => {
|
||||||
@ -1036,33 +1036,24 @@ impl ClosureRunner {
|
|||||||
"__shl",
|
"__shl",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction::Equal(res, lhs, rhs) => {
|
Instruction::Equal(res, lhs, rhs) => {
|
||||||
let (lhs, rhs) = self.lhs_and_rhs(lhs, rhs);
|
let (lhs, rhs) = self.lhs_and_rhs(lhs, rhs);
|
||||||
|
self.set_stack(
|
||||||
let metatable = match (&lhs, &rhs) {
|
*res,
|
||||||
(Value::Table { metatable, .. }, _) => Some(metatable),
|
StackValue::Value(Value::Boolean(LuaBool(
|
||||||
(_, Value::Table { metatable, .. }) => Some(metatable),
|
self.result_or_metamethod_binop(
|
||||||
_ => todo!(),
|
lhs.eq(&rhs),
|
||||||
};
|
"__eq",
|
||||||
|
lhs.clone(),
|
||||||
let value = if let Some(metatable) = metatable {
|
rhs.clone(),
|
||||||
match self.call_metamethod(
|
)?
|
||||||
metatable,
|
.is_truthy(),
|
||||||
"__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);
|
|
||||||
}
|
}
|
||||||
Instruction::LessThan(res, lhs, rhs) => {
|
Instruction::LessThan(res, lhs, rhs) => {
|
||||||
let (lhs, rhs) = self.lhs_and_rhs(lhs, rhs);
|
let (lhs, rhs) = self.lhs_and_rhs(lhs, rhs);
|
||||||
@ -1074,7 +1065,7 @@ impl ClosureRunner {
|
|||||||
"__lt",
|
"__lt",
|
||||||
lhs.clone(),
|
lhs.clone(),
|
||||||
rhs.clone(),
|
rhs.clone(),
|
||||||
)??
|
)?
|
||||||
.is_truthy(),
|
.is_truthy(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
@ -1089,7 +1080,7 @@ impl ClosureRunner {
|
|||||||
"__le",
|
"__le",
|
||||||
lhs.clone(),
|
lhs.clone(),
|
||||||
rhs.clone(),
|
rhs.clone(),
|
||||||
)??
|
)?
|
||||||
.is_truthy(),
|
.is_truthy(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
@ -1116,7 +1107,7 @@ impl ClosureRunner {
|
|||||||
value.unm(),
|
value.unm(),
|
||||||
"__unm",
|
"__unm",
|
||||||
value.clone(),
|
value.clone(),
|
||||||
)??),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Instruction::Len(res, reg) => {
|
Instruction::Len(res, reg) => {
|
||||||
@ -1125,24 +1116,14 @@ impl ClosureRunner {
|
|||||||
.get(reg)
|
.get(reg)
|
||||||
.map(|v| v.borrow().clone())
|
.map(|v| v.borrow().clone())
|
||||||
.unwrap_or(Value::Nil);
|
.unwrap_or(Value::Nil);
|
||||||
match &value {
|
self.set_stack(
|
||||||
Value::Table { metatable, .. } => {
|
*res,
|
||||||
match self.call_metamethod(&metatable, "__len", vec![value.clone()]) {
|
StackValue::Value(self.result_or_metamethod_unop(
|
||||||
Ok(result) => {
|
value.len(),
|
||||||
self.set_stack(
|
"__len",
|
||||||
*res,
|
value.clone(),
|
||||||
StackValue::Value(result?.first().unwrap().clone()),
|
)?),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
self.set_stack(*res, StackValue::Value(value.len()?));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.set_stack(*res, StackValue::Value(value.len()?));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Instruction::Not(res, reg) => {
|
Instruction::Not(res, reg) => {
|
||||||
self.set_stack(
|
self.set_stack(
|
||||||
@ -1217,32 +1198,16 @@ impl ClosureRunner {
|
|||||||
value: Result<Value, RuntimeError>,
|
value: Result<Value, RuntimeError>,
|
||||||
metamethod: &str,
|
metamethod: &str,
|
||||||
param: Value,
|
param: Value,
|
||||||
) -> Result<Result<Value, RuntimeError>, RuntimeError> {
|
) -> Result<Value, RuntimeError> {
|
||||||
match value {
|
let metatable = extract_metatable(¶m);
|
||||||
Ok(value) => Ok(Ok(value)),
|
|
||||||
Err(_) => match ¶m {
|
if let Some(metatable) = metatable {
|
||||||
Value::Table { metatable, .. } => {
|
match self.call_metamethod(metatable, metamethod, vec![param.clone()]) {
|
||||||
if metatable
|
Ok(value) => extract_ret_value(value),
|
||||||
.borrow()
|
Err(_) => value,
|
||||||
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
}
|
||||||
{
|
} else {
|
||||||
Ok(extract_ret_value(self.call_metamethod(
|
value
|
||||||
metatable,
|
|
||||||
metamethod,
|
|
||||||
vec![param.clone()],
|
|
||||||
)?))
|
|
||||||
} else {
|
|
||||||
Err(RuntimeError::InvalidUnop(
|
|
||||||
metamethod.to_owned(),
|
|
||||||
param.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Err(RuntimeError::InvalidUnop(
|
|
||||||
metamethod.to_owned(),
|
|
||||||
param.clone(),
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1252,71 +1217,16 @@ impl ClosureRunner {
|
|||||||
metamethod: &str,
|
metamethod: &str,
|
||||||
lhs: Value,
|
lhs: Value,
|
||||||
rhs: Value,
|
rhs: Value,
|
||||||
) -> Result<Result<Value, RuntimeError>, RuntimeError> {
|
) -> Result<Value, RuntimeError> {
|
||||||
match value {
|
let metatable = extract_metatable(&lhs).or(extract_metatable(&rhs));
|
||||||
Ok(value) => Ok(Ok(value)),
|
|
||||||
Err(_) => {
|
if let Some(metatable) = metatable {
|
||||||
if let Value::Table { metatable, .. } = &lhs {
|
match self.call_metamethod(metatable, metamethod, vec![lhs.clone(), rhs.clone()]) {
|
||||||
if metatable
|
Ok(value) => extract_ret_value(value),
|
||||||
.borrow()
|
Err(_) => value,
|
||||||
.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(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} 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<Vec<Value>, RuntimeError>) -> Result<Value, RuntimeError> {
|
fn extract_ret_value(values: Result<Vec<Value>, RuntimeError>) -> Result<Value, RuntimeError> {
|
||||||
values.map(|v| v.into_iter().next().unwrap())
|
values.map(|v| v.into_iter().next().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -198,7 +198,7 @@ impl Display for Value {
|
|||||||
Value::Integer(lua_integer) => Display::fmt(&lua_integer.0, f),
|
Value::Integer(lua_integer) => Display::fmt(&lua_integer.0, f),
|
||||||
Value::Boolean(lua_bool) => Display::fmt(&lua_bool.0, f),
|
Value::Boolean(lua_bool) => Display::fmt(&lua_bool.0, f),
|
||||||
Value::RustFunction(ref_cell) => {
|
Value::RustFunction(ref_cell) => {
|
||||||
write!(f, "<RustFunction#{}>", ref_cell.borrow().as_indexable())
|
write!(f, "<RustFunction#{})>", ref_cell.borrow().as_indexable())
|
||||||
}
|
}
|
||||||
Value::Function(closure) => write!(f, "<function#{}>", closure.prototype),
|
Value::Function(closure) => write!(f, "<function#{}>", closure.prototype),
|
||||||
Value::Nil => write!(f, "nil"),
|
Value::Nil => write!(f, "nil"),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user