use pnc_engine::Value;
use pnc_engine::parse;
use serde::Serialize;
use std::io;
use std::process::ExitCode;
#[derive(Serialize)]
struct JsonOutput {
input: String,
result: Option<Value>,
stack: Vec<Value>,
error: Option<String>,
}
pub fn eval_tokens(tokens: Vec<String>, json: bool) -> ExitCode {
let mut stack = Vec::new();
let line = tokens.join(" ");
match parse::eval_line(&mut stack, &line) {
Ok(()) => {
let top = stack.last().cloned();
if json {
let out = JsonOutput {
input: line.clone(),
result: top,
stack: stack.clone(),
error: None,
};
match serde_json::to_string(&out) {
Ok(s) => println!("{}", s),
Err(_) => return ExitCode::from(1),
}
} else if let Some(v) = stack.last() {
println!("{}", v);
}
ExitCode::SUCCESS
}
Err(e) => {
if json {
let out = JsonOutput {
input: line.clone(),
result: None,
stack: stack.clone(),
error: Some(e.to_string()),
};
match serde_json::to_string(&out) {
Ok(s) => println!("{}", s),
Err(_) => return ExitCode::from(1),
}
} else {
eprintln!("{}", e);
}
ExitCode::from(1)
}
}
}
pub fn eval_stdin(json: bool) -> ExitCode {
let mut line = String::new();
if io::stdin().read_line(&mut line).is_err() {
if json {
let out = JsonOutput {
input: String::new(),
result: None,
stack: Vec::new(),
error: Some("io error: failed to read stdin".to_string()),
};
if let Ok(s) = serde_json::to_string(&out) {
println!("{}", s);
}
} else {
eprintln!("failed to read stdin");
}
return ExitCode::from(1);
}
let mut input = line;
if input.ends_with('\n') {
input.pop();
if input.ends_with('\r') {
input.pop();
}
}
let mut stack = Vec::new();
match parse::eval_line(&mut stack, &input) {
Ok(()) => {
let top = stack.last().cloned();
if json {
let out = JsonOutput {
input: input.clone(),
result: top,
stack: stack.clone(),
error: None,
};
match serde_json::to_string(&out) {
Ok(s) => println!("{}", s),
Err(_) => return ExitCode::from(1),
}
} else if let Some(v) = stack.last() {
println!("{}", v);
}
ExitCode::SUCCESS
}
Err(e) => {
if json {
let out = JsonOutput {
input: input.clone(),
result: None,
stack: stack.clone(),
error: Some(e.to_string()),
};
match serde_json::to_string(&out) {
Ok(s) => println!("{}", s),
Err(_) => return ExitCode::from(1),
}
} else {
eprintln!("{}", e);
}
ExitCode::from(1)
}
}
}