Add a return type to main

master
Araozu 2024-03-01 16:52:32 -05:00
parent e1a0afba36
commit a219faf283
9 changed files with 69 additions and 37 deletions

View File

@ -26,6 +26,7 @@
- [x] Begin work on semantic analysis - [x] Begin work on semantic analysis
- [x] Minimal symbol table - [x] Minimal symbol table
- [x] Check duplicate function declarations - [x] Check duplicate function declarations
- [ ] Improve REPL/File compilation code
- [ ] Typecheck bindings - [ ] Typecheck bindings
- [ ] Typecheck functions - [ ] Typecheck functions
- [ ] Transform simple THP expression into PHP statements - [ ] Transform simple THP expression into PHP statements

View File

@ -1,19 +1,19 @@
use colored::*; use colored::*;
pub fn compile_command(arguments: Vec<String>) { pub fn compile_command(arguments: Vec<String>) -> Result<(), ()> {
if arguments.is_empty() { if arguments.is_empty() {
println!("{}", compile_help()); eprintln!("{}", compile_help());
println!("{}: {}", "error".on_red(), "No file specified"); eprintln!("{}: {}", "error".on_red(), "No file specified");
return; return Err(());
} }
if arguments.len() > 1 { if arguments.len() > 1 {
println!("{}", compile_help()); eprintln!("{}", compile_help());
println!( eprintln!(
"{}: {}", "{}: {}",
"error".on_red(), "error".on_red(),
"Only a single file can be compiled at a time" "Only a single file can be compiled at a time"
); );
return; return Err(());
} }
let argument = &arguments[0]; let argument = &arguments[0];
@ -23,16 +23,16 @@ pub fn compile_command(arguments: Vec<String>) {
println!("{}", compile_help()); println!("{}", compile_help());
if opt_str != "-h" && opt_str != "--help" { if opt_str != "-h" && opt_str != "--help" {
println!( eprintln!(
"{}: {}", "{}: {}",
"error".on_red(), "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 { fn compile_help() -> String {

View File

@ -7,7 +7,7 @@ enum EmptyOptions {
Version, Version,
} }
pub fn empty_command(arguments: Vec<String>) { pub fn empty_command(arguments: Vec<String>) -> Result<(), ()> {
// Add all options to a set // Add all options to a set
let mut options_set = std::collections::HashSet::new(); let mut options_set = std::collections::HashSet::new();
for option in arguments { for option in arguments {
@ -16,9 +16,9 @@ pub fn empty_command(arguments: Vec<String>) {
options_set.insert(o); options_set.insert(o);
} }
Err(invalid_option) => { Err(invalid_option) => {
println!("{}", get_help_text()); eprintln!("{}", get_help_text());
println!("{}: invalid option: `{}`", "error".on_red(), invalid_option); eprintln!("{}: invalid option: `{}`", "error".on_red(), invalid_option);
return; return Err(());
} }
}; };
} }
@ -35,6 +35,8 @@ pub fn empty_command(arguments: Vec<String>) {
println!("{}", get_help_text()); println!("{}", get_help_text());
} }
} }
Ok(())
} }
fn expand_option(option: &String) -> Result<EmptyOptions, String> { fn expand_option(option: &String) -> Result<EmptyOptions, String> {

View File

@ -1,7 +1,7 @@
use crate::cli::get_help_text; use crate::cli::get_help_text;
use colored::*; use colored::*;
pub fn help_command(arguments: Vec<String>) { pub fn help_command(arguments: Vec<String>) -> Result<(), ()> {
println!("{}", get_help_text()); println!("{}", get_help_text());
if arguments.len() > 0 { if arguments.len() > 0 {
@ -11,4 +11,6 @@ pub fn help_command(arguments: Vec<String>) {
"The help command doesn't take any argument." "The help command doesn't take any argument."
); );
} }
Ok(())
} }

View File

@ -40,17 +40,17 @@ fn get_version() -> String {
format!("The THP compiler, linter & formatter, v{}", crate_version) format!("The THP compiler, linter & formatter, v{}", crate_version)
} }
pub fn run_cli() { pub fn run_cli() -> Result<(), ()> {
let (command, args) = match parse_args() { let (command, args) = match parse_args() {
Ok(c) => c, Ok(c) => c,
Err(reason) => { Err(reason) => {
println!("{}", get_help_text()); eprintln!("{}", get_help_text());
println!("{}: {}", "error".on_red(), reason); eprintln!("{}: {}", "error".on_red(), reason);
return; return Err(());
} }
}; };
command.run(args); command.run(args)
} }
fn parse_args() -> Result<(CommandType, Vec<String>), String> { fn parse_args() -> Result<(CommandType, Vec<String>), String> {

View File

@ -1,4 +1,13 @@
pub fn repl_command(_arguments: Vec<String>) { use colored::Colorize;
pub fn repl_command(_arguments: Vec<String>) -> Result<(), ()> {
println!("{}", super::get_version()); 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(())
} }

View File

@ -12,14 +12,15 @@ pub enum CommandType {
} }
impl CommandType { impl CommandType {
pub fn run(&self, options: Vec<String>) { pub fn run(&self, options: Vec<String>) -> Result<(), ()> {
match self { match self {
CommandType::Help => super::help::help_command(options), CommandType::Help => super::help::help_command(options),
CommandType::Compile => super::compile::compile_command(options), CommandType::Compile => super::compile::compile_command(options),
CommandType::Repl => super::repl::repl_command(options), CommandType::Repl => super::repl::repl_command(options),
CommandType::None => super::empty::empty_command(options), CommandType::None => super::empty::empty_command(options),
_ => { _ => {
println!("Not implemented yet! {:?} {:?}", self, options); eprintln!("Not implemented yet! {:?} {:?}", self, options);
Err(())
} }
} }
} }

View File

@ -4,37 +4,54 @@ use std::{fs, path::Path};
use crate::lexic::token::Token; use crate::lexic::token::Token;
use crate::{codegen, error_handling::PrintableError, lexic, syntax}; 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); let input_path = Path::new(input);
if !input_path.is_file() { if !input_path.is_file() {
println!( eprintln!(
"{}: {} {}", "{}: {} {}",
"error".on_red(), "error".on_red(),
"Input path is not a valid file:".red(), "Input path is not a valid file:".red(),
input 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) { let contents = match String::from_utf8(bytes) {
Ok(str) => str, Ok(str) => str,
Err(_) => { Err(error) => {
println!("{}: Input file contains invalid UTF-8", "error".on_red()); eprintln!("{}: Input file contains invalid UTF-8", "error".on_red());
return; eprintln!("{}", error);
return Err(());
} }
}; };
let Some(out_code) = compile(&contents) else { 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"); 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 /// Executes Lexical analysis, handles errors and calls build_ast for the next phase

View File

@ -17,6 +17,6 @@ mod utils;
mod error_handling; mod error_handling;
fn main() { fn main() -> Result<(), ()> {
cli::run_cli(); cli::run_cli()
} }