use crate::serialization::op_code::OpCode;
use crate::types::smethod::SMethod;
use crate::types::stype::SType;
use super::expr::Expr;
use super::expr::InvalidArgumentError;
use crate::has_opcode::HasStaticOpCode;
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct MethodCall {
pub obj: Box<Expr>,
pub method: SMethod,
pub args: Vec<Expr>,
}
impl MethodCall {
pub fn new(obj: Expr, method: SMethod, args: Vec<Expr>) -> Result<Self, InvalidArgumentError> {
if method.tpe().t_dom.len() != args.len() + 1 {
return Err(InvalidArgumentError(format!(
"MethodCall: expected arguments count {} does not match provided arguments count {}",
method.tpe().t_dom.len(), args.len() + 1)));
}
let mut expected_types: Vec<SType> = vec![obj.tpe()];
let arg_types: Vec<SType> = args.clone().into_iter().map(|a| a.tpe()).collect();
expected_types.extend(arg_types);
if !method
.tpe()
.t_dom
.iter()
.zip(&expected_types)
.all(|(expected, actual)| expected == actual)
{
return Err(InvalidArgumentError(format!(
"MethodCall: expected types {:?} do not match provided obj and args types {:?}",
method.tpe().t_dom,
expected_types
)));
}
Ok(Self {
obj: obj.into(),
method,
args,
})
}
pub fn tpe(&self) -> SType {
*self.method.tpe().t_range.clone()
}
}
impl HasStaticOpCode for MethodCall {
const OP_CODE: OpCode = OpCode::METHOD_CALL;
}