use crate::ast::AstGlobalAttr;
use crate::ast::common::{
AstBlock, AstGlobalBinding, AstGlobalBindingTarget, AstGlobalDecl, AstGlobalName, AstStmt,
};
use super::facts::MissingGlobals;
pub(super) fn insert_missing_global_decls(block: &mut AstBlock, missing: &MissingGlobals) {
let mut inserted = Vec::new();
if !missing.none.is_empty() {
inserted.push(build_global_decl(&missing.none, AstGlobalAttr::None));
}
if !missing.const_.is_empty() {
inserted.push(build_global_decl(&missing.const_, AstGlobalAttr::Const));
}
if inserted.is_empty() {
return;
}
let old_stmts = std::mem::take(&mut block.stmts);
let insert_at = old_stmts
.iter()
.take_while(|stmt| matches!(stmt, AstStmt::GlobalDecl(_)))
.count();
let mut new_stmts = Vec::with_capacity(old_stmts.len() + inserted.len());
new_stmts.extend(old_stmts.iter().take(insert_at).cloned());
new_stmts.extend(inserted);
new_stmts.extend(old_stmts.into_iter().skip(insert_at));
block.stmts = new_stmts;
}
pub(super) fn build_wildcard_global_decl(attr: AstGlobalAttr) -> AstStmt {
AstStmt::GlobalDecl(Box::new(AstGlobalDecl {
bindings: vec![AstGlobalBinding {
target: AstGlobalBindingTarget::Wildcard,
attr,
}],
values: Vec::new(),
}))
}
fn build_global_decl(names: &[String], attr: AstGlobalAttr) -> AstStmt {
AstStmt::GlobalDecl(Box::new(AstGlobalDecl {
bindings: names
.iter()
.cloned()
.map(|name| AstGlobalBinding {
target: AstGlobalBindingTarget::Name(AstGlobalName { text: name }),
attr,
})
.collect(),
values: Vec::new(),
}))
}