use anyhow::Result; use clap::{Parser, Subcommand}; use node::Node; use rustyline::{error::ReadlineError, DefaultEditor}; mod env; mod error; mod evaluator; mod macros; mod node; mod parser; #[derive(Debug, Parser)] #[clap(version, author, about)] struct Args { #[clap(subcommand)] command: Command, } #[derive(Debug, Subcommand)] enum Command { Run { #[clap(short, long)] command: String, }, Repl, } impl std::default::Default for Command { fn default() -> Self { Command::Repl } } fn main() { if std::env::args().len() == 1 { repl(); return; } let args = Args::parse(); match args.command { Command::Run { command } => { let res = run(&command); match res { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("{}", err), } } Command::Repl => repl(), } } fn run(command: &str) -> Result> { let env = env::Environment::new(); let ast = parser::parse_str(command)?; evaluator::eval(&env, ast) } fn repl() { let env = env::Environment::new(); 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 = parser::parse_str(&line).unwrap(); let res = evaluator::eval(&env, ast); match res { Ok(expressions) => expressions.into_iter().for_each(|expr| println!("{expr}")), Err(err) => println!("{}", err), } } Err(ReadlineError::Interrupted) => { continue; } Err(ReadlineError::Eof) => { break; } Err(err) => { println!("Error: {:?}", err); break; } } } }