use rasm_core::{
    codegen::{CodeGen, CodegenOutput, err::CodegenError},
    lexer::Lexer,
    parser::{Parser, err::ParserError},
    src::SourceCode,
    str_pool::StrPool,
};

pub fn compile(code: &str) -> Result<CodegenOutput, String> {
    let source = SourceCode::new(code.to_string());
    let mut str_pool = StrPool::from_source(&source);

    let mut lexer = Lexer::new(&mut str_pool, source);
    lexer.tokenize();
    if !lexer.errors.is_empty() {
        return Err(format!("{:?}", lexer.errors));
    }

    let mut parser = Parser::new(&lexer.tokens, &mut str_pool);
    let ast = parser.parse();
    if !parser.errors.is_empty() {
        return Err(format_parser_errors(&parser.errors));
    }

    let mut codegen = CodeGen::new(&str_pool);
    let output = codegen.compile(&ast);
    if !codegen.errors.is_empty() {
        return Err(format_codegen_errors(&codegen.errors));
    }

    Ok(output)
}

fn format_parser_errors(errors: &[ParserError]) -> String {
    errors
        .iter()
        .map(ToString::to_string)
        .collect::<Vec<_>>()
        .join("\n")
}

fn format_codegen_errors(errors: &[CodegenError]) -> String {
    errors
        .iter()
        .map(ToString::to_string)
        .collect::<Vec<_>>()
        .join("\n")
}
