From a219faf28332b33017c0d68c56aa57adeb9ba2b9 Mon Sep 17 00:00:00 2001 From: Araozu Date: Fri, 1 Mar 2024 16:52:32 -0500 Subject: [PATCH] Add a return type to main --- CHANGELOG.md | 1 + src/cli/compile.rs | 22 +++++++++++----------- src/cli/empty.rs | 10 ++++++---- src/cli/help.rs | 4 +++- src/cli/mod.rs | 10 +++++----- src/cli/repl.rs | 13 +++++++++++-- src/cli/types.rs | 5 +++-- src/file/mod.rs | 37 +++++++++++++++++++++++++++---------- src/main.rs | 4 ++-- 9 files changed, 69 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 862e953..509e72e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - [x] Begin work on semantic analysis - [x] Minimal symbol table - [x] Check duplicate function declarations +- [ ] Improve REPL/File compilation code - [ ] Typecheck bindings - [ ] Typecheck functions - [ ] Transform simple THP expression into PHP statements diff --git a/src/cli/compile.rs b/src/cli/compile.rs index 802fdb0..785c317 100644 --- a/src/cli/compile.rs +++ b/src/cli/compile.rs @@ -1,19 +1,19 @@ use colored::*; -pub fn compile_command(arguments: Vec) { +pub fn compile_command(arguments: Vec) -> Result<(), ()> { if arguments.is_empty() { - println!("{}", compile_help()); - println!("{}: {}", "error".on_red(), "No file specified"); - return; + eprintln!("{}", compile_help()); + eprintln!("{}: {}", "error".on_red(), "No file specified"); + return Err(()); } if arguments.len() > 1 { - println!("{}", compile_help()); - println!( + eprintln!("{}", compile_help()); + eprintln!( "{}: {}", "error".on_red(), "Only a single file can be compiled at a time" ); - return; + return Err(()); } let argument = &arguments[0]; @@ -23,16 +23,16 @@ pub fn compile_command(arguments: Vec) { println!("{}", compile_help()); if opt_str != "-h" && opt_str != "--help" { - println!( + eprintln!( "{}: {}", "error".on_red(), - "Invalid option. The compile command only accepts the `-h` or `--help` option" + "Invalid option. The compile command only accepts the `-h` or `--help` options" ); } - return; + return Err(()); } - crate::file::compile_file(argument); + crate::file::compile_file(argument) } fn compile_help() -> String { diff --git a/src/cli/empty.rs b/src/cli/empty.rs index 9fb1410..8cf4d41 100644 --- a/src/cli/empty.rs +++ b/src/cli/empty.rs @@ -7,7 +7,7 @@ enum EmptyOptions { Version, } -pub fn empty_command(arguments: Vec) { +pub fn empty_command(arguments: Vec) -> Result<(), ()> { // Add all options to a set let mut options_set = std::collections::HashSet::new(); for option in arguments { @@ -16,9 +16,9 @@ pub fn empty_command(arguments: Vec) { options_set.insert(o); } Err(invalid_option) => { - println!("{}", get_help_text()); - println!("{}: invalid option: `{}`", "error".on_red(), invalid_option); - return; + eprintln!("{}", get_help_text()); + eprintln!("{}: invalid option: `{}`", "error".on_red(), invalid_option); + return Err(()); } }; } @@ -35,6 +35,8 @@ pub fn empty_command(arguments: Vec) { println!("{}", get_help_text()); } } + + Ok(()) } fn expand_option(option: &String) -> Result { diff --git a/src/cli/help.rs b/src/cli/help.rs index c259430..7ece4b0 100644 --- a/src/cli/help.rs +++ b/src/cli/help.rs @@ -1,7 +1,7 @@ use crate::cli::get_help_text; use colored::*; -pub fn help_command(arguments: Vec) { +pub fn help_command(arguments: Vec) -> Result<(), ()> { println!("{}", get_help_text()); if arguments.len() > 0 { @@ -11,4 +11,6 @@ pub fn help_command(arguments: Vec) { "The help command doesn't take any argument." ); } + + Ok(()) } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 133da1e..f0271a4 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -40,17 +40,17 @@ fn get_version() -> String { format!("The THP compiler, linter & formatter, v{}", crate_version) } -pub fn run_cli() { +pub fn run_cli() -> Result<(), ()> { let (command, args) = match parse_args() { Ok(c) => c, Err(reason) => { - println!("{}", get_help_text()); - println!("{}: {}", "error".on_red(), reason); - return; + eprintln!("{}", get_help_text()); + eprintln!("{}: {}", "error".on_red(), reason); + return Err(()); } }; - command.run(args); + command.run(args) } fn parse_args() -> Result<(CommandType, Vec), String> { diff --git a/src/cli/repl.rs b/src/cli/repl.rs index 7610b48..893d391 100644 --- a/src/cli/repl.rs +++ b/src/cli/repl.rs @@ -1,4 +1,13 @@ -pub fn repl_command(_arguments: Vec) { +use colored::Colorize; + +pub fn repl_command(_arguments: Vec) -> Result<(), ()> { println!("{}", super::get_version()); - let _ = crate::repl::run(); + let result = crate::repl::run(); + + if let Err(e) = result { + eprintln!("{}: {}", "error".on_red(), e); + return Err(()); + } + + Ok(()) } diff --git a/src/cli/types.rs b/src/cli/types.rs index 2c81e4b..be8bd9b 100644 --- a/src/cli/types.rs +++ b/src/cli/types.rs @@ -12,14 +12,15 @@ pub enum CommandType { } impl CommandType { - pub fn run(&self, options: Vec) { + pub fn run(&self, options: Vec) -> Result<(), ()> { match self { CommandType::Help => super::help::help_command(options), CommandType::Compile => super::compile::compile_command(options), CommandType::Repl => super::repl::repl_command(options), CommandType::None => super::empty::empty_command(options), _ => { - println!("Not implemented yet! {:?} {:?}", self, options); + eprintln!("Not implemented yet! {:?} {:?}", self, options); + Err(()) } } } diff --git a/src/file/mod.rs b/src/file/mod.rs index 6ddcae8..a2676bc 100644 --- a/src/file/mod.rs +++ b/src/file/mod.rs @@ -4,37 +4,54 @@ use std::{fs, path::Path}; use crate::lexic::token::Token; use crate::{codegen, error_handling::PrintableError, lexic, syntax}; -pub fn compile_file(input: &String) { +pub fn compile_file(input: &String) -> Result<(), ()> { let input_path = Path::new(input); if !input_path.is_file() { - println!( + eprintln!( "{}: {} {}", "error".on_red(), "Input path is not a valid file:".red(), input ); - return; + return Err(()); } - let bytes = fs::read(input_path).expect("INPUT_PATH should be valid"); + let bytes = match fs::read(input_path) { + Ok(bytes) => bytes, + Err(error) => { + eprintln!("{}: Error reading input file", "error".on_red()); + eprintln!("{}", error); + return Err(()); + } + }; let contents = match String::from_utf8(bytes) { Ok(str) => str, - Err(_) => { - println!("{}: Input file contains invalid UTF-8", "error".on_red()); - return; + Err(error) => { + eprintln!("{}: Input file contains invalid UTF-8", "error".on_red()); + eprintln!("{}", error); + return Err(()); } }; let Some(out_code) = compile(&contents) else { - return; + return Err(()); }; - let mut output_path = Path::new(input).canonicalize().unwrap(); + let mut output_path = Path::new(input) + .canonicalize() + .expect("Invalid input path: Cannot be canonicalized"); output_path.set_extension("php"); - fs::write(output_path, out_code).expect("Error writing to output path"); + match fs::write(output_path, out_code) { + Ok(_) => Ok(()), + Err(error) => { + eprintln!("{}: Error writing output file", "error".on_red()); + eprintln!("{}", error); + Err(()) + } + } } /// Executes Lexical analysis, handles errors and calls build_ast for the next phase diff --git a/src/main.rs b/src/main.rs index 9e3b281..b40994d 100755 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,6 @@ mod utils; mod error_handling; -fn main() { - cli::run_cli(); +fn main() -> Result<(), ()> { + cli::run_cli() }