use std::rc::Rc;
use bigdecimal::ToPrimitive;
use crate::error::{DogeError, DogeResult};
use crate::objects::method_arity_error;
use crate::value::Value;
mod bytes;
mod dict;
mod list;
mod str;
#[cfg(test)]
mod tests;
use bytes::bytes_method;
use dict::dict_method;
use list::list_method;
use str::str_method;
pub fn builtin_method(recv: &Value, name: &str, args: Vec<Value>) -> DogeResult {
match recv {
Value::List(_) => list_method(recv, name, args),
Value::Dict(_) => dict_method(recv, name, args),
Value::Bytes(_) => bytes_method(recv, name, args),
Value::Str(_) => str_method(recv, name, args),
Value::Object(_) => Err(crate::objects::no_such_method(recv, name)),
Value::Int(_)
| Value::Float(_)
| Value::Decimal(_)
| Value::Bool(_)
| Value::None
| Value::Function(_)
| Value::Class(_)
| Value::BoundMethod(_)
| Value::Error(_)
| Value::Socket(_)
| Value::Pup(_)
| Value::Bowl(_) => Err(crate::objects::no_methods_error(recv)),
}
}
pub fn has_builtin_method(recv: &Value, name: &str) -> bool {
match recv {
Value::List(_) => list::LIST_METHODS.contains(&name),
Value::Dict(_) => dict::DICT_METHODS.contains(&name),
Value::Bytes(_) => bytes::BYTES_METHODS.contains(&name),
Value::Str(_) => str::STR_METHODS.contains(&name),
_ => false,
}
}
pub(super) fn check_arity(
class: &str,
method: &str,
expected: usize,
got: usize,
) -> DogeResult<()> {
if got == expected {
Ok(())
} else {
Err(method_arity_error(
class,
method,
expected,
Some(expected),
got,
))
}
}
pub(super) fn expect_int(value: Value, what: &str) -> DogeResult<i64> {
match value {
Value::Int(n) => n
.to_i64()
.ok_or_else(|| DogeError::value_error(format!("{what}, but {n} is too large"))),
other => Err(DogeError::type_error(format!(
"{what}, got {}",
other.describe()
))),
}
}
pub(super) fn expect_str(value: Value, what: &str) -> DogeResult<Rc<str>> {
match value {
Value::Str(s) => Ok(s),
other => Err(DogeError::type_error(format!(
"{what}, got {}",
other.describe()
))),
}
}