diff --git a/src/main.rs b/src/main.rs index ec41110..98cb9fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,40 @@ -use std::{env, fs, io::{self, Write}}; +use std::{env, fs, io::{self, Write}, process::ExitCode}; + +/// Error handler. Can be used to print error messages; will also retain the +/// current error status. +#[derive(Default, Debug)] +struct ErrorHandler { + had_error: bool +} + +impl ErrorHandler { + /// Check whether this handler reported an error. + pub fn had_error(&self) -> bool { + self.had_error + } + + /// Report an error. + pub fn error(&mut self, line: usize, message: &str) { + self.report(line, "", message) + } + + fn report(&mut self, line: usize, pos: &str, message: &str) { + self.had_error = true; + println!("[line {line}] Error{pos}: {message}") + } +} /// Execute a script. -fn run(_source: String) { - todo!(); +fn run(_source: String) -> ErrorHandler { + let error_handler = ErrorHandler::default(); + /* + let scanner = Scanner::new(source); + let tokens = scanner.scan_tokens(); + for token in tokens { + println!("{}", token); + } + */ + error_handler } /// Run the REPL. @@ -14,28 +46,31 @@ fn run_prompt() { print!("slox> "); stdout.flush().unwrap(); let n_read = stdin.read_line(&mut buffer).expect("Failed to read from stdin"); - match n_read { + let _ = match n_read { 0 => return, _ => run(buffer.clone()), - } + }; } } /// Load a file and run the script it contains. -fn run_file(file: &str) { +fn run_file(file: &str) -> ErrorHandler { let contents = fs::read_to_string(file).expect(&format!("Could not load {}", file)); run(contents) } /// Main program. Either load a script from a file, or start the REPL. -fn main() { +fn main() -> Result<(), ExitCode> { let args: Vec = env::args().skip(1).collect(); let n_args = args.len(); if n_args == 0 { run_prompt() } else if n_args == 1 { - run_file(&args[0]); + if run_file(&args[0]).had_error() { + return Err(ExitCode::from(65)); + } } else { println!("Usage: slox [script]"); } + Ok(()) }