use rucc_session::{FileSystem, Options};
use crate::compile::{Artifact, Compiled, Temps};
use crate::preprocess::preprocess;
#[must_use]
pub fn assemble(opts: &Options, name: &str, cpp: bool, fs: &dyn FileSystem) -> Compiled {
let mut messages = Vec::new();
let mut deps = Vec::new();
let mut temps = Temps::default();
let text = if cpp {
let out = preprocess(opts, name, fs);
messages.extend(out.messages.iter().cloned());
deps = out.deps.clone();
if out.failed() {
return done(Artifact::Nothing, messages, 1, deps, temps);
}
temps.preprocessed = Some(out.text.clone());
out.text
} else {
match fs.read(std::path::Path::new(name)) {
Ok(bytes) => match String::from_utf8(bytes.to_vec()) {
Ok(text) => text,
Err(_) => {
messages.push(format!("rucc: error: {name}: this is not text"));
return done(Artifact::Nothing, messages, 1, deps, temps);
}
},
Err(e) => {
messages.push(format!("rucc: error: {name}: {e}"));
return done(Artifact::Nothing, messages, 1, deps, temps);
}
}
};
let assembled = match rucc_asm::read(&text) {
Ok(assembled) => assembled,
Err(trouble) => {
messages.push(format!("{name}:{}: error: {}", trouble.line, trouble.why));
return done(Artifact::Nothing, messages, 1, deps, temps);
}
};
let defines = rucc_object::assembled_defines(&assembled);
match rucc_object::assembled(&assembled, &rucc_target::TargetInfo::new(opts.target)) {
Ok(bytes) => done(Artifact::Object { bytes, defines }, messages, 0, deps, temps),
Err(e) => {
messages.push(format!("rucc: error: {name}: {e}"));
done(Artifact::Nothing, messages, 1, deps, temps)
}
}
}
fn done(
artifact: Artifact,
messages: Vec<String>,
errors: u32,
deps: Vec<rucc_pp::Dependency>,
temps: Temps,
) -> Compiled {
Compiled {
artifact,
messages,
errors,
fired: rucc_codegen::coverage::Fired::new(),
pressure: rucc_codegen::pressure::Pressure::new(),
lowerings: rucc_codegen::lowering::Lowerings::new(),
dumps: Vec::new(),
remarks: String::new(),
deps,
temps,
}
}