use clap::{Parser, Subcommand}; use rustyline::{error::ReadlineError, DefaultEditor}; use mute_interpreter::{eval, Environment}; use mute_parser::parse_str; #[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 ast = match parse_str(&input) { Ok(ast) => ast, Err(err) => { println!("error: {}", err); return; } }; let res = eval(&env, ast); match res { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("{}", err), } } Command::RunCmd { command } => { let env = Environment::default(); let ast = match parse_str(&command) { Ok(ast) => ast, Err(err) => { println!("error: {}", err); return; } }; let res = eval(&env, ast); match res { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("{}", err), } } Command::Repl => repl(), } } 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(); let ast = match parse_str(&line) { Ok(ast) => ast, Err(err) => { println!("error: {}", err); continue; } }; let res = eval(&env, ast); match res { 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; } } } }