use regex::Regex;
use std::{
    env,
    io::Write,
    path::Path,
    process::{Command, Stdio},
};

fn main() {
    const FILE: &str = "src/codegen/irrt/irrt.c";
    println!("cargo:rerun-if-changed={}", FILE);

    /*
     * HACK: Sadly, clang doesn't let us emit generic LLVM bitcode.
     * Compiling for WASM32 and filtering the output with regex is the closest we can get.
     */

    const FLAG: &[&str] = &[
        "--target=wasm32",
        FILE,
        "-O3",
        "-emit-llvm",
        "-S",
        "-Wall",
        "-Wextra",
        "-Wno-implicit-function-declaration",
        "-o",
        "-",
    ];
    let output = Command::new("clang")
        .args(FLAG)
        .output()
        .map(|o| {
            assert!(o.status.success(), "{}", std::str::from_utf8(&o.stderr).unwrap());
            o
        })
        .unwrap();

    let output = std::str::from_utf8(&output.stdout).unwrap();
    let mut filtered_output = String::with_capacity(output.len());

    let regex_filter = regex::Regex::new(r"(?ms:^define.*?\}$)|(?m:^declare.*?$)").unwrap();
    for f in regex_filter.captures_iter(output) {
        assert!(f.len() == 1);
        filtered_output.push_str(&f[0]);
        filtered_output.push('\n');
    }

    let filtered_output = Regex::new("(#\\d+)|(, *![0-9A-Za-z.]+)|(![0-9A-Za-z.]+)|(!\".*?\")")
        .unwrap()
        .replace_all(&filtered_output, "");

    let mut llvm_as = Command::new("llvm-as")
        .stdin(Stdio::piped())
        .arg("-o")
        .arg(Path::new(&env::var("OUT_DIR").unwrap()).join("irrt.bc"))
        .spawn()
        .unwrap();
    llvm_as.stdin.as_mut().unwrap().write_all(filtered_output.as_bytes()).unwrap();
    assert!(llvm_as.wait().unwrap().success())
}