//! Interpret the Lox language. Either compile (interpret for now though) some source code or run a //! REPL. use std::{ fs::{self}, io::{self, Write}, path::Path, }; use interpreter::Interpreter; use tracing::error; pub mod cli; pub mod environment; pub mod expression; pub mod interpreter; pub mod keywords; pub mod parser; pub mod scanner; pub mod statement; pub mod token; pub mod tokenizer { pub mod comment; pub mod identifier; pub mod interface; pub mod lookahead; pub mod newline; pub mod number; pub mod single_char; pub mod string; pub mod whitespace; } pub mod value; /// Read the source code in a file and scan it to tokens. pub fn compile(source: &Path) -> Result<(), io::Error> { let input = fs::read_to_string(source)?; let mut interpreter = Interpreter::default(); run(&input, &mut interpreter); Ok(()) } /// Run a Lox REPL until SIGINT. pub fn repl() { let mut interpreter = Interpreter::default(); loop { print!("> "); let _ = io::stdout().flush(); let mut input = String::new(); match io::stdin().read_line(&mut input) { Ok(_) => {} Err(e) => error!("{}", e), } let input = input.trim().to_string(); run(&input, &mut interpreter); } } /// Evaluate a Lox input string and print errors or output. fn run(input: &str, interpreter: &mut Interpreter) { let tokens = scanner::tokenize(input); match parser::ast(tokens) { Ok(ast) => match interpreter.run(ast) { Ok(_) => {} Err(e) => error!("{e}"), }, Err(e) => error!("{e}"), } }