use crate::object::resolve as obj_resolve;
use runmat_builtins::Value;
use runmat_gc::gc_record_write;
use runmat_runtime::RuntimeError;
pub async fn dispatch_object(
instr: &crate::bytecode::Instr,
stack: &mut Vec<Value>,
current_function_name: &str,
) -> Result<bool, RuntimeError> {
let caller_function_name = if current_function_name.is_empty() {
None
} else {
Some(current_function_name)
};
match instr {
crate::bytecode::Instr::LoadMember(field) => {
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let value =
obj_resolve::load_member(base, field.clone(), false, caller_function_name).await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::LoadMemberOrInit(field) => {
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let value =
obj_resolve::load_member(base, field.clone(), true, caller_function_name).await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::LoadMemberDynamic => {
let name_val = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let name: String = (&name_val).try_into()?;
let value =
obj_resolve::load_member_dynamic(base, name, false, caller_function_name).await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::LoadMemberDynamicOrInit => {
let name_val = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let name: String = (&name_val).try_into()?;
let value =
obj_resolve::load_member_dynamic(base, name, true, caller_function_name).await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::StoreMember(field) => {
let rhs = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let value = obj_resolve::store_member(
base,
field.clone(),
rhs,
false,
caller_function_name,
|oldv, newv| {
gc_record_write(oldv, newv);
},
)
.await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::StoreMemberOrInit(field) => {
let rhs = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let value = obj_resolve::store_member(
base,
field.clone(),
rhs,
true,
caller_function_name,
|oldv, newv| {
gc_record_write(oldv, newv);
},
)
.await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::StoreMemberDynamic => {
let rhs = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let name_val = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let name: String = (&name_val).try_into()?;
let value = obj_resolve::store_member_dynamic(
base,
name,
rhs,
false,
caller_function_name,
|oldv, newv| {
gc_record_write(oldv, newv);
},
)
.await?;
stack.push(value);
Ok(true)
}
crate::bytecode::Instr::StoreMemberDynamicOrInit => {
let rhs = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let name_val = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let base = stack.pop().ok_or(crate::interpreter::errors::mex(
"StackUnderflow",
"stack underflow",
))?;
let name: String = (&name_val).try_into()?;
let value = obj_resolve::store_member_dynamic(
base,
name,
rhs,
true,
caller_function_name,
|oldv, newv| {
gc_record_write(oldv, newv);
},
)
.await?;
stack.push(value);
Ok(true)
}
_ => Ok(false),
}
}