use crate::{Environment, FALSE_SYMBOL, TRUE_SYMBOL, eval::apply::eval_apply, value::Value};
pub(crate) fn builtin(args: &[Value], env: &Environment) -> Option<(Value, Environment)> {
if let [path, is_append, content] = &args[..] {
match (
eval_apply(path, env),
eval_apply(is_append, env),
eval_apply(content, env),
) {
(
Some((Value::String(file_path), _)),
Some((Value::Atom(p), _)),
Some((Value::String(text), _)),
) if &p == TRUE_SYMBOL || &p == FALSE_SYMBOL => {
match std::fs::File::options()
.append(&p == TRUE_SYMBOL)
.write(true)
.create(true)
.open(&file_path)
.and_then(|f| {
std::io::Write::write_all(
&mut std::io::BufWriter::new(f),
&text.bytes().collect::<Vec<u8>>(),
)
}) {
Ok(()) => Some((Value::Unit, Environment::new())),
Err(_) => {
eprintln!(concat!(
"Error[ksl::builtin::write]: ",
"Write to file failed.",
));
None
}
}
}
(Some((e1, _)), Some((e2, _)), Some((e3, _))) => {
eprintln!(
concat!(
"Error[ksl::builtin::write]: ",
"Only accepts a path, a predicate expression, ",
"and a text content as arguments, but got `{:?}`."
),
(e1, e2, e3)
);
None
}
_ => {
eprintln!(
concat!(
"Error[ksl::builtin::write]: ",
"Cannot evaluate expression {:?}."
),
(path, is_append, content)
);
None
}
}
} else {
eprintln!(
concat!(
"Error[ksl::builtin::write]: ",
"Only accepts 3 arguments, but {} were passed."
),
args.len()
);
None
}
}