use tan::{
api::compile_string,
context::Context,
error::Error,
expr::{format_value, Expr},
util::module_util::require_module,
};
pub fn read_string(args: &[Expr], context: &mut Context) -> Result<Expr, Error> {
if let Some(input) = args.first() {
let Some(input_str) = input.as_string() else {
return Err(Error::invalid_arguments(
"expected String argument",
input.range(),
));
};
let result = compile_string(input_str, context);
if let Ok(exprs) = result {
let expr = exprs.first().unwrap().clone(); Ok(expr)
} else {
dbg!(&result);
Err(Error::general("cannot read string, eval failed"))
}
} else {
Err(Error::invalid_arguments("expected one argument", None))
}
}
pub fn read_string_all(args: &[Expr], context: &mut Context) -> Result<Expr, Error> {
if let Some(input) = args.first() {
let Some(input_str) = input.as_string() else {
return Err(Error::invalid_arguments(
"expected String argument",
input.range(),
));
};
let result = compile_string(input_str, context);
if let Ok(exprs) = result {
Ok(Expr::array(exprs))
} else {
dbg!(&result);
Err(Error::general("cannot read string, eval failed"))
}
} else {
Err(Error::invalid_arguments("expected one argument", None))
}
}
pub fn write(args: &[Expr]) -> Result<Expr, Error> {
let output = args.iter().fold(String::new(), |mut str, x| {
str.push_str(&format_value(x));
str
});
for line in output.split_inclusive("\\n") {
if line.ends_with("\\n") {
let mut line: String = line.to_owned();
line.pop();
line.pop();
println!("{line}");
} else {
print!("{line}");
}
}
Ok(Expr::None)
}
pub fn writeln(args: &[Expr]) -> Result<Expr, Error> {
write(args)?;
write(&[Expr::string("\n")])
}
pub fn echo(args: &[Expr]) -> Result<Expr, Error> {
let output: Vec<String> = args.iter().map(format_value).collect();
let output = output.join(" ") + "\n";
for line in output.split_inclusive("\\n") {
if line.ends_with("\\n") {
let mut line: String = line.to_owned();
line.pop();
line.pop();
println!("{line}");
} else {
print!("{line}");
}
}
Ok(Expr::None)
}
pub fn setup_lib_io(context: &mut Context) {
let module = require_module("prelude", context);
module.insert_invocable("read", Expr::foreign_func_mut_context(&read_string));
module.insert_invocable("read$$String", Expr::foreign_func_mut_context(&read_string));
module.insert_invocable(
"read-string-all",
Expr::foreign_func_mut_context(&read_string_all),
);
module.insert_invocable(
"read-string-all$$String",
Expr::foreign_func_mut_context(&read_string_all),
);
module.insert_invocable("write", Expr::foreign_func(&write));
module.insert_invocable("write$$String", Expr::foreign_func(&write));
module.insert_invocable("writeln", Expr::foreign_func(&writeln));
module.insert_invocable("writeln$$String", Expr::foreign_func(&writeln));
module.insert_invocable("echo", Expr::foreign_func(&echo));
module.insert_invocable("echo$$String", Expr::foreign_func(&echo));
}