maslc 1.0.1

Maduka Authorization Specification Language (MASL) toolchain and runtime
use std::fs;
use std::path::PathBuf;
use std::process::exit;

use masl_compiler::{CompileError, compile};

use crate::diagnostics::print_diagnostics;

/// Checks a single `.mdk` file for errors without emitting output.
pub fn check_file(file: &std::path::Path) -> Result<(), ()> {
    let source = match fs::read_to_string(file) {
        Ok(s) => s,
        Err(e) => {
            eprintln!("Error reading file {}: {}", file.display(), e);
            return Err(());
        }
    };

    match compile(&source) {
        Ok(_) => {
            println!("{} is correct.", file.display());
            Ok(())
        }
        Err(e) => {
            let diags = match e {
                CompileError::ParseFailed(d) => d,
                CompileError::AnalysisFailed(d) => d,
                CompileError::ValidationFailed(d) => d,
                CompileError::LoweringFailed(d) => d,
                CompileError::BytecodeFailed(d) => d,
            };
            print_diagnostics(&diags, &source, file.to_str().unwrap_or(""));
            Err(())
        }
    }
}

/// Runs the `check` command over a file or directory.
pub fn run(path: PathBuf) {
    if path.is_dir() {
        let mut success = true;
        let read_dir = match fs::read_dir(&path) {
            Ok(rd) => rd,
            Err(e) => {
                eprintln!("Error reading directory {}: {}", path.display(), e);
                exit(1);
            }
        };
        for entry in read_dir {
            let file_path = entry.unwrap().path();
            if file_path.is_file()
                && file_path.extension().is_some_and(|ext| ext == "mdk")
                && check_file(&file_path).is_err()
            {
                success = false;
            }
        }
        if !success {
            exit(1);
        }
    } else if check_file(&path).is_err() {
        exit(1);
    }
}