use clap::{Parser, Subcommand}; use rustyline::{error::ReadlineError, DefaultEditor}; use mute::{eval, parse, Environment, Node, Result}; #[derive(Debug, Parser)] #[clap(version, author, about)] struct Args { #[clap(subcommand)] command: Command, } #[derive(Debug, Subcommand)] enum Command { #[clap(name = "-c", about = "Run a program passed in as a string")] RunCmd { command: String }, #[clap(about = "Run a Mute file")] Run { file: String }, #[clap(about = "Start a REPL")] Repl, } fn main() { let args = Args::parse(); match args.command { Command::Run { file } => { let input = std::fs::read_to_string(file).unwrap(); let env = Environment::default(); let res = run(&env, &input); match res { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("{}", err), } } Command::RunCmd { command } => { let env = Environment::default(); let res = run(&env, &command); match res { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("{}", err), } } Command::Repl => repl(), } } fn run(env: &Environment, command: &str) -> Result> { let ast = parse(command)?; eval(env, ast) } fn repl() { let env = Environment::default(); let mut rl = DefaultEditor::new().unwrap(); println!("Mute -- REPL"); loop { let readline = rl.readline("> "); match readline { Ok(line) => { rl.add_history_entry(line.as_str()).unwrap(); match run(&env, &line) { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("error: {}", err), } } Err(ReadlineError::Interrupted) => { continue; } Err(ReadlineError::Eof) => { break; } Err(err) => { println!("Error: {:?}", err); break; } } } }