mod register_allocator;
pub mod generator;
mod arm_instr;
pub mod types;


#[cfg(test)]
mod tests {
    use std::io::BufRead;
    use std::path::Path;
    use std::fs::File;
    use std::io::Write;
    use crate::ast::parser::Parser;
    use crate::lexer::lexer::Lexer;
    use crate::utils::case_list::CaseList;
    use crate::utils::num_sequence::NumberSequence;
    use crate::ir::generator::Generator as IRGenerator;
    use crate::sema::analyzer::Analyzer;
    pub use super::generator::Generator as ASMGenerator;
    fn test_case(case_str: &str) {
        let case_sequence = NumberSequence::from_str(case_str).unwrap();
        let case_list = CaseList::from_dir(&Path::new("./testcases")).unwrap();
        let mut error_case_cnt = 0;
        for case_no in case_sequence {
            let case_path = case_list.get_case_path(case_no).unwrap();
            println!("{}", case_path.display());
            let file = File::open(&case_path).unwrap();
            let mut buf_reader = std::io::BufReader::new(file);
            let mut lexer = Lexer::new();
            let mut full_text = String::new();
            loop {
                let mut line = String::new();
                let bytes_read = buf_reader.read_line(&mut line).unwrap();
                if bytes_read == 0 {
                    break;
                }
                full_text.push_str(&line);
                lexer.parse_next_str(&line);
            }
            let (tokens, diagnostics) = lexer.finish();
            let mut is_error = false;
            if !diagnostics.is_empty() {
                diagnostics.print(&format!("{}", case_path.display()), &full_text);
                is_error = true;
            }
            let mut parser = Parser::new(tokens, diagnostics);
            let compile_unit = parser.parse();
            let case_name = case_list.get_case_name(case_no).unwrap().strip_suffix(".c").unwrap();
            if !parser.diagnostics.is_empty() {
                parser.diagnostics.print(&format!("{}", case_path.display()), &full_text);
                is_error = true;
            }
            let mut analyzer = Analyzer::new();
            let hir = analyzer.analyze(compile_unit);
            if !analyzer.get_diagnostics().is_empty() {
                analyzer.get_diagnostics().print(&format!("{}", case_path.display()), &full_text);
                is_error = true;
            }
            let mut generator = IRGenerator::new(&analyzer);
            let ir = generator.emit(hir);
            let mut asm_generator = ASMGenerator::new();
            asm_generator.emit(ir);
            let asm_text = asm_generator.to_text();
            let mut output_file = File::create(format!("output/{}.s", case_name)).unwrap();
            output_file.write_all(asm_text.as_bytes()).unwrap();
            if is_error {
                error_case_cnt += 1;
            }
        }
        if error_case_cnt > 0 {
            panic!("Found {} cases with errors", error_case_cnt);
        }

    }
    #[test]
    fn test_expr() {
        test_case("0-3,14-25");
        // test_case("0-3,14-25");
    }
    #[test]
    fn test_if_while() {
        test_case("26-32,34-41,46-51,57");
    }
    #[test]
    fn test_func() {
        test_case("12-13,58-60");
    }
}
