//! 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 tracing::{error, info}; pub mod cli; pub mod expression; pub mod interpreter; pub mod keywords; pub mod parser; pub mod scanner; 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)?; run(&input); Ok(()) } /// Run a Lox REPL until SIGINT. pub fn repl() { 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); } } /// Evaluate a Lox input string and print errors or output. fn run(input: &str) { let tokens = scanner::tokenize(input); match parser::generate_ast(tokens) { Ok(ast) => match interpreter::evaluate(ast) { Ok(value) => println!("{value}"), Err(e) => error!("{e}"), }, Err(e) => error!("{e}"), } }