Add a return type to main
This commit is contained in:
parent
e1a0afba36
commit
a219faf283
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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> {
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -17,6 +17,6 @@ mod utils;
|
|||||||
|
|
||||||
mod error_handling;
|
mod error_handling;
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), ()> {
|
||||||
cli::run_cli();
|
cli::run_cli()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user