use leptonvm::cpu::*;
use leptonvm::parser::*;
use peg::{error::ParseError, str::LineCol};
use anyhow::Result;
use clap::Parser;
use std::path::PathBuf;
use std::fs;
const ITERATIONS: u32 = 4096*8;
#[derive(Parser, Debug)]
#[clap(author = "Ellie")]
struct Args {
#[clap(long, short)]
verbose: bool,
#[clap(long, short)]
playback: bool,
#[clap(parse(from_os_str))]
files: Vec<PathBuf>,
#[clap(long, short)]
iterations: Option<u32>
}
fn format_msg(e: ParseError::<LineCol>, input: &str, filename: &str) -> anyhow::Error {
let line_with_error = input.lines().nth(e.location.line - 1).unwrap();
let expected: Vec<&str> = e.expected.tokens().collect();
let msg = if expected.len() == 1 {
format!("Expected {}", expected[0])
} else {
format!("Expected one of {}", expected.join(", "))
};
let final_msg = format!("{}, found \"{}\"", msg, line_with_error.chars().nth(e.location.column -1).unwrap());
let mut output = String::new();
output.push_str(&format!("Error: {}:\n", final_msg));
output.push_str(&format!("--> {}:{}:{}\n", filename, e.location.line, e.location.column));
output.push_str(&format!("{} | {}\n", e.location.line, line_with_error));
output.push_str(&format!("{}^ {}", " ".repeat(e.location.column + (e.location.line as f32).log10() as usize + 3), msg));
anyhow::Error::msg(output)
}
fn main() -> Result<()> {
pretty_env_logger::init();
let args = Args::parse();
if args.files.len() < 2 {
return Err(anyhow::Error::msg::<&'static str>("USAGE: lepton [OPTIONS] QUARK1 QUARK2 [QUARKn...]".into()));
}
let mut programs: Vec<Program> = vec![];
for source in args.files {
let code = fs::read_to_string(&source)?;
match pcode::program(&code) {
Ok(program) => programs.push(program),
Err(e) => {
println!("{}", format_msg(e, &code, &source.to_string_lossy()));
std::process::exit(2);
}
};
}
let mut comp = Cpu::new(programs);
for _ in 0..args.iterations.unwrap_or(ITERATIONS) {
if comp.halted { break }
if args.playback {
println!("{:?}", serde_json::to_string(&comp).unwrap());
}
comp = comp.do_cycle();
}
if !comp.halted {
println!("Execution timed out; there is no winner");
println!("You could try to increase the number of iterations using `-i` (ran for {} iterations)", ITERATIONS);
}
Ok(())
}