delo 0.1.0

A statically typed, compiled-to-C programming language that can time-travel.
mod error;
mod ast;
mod frontend;
mod type_system;
mod backend;

use std::env;
use std::fs;
use std::path::Path;

use crate::backend::compiler_runner::CompilerRunner;
use crate::error::unwrap_or_exit;
use crate::frontend::scanner::Scanner;
pub use crate::frontend::parser::Parser;
use crate::type_system::type_checker::TypeChecker;
use crate::backend::code_generator::CodeGenerator;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        println!("Usage: delo <program.delo>");
        std::process::exit(64);
    }
    
    let file_path = &args[1];
    let file_content = fs::read_to_string(file_path).unwrap_or_else(|err| {
        eprintln!("Error reading file '{file_path}': {err}");
        std::process::exit(66);
    });
    let lines: Vec<&str> = file_content.lines().collect();

    let mut scanner = Scanner::new(file_content.clone());
    let tokens = unwrap_or_exit(scanner.scan_tokens(), &lines, file_path);
    
    let mut parser = Parser::new(tokens);
    let statements = unwrap_or_exit(parser.parse(), &lines, file_path);

    let mut type_checker = TypeChecker::new();
    let types = unwrap_or_exit(type_checker.check_program(&statements), &lines, file_path);

    let mut code_generator = CodeGenerator::new(&types);
    let c_src = unwrap_or_exit(code_generator.generate_program(&statements).map_err(|error| vec![error]), &lines, file_path);
    println!("{}", c_src);

    let path = Path::new(file_path);
    let file_name = path.file_stem().unwrap().to_string_lossy().to_string();
    let compiler_runner = CompilerRunner::new();
    let executable_path = unwrap_or_exit(compiler_runner.compile(&c_src, &file_name).map_err(|error| vec![error]), &lines, file_path);

    println!("COMPILATION SUCCESSFUL! Run the program with: {}", executable_path);
}