use std::{ io::{BufRead, Write}, sync::{Arc, Mutex}, }; use crate::{ data::{ self, int::{INT_MAX, INT_MIN}, Data, MersDataWInfo, Type, }, program::{self, run::CheckInfo}, }; use super::{ gen::{ function::{func, func_err}, IntR, OneOrNone, }, Config, }; impl Config { /// `println: fn` prints to stdout and adds a newline to the end /// `print: fn` prints to stdout /// `eprintln: fn` prints to stderr and adds a newline to the end /// `eprint: fn` prints to stderr /// `debug: fn` debug-prints any value /// `read_line: fn` reads a line from stdin and returns it /// `exit: fn` exits the program with the given exit code. returns ``, just like `panic` pub fn with_stdio(self) -> Self { self // .add_var( // "read_line", // data::function::Function { // info: program::run::Info::neverused(), // info_check: Arc::new(Mutex::new(CheckInfo::neverused())), // out: Ok(Arc::new(|a, _i| { // if a.is_zero_tuple() { // Ok(Type::newm(vec![ // Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])), // Arc::new(data::tuple::TupleT(vec![])), // ])) // } else { // Err(CheckError::new().msg(vec![ // ("expected (), got ".to_owned(), None), // (a.to_string(), Some(EColor::FunctionArgument)), // ])) // } // })), // run: Arc::new(|_a, _i| { // Ok(if let Some(Ok(line)) = std::io::stdin().lines().next() { // Data::one_tuple(Data::new(data::string::String(line))) // } else { // Data::empty_tuple() // }) // }), // inner_statements: None, // }, // ) .add_var( "exit", func_err(|code: IntR, i| { if i.global .allow_process_exit_via_exit .load(std::sync::atomic::Ordering::Relaxed) { std::process::exit(code.0.try_into().unwrap_or(255)); } else { format!("Program exited with status code {}", code.0).into() } }), ) .add_var( "read_line", func(|_: (), i| { let next_line = if let Some(stdin) = &mut *i.global.stdin.lock().unwrap() { std::io::BufReader::new(stdin).lines().next() } else { std::io::stdin().lines().next() }; Ok(if let Some(Ok(line)) = next_line { OneOrNone(Some(line)) } else { OneOrNone(None) }) }), ) .add_var( "debug", data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), fixed_type: None, fixed_type_out: Arc::new(Mutex::new(None)), out: Ok(Arc::new(|a, _i| Ok(a.clone()))), run: Arc::new(|a, i| { let a2 = a.get(); let ty = a2.as_type(); let ty = ty.with_info(i); let v = a2.with_info(i); if let Some((_, stderr)) = &mut *i.global.stdout.lock().unwrap() { let _ = write!(stderr, "{ty} :: {v}"); let _ = stderr.flush(); } else { eprintln!("{ty} :: {v}"); } drop(a2); Ok(a) }), inner_statements: None, }, ) .add_var( "eprint", data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), fixed_type: None, fixed_type_out: Arc::new(Mutex::new(None)), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, i| { if let Some((_, stderr)) = &mut *i.global.stdout.lock().unwrap() { let _ = write!(stderr, "{}", a.get().with_info(i)); let _ = stderr.flush(); } else { eprint!("{}", a.get().with_info(i)); let _ = std::io::stderr().lock().flush(); } Ok(Data::empty_tuple()) }), inner_statements: None, }, ) .add_var( "eprintln", data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), fixed_type: None, fixed_type_out: Arc::new(Mutex::new(None)), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, i| { if let Some((_, stderr)) = &mut *i.global.stdout.lock().unwrap() { let _ = writeln!(stderr, "{}", a.get().with_info(i)); let _ = stderr.flush(); } else { eprintln!("{}", a.get().with_info(i)); } Ok(Data::empty_tuple()) }), inner_statements: None, }, ) .add_var( "print", data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), fixed_type: None, fixed_type_out: Arc::new(Mutex::new(None)), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, i| { if let Some((stdout, _)) = &mut *i.global.stdout.lock().unwrap() { let _ = write!(stdout, "{}", a.get().with_info(i)); let _ = stdout.flush(); } else { print!("{}", a.get().with_info(i)); let _ = std::io::stdout().lock().flush(); } Ok(Data::empty_tuple()) }), inner_statements: None, }, ) .add_var( "println", data::function::Function { info: program::run::Info::neverused(), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), fixed_type: None, fixed_type_out: Arc::new(Mutex::new(None)), out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))), run: Arc::new(|a, i| { if let Some((stdout, _)) = &mut *i.global.stdout.lock().unwrap() { let _ = writeln!(stdout, "{}", a.get().with_info(i)); let _ = stdout.flush(); } else { println!("{}", a.get().with_info(i)); } Ok(Data::empty_tuple()) }), inner_statements: None, }, ) } }