use crate::{Environment, eval::apply::eval_apply, is_invalid_symbol, value::Value};
pub(crate) fn builtin(args: &[Value], env: Environment) -> Result<Value, std::sync::Arc<str>> {
if let [sym_expr, path_expr] = args {
let path_val = eval_apply(path_expr, env.clone())?;
match (sym_expr, path_val) {
(Value::Symbol(plugin_sym), Value::String(path_str)) => {
if let Some((lib_name, func_name)) = path_str.split_once('/') {
if is_invalid_symbol(plugin_sym) {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Plugin]: ",
"Rebinding of symbol `{}` is not permitted."
),
plugin_sym
)));
}
let _ = env.store.write().insert(
plugin_sym.clone(),
std::sync::Arc::new(Value::Plugin(
std::sync::Arc::from(lib_name),
std::sync::Arc::from(func_name),
)),
);
Ok(Value::Unit)
} else {
Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Plugin]: ",
"Expected format is `library_name/function_name`, ",
"but got `{}`."
),
path_str
)))
}
}
(Value::Symbol(_), e) => Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Plugin]: ",
"Expected a String for plugin path, ",
"but got `{}`."
),
e
))),
(e, _) => Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Plugin]: ",
"Expected a Symbol for function name, ",
"but got `{}`."
),
e
))),
}
} else {
Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Plugin]: ",
"Expected 2 parameters, but {} were passed."
),
args.len()
)))
}
}