use std::sync::{Arc, Mutex};
use crate::parser::interpreter::{Interpreter, DynamicFn, DynamicFnInfo, PollerFn};
use crate::parser::types::{FunctionValue, Value, InkIteratorKind};
fn slog_direct(interp: &mut Interpreter, data: Value) -> Result<Value, String> {
if interp.is_verbose() {
eprintln!("[slog] => About to print data with a newline. data={:?}", data);
}
match data {
Value::InkIterator(handle) => {
if interp.is_verbose() {
eprintln!("[slog] => encountered InkIterator => register poller for non-blocking iteration");
}
let poller_handle = handle.clone();
let return_handle = handle;
let poller: PollerFn = Arc::new(Mutex::new(move |interp: &mut Interpreter| {
let mut items_printed = 0;
match &poller_handle.kind {
InkIteratorKind::Core(state_arc) => {
let mut guard = state_arc.lock().unwrap();
while !guard.done && guard.current < guard.end {
let item_val = guard.current;
guard.current += 1;
if guard.current >= guard.end {
guard.done = true;
}
drop(guard);
println!("{}", item_val);
interp.push_print(&format!("{}", item_val));
items_printed += 1;
break;
}
}
InkIteratorKind::Plugin(plugin_arc) => {
let mut plugin = plugin_arc.lock().unwrap();
match plugin.next_value() {
Ok(val) => {
println!("{}", item_val_to_string(&val));
interp.push_print(&item_val_to_string(&val));
items_printed += 1;
}
Err(e) if e == "NO_MORE_DATA" => {}
Err(e) => {
eprintln!("[slog] => transform error => {}", e);
}
}
}
}
if items_printed > 0 {
items_printed
} else {
0
}
}));
interp.add_poller(poller);
Ok(Value::InkIterator(return_handle))
}
Value::InkTransform(fb) => {
if interp.is_verbose() {
eprintln!("[slog] => encountered InkTransform => register poller for non-blocking iteration");
}
let poller_fb = fb.clone();
let return_fb = fb;
let poller: PollerFn = Arc::new(Mutex::new(move |interp: &mut Interpreter| {
let mut items_printed = 0;
match &*poller_fb {
FunctionValue::RustClosure(_desc, closure_arc, _arity) => {
let lock_cl = closure_arc.lock().unwrap();
match lock_cl(&mut *interp, vec![]) {
Ok(item_val) => {
let txt = format!("{}", item_val_to_string(&item_val));
println!("{}", txt);
interp.push_print(&txt);
items_printed += 1;
}
Err(e) => {
if e == "NO_MORE_DATA" {
} else {
eprintln!("[slog] => transform error => {}", e);
}
}
}
}
_ => {
}
}
if items_printed > 0 {
items_printed
} else {
0
}
}));
interp.add_poller(poller);
Ok(Value::InkTransform(return_fb))
}
other => {
let text = item_val_to_string(&other);
if interp.is_verbose() {
eprintln!("[slog] => printing => '{}\\n'", text);
}
println!("{}", text);
interp.push_print(&text);
Ok(other)
}
}
}
fn item_val_to_string(v: &Value) -> String {
match v {
Value::SingleString(s) => s.clone(),
Value::Int(i) => i.to_string(),
Value::Float(ff) => ff.to_string(),
Value::Bool(b) => b.to_string(),
Value::Long(l) => l.to_string(),
other => format!("{:?}", other),
}
}
fn slog_bridge_fn(interp: &mut Interpreter, mut args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("slog(...) => expected exactly 1 argument, got {}", args.len()));
}
let data = args.remove(0);
slog_direct(interp, data)
}
pub fn register_slog(interp: &mut Interpreter) {
if interp.is_verbose() {
eprintln!("[slog] => register_slog => setting up bridging for slog(...)");
}
let f: DynamicFn = Arc::new(Mutex::new(slog_bridge_fn));
let info = DynamicFnInfo::new(f, false);
interp.register_dynamic_function_ex("slog", info);
interp.set_variable(
"slog",
Value::Function(Box::new(FunctionValue::Named("slog".to_string())))
);
}