use tan::{
context::Context,
error::Error,
expr::Expr,
util::{
args::{
unpack_bool_arg, unpack_float_arg, unpack_int_arg, unpack_stringable_arg, unpack_u8_arg,
},
module_util::require_module,
},
};
pub fn eq_int(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_int_arg(args, 0, "a")?;
let b = unpack_int_arg(args, 1, "b")?;
Ok(Expr::Bool(a == b))
}
pub fn eq_u8(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_u8_arg(args, 0, "a")?;
let b = unpack_u8_arg(args, 1, "b")?;
Ok(Expr::Bool(a == b))
}
pub fn eq_float(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_float_arg(args, 0, "a")?;
let b = unpack_float_arg(args, 1, "b")?;
Ok(Expr::Bool(a == b))
}
pub fn eq_bool(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_bool_arg(args, 0, "a")?;
let b = unpack_bool_arg(args, 1, "b")?;
Ok(Expr::Bool(a == b))
}
pub fn eq_string(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_stringable_arg(args, 0, "a")?;
let b = unpack_stringable_arg(args, 1, "b")?;
Ok(Expr::Bool(a == b))
}
pub fn eq_symbol(args: &[Expr]) -> Result<Expr, Error> {
let [a, b] = args else {
return Err(Error::invalid_arguments(
"`=` requires at least two arguments",
None,
));
};
let Some(a) = a.as_symbolic() else {
return Err(Error::invalid_arguments(
&format!("`{a}` is not a Symbol"),
a.range(),
));
};
let Some(b) = b.as_symbolic() else {
return Err(Error::invalid_arguments(
&format!("`{b}` is not a Symbol"),
b.range(),
));
};
Ok(Expr::Bool(a == b))
}
pub fn not_eq_int(args: &[Expr]) -> Result<Expr, Error> {
Ok(Expr::Bool(eq_int(args)?.is_false()))
}
pub fn not_eq_float(args: &[Expr]) -> Result<Expr, Error> {
Ok(Expr::Bool(eq_float(args)?.is_false()))
}
pub fn not_eq_string(args: &[Expr]) -> Result<Expr, Error> {
Ok(Expr::Bool(eq_string(args)?.is_false()))
}
pub fn not_eq_symbol(args: &[Expr]) -> Result<Expr, Error> {
let [a, b] = args else {
return Err(Error::invalid_arguments(
"`!=` requires at least two arguments",
None,
));
};
let Some(a) = a.as_symbolic() else {
return Err(Error::invalid_arguments(
&format!("`{a}` is not a String"),
a.range(),
));
};
let Some(b) = b.as_symbolic() else {
return Err(Error::invalid_arguments(
&format!("`{b}` is not a Symbol"),
b.range(),
));
};
Ok(Expr::Bool(a != b))
}
pub fn int_gt(args: &[Expr]) -> Result<Expr, Error> {
let [a, b] = args else {
return Err(Error::invalid_arguments(
"`>` requires at least two arguments",
None,
));
};
let Some(a) = a.as_int() else {
return Err(Error::invalid_arguments(
&format!("`{a}` is not an Int"),
a.range(),
));
};
let Some(b) = b.as_int() else {
return Err(Error::invalid_arguments(
&format!("`{b}` is not an Int"),
b.range(),
));
};
Ok(Expr::Bool(a > b))
}
pub fn float_gt(args: &[Expr]) -> Result<Expr, Error> {
let [a, b] = args else {
return Err(Error::invalid_arguments(
"`>` requires at least two arguments",
None,
));
};
let Some(a) = a.as_float() else {
return Err(Error::invalid_arguments(
&format!("`{a}` is not a Float"),
a.range(),
));
};
let Some(b) = b.as_float() else {
return Err(Error::invalid_arguments(
&format!("`{b}` is not a Float"),
b.range(),
));
};
Ok(Expr::Bool(a > b))
}
pub fn int_gte(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_int_arg(args, 0, "a")?;
let b = unpack_int_arg(args, 1, "b")?;
Ok(Expr::Bool(a >= b))
}
pub fn float_gte(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_float_arg(args, 0, "a")?;
let b = unpack_float_arg(args, 1, "b")?;
Ok(Expr::Bool(a >= b))
}
pub fn int_lt(args: &[Expr]) -> Result<Expr, Error> {
let [a, b] = args else {
return Err(Error::invalid_arguments(
"`<` requires at least two arguments",
None,
));
};
let Some(a) = a.as_int() else {
return Err(Error::invalid_arguments(
&format!("`{a}` is not an Int"),
a.range(),
));
};
let Some(b) = b.as_int() else {
return Err(Error::invalid_arguments(
&format!("`{b}` is not an Int"),
b.range(),
));
};
Ok(Expr::Bool(a < b))
}
pub fn float_lt(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_float_arg(args, 0, "a")?;
let b = unpack_float_arg(args, 1, "b")?;
Ok(Expr::Bool(a < b))
}
pub fn int_lte(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_int_arg(args, 0, "a")?;
let b = unpack_int_arg(args, 1, "b")?;
Ok(Expr::Bool(a <= b))
}
pub fn float_lte(args: &[Expr]) -> Result<Expr, Error> {
let a = unpack_float_arg(args, 0, "a")?;
let b = unpack_float_arg(args, 1, "b")?;
Ok(Expr::Bool(a <= b))
}
pub fn setup_lib_eq(context: &mut Context) {
let module = require_module("prelude", context);
module.insert_invocable("=$$Int$$Int", Expr::foreign_func(&eq_int));
module.insert_invocable("=$$U8$$U8", Expr::foreign_func(&eq_u8));
module.insert_invocable("=$$Bool$$Bool", Expr::foreign_func(&eq_bool));
module.insert_invocable("=$$Float$$Float", Expr::foreign_func(&eq_float));
module.insert_invocable("=$$String$$String", Expr::foreign_func(&eq_string));
module.insert_invocable("=$$KeySymbol$$KeySymbol", Expr::foreign_func(&eq_symbol));
module.insert_invocable("=$$Type$$Type", Expr::foreign_func(&eq_symbol));
module.insert_invocable("=$$Type$$String", Expr::foreign_func(&eq_symbol));
module.insert_invocable("=$$Type$$KeySymbol", Expr::foreign_func(&eq_symbol));
module.insert_invocable("!=$$Int$$Int", Expr::foreign_func(¬_eq_int));
module.insert_invocable("!=$$Float$$Float", Expr::foreign_func(¬_eq_float));
module.insert_invocable("!=$$String$$String", Expr::foreign_func(¬_eq_string));
module.insert_invocable("!=$$Symbol$$Symbol", Expr::foreign_func(¬_eq_symbol));
module.insert_invocable(
"!=$$KeySymbol$$KeySymbol",
Expr::foreign_func(¬_eq_symbol),
);
module.insert_invocable(">$$Int$$Int", Expr::foreign_func(&int_gt));
module.insert_invocable(">$$Float$$Float", Expr::foreign_func(&float_gt));
module.insert_invocable(">=$$Int$$Int", Expr::foreign_func(&int_gte));
module.insert_invocable(">=$$Float$$Float", Expr::foreign_func(&float_gte));
module.insert_invocable("<$$Int$$Int", Expr::foreign_func(&int_lt));
module.insert_invocable("<$$Float$$Float", Expr::foreign_func(&float_lt));
module.insert_invocable("<=$$Int$$Int", Expr::foreign_func(&int_lte));
module.insert_invocable("<=$$Float$$Float", Expr::foreign_func(&float_lte));
}