#![feature(array_windows)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] #![feature(let_else)] use std::cell::RefCell; use std::io; use std::rc::Rc; use rustyline::validate::{ MatchingBracketValidator, ValidationContext, ValidationResult, Validator, }; use rustyline::Editor; use rustyline_derive::{Completer, Helper, Highlighter, Hinter}; mod ast; mod eval; #[allow(clippy::all)] mod grammar; mod prims; #[cfg(test)] mod tests; mod value; fn main() { let args = std::env::args().collect::>(); match &args[..] { [_] => repl(), [_, file] => run_file(file).unwrap(), _ => panic!("To many args `{:?}`", args), } } fn run_file(file: &str) -> io::Result<()> { let src = std::fs::read_to_string(file)?; let tree = grammar::FileParser::new().parse(&src).unwrap(); let env = Rc::new(RefCell::new(eval::default_env())); for i in tree { eval::eval(&i, Rc::clone(&env)).unwrap(); } Ok(()) } fn repl() { let mut rl = Editor::new(); rl.set_helper(Some(InputValidator { brackets: MatchingBracketValidator::new(), })); let env = Rc::new(RefCell::new(eval::default_env())); while let Ok(line) = rl.readline("> ") { rl.add_history_entry(&line); let tree = grammar::TreeParser::new().parse(&line).unwrap(); // dbg!(&tree); match eval::eval(&tree, Rc::clone(&env)) { Ok(v) => { // Cant use == because it will panic. This is the only // valid comparison to trap if !matches!(v, value::Value::Trap) { println!("{}", v) } } Err(e) => println!("! {}", e.0), } } } #[derive(Completer, Helper, Highlighter, Hinter)] struct InputValidator { brackets: MatchingBracketValidator, } impl Validator for InputValidator { fn validate(&self, ctx: &mut ValidationContext) -> rustyline::Result { self.brackets.validate(ctx) } }