use crate::hir::traverse::{
traverse_hir_call_children, traverse_hir_decision_children, traverse_hir_expr_children,
traverse_hir_lvalue_children, traverse_hir_stmt_children, traverse_hir_table_constructor_children,
};
use crate::hir::{HirBlock, HirExpr, HirModule, HirStmt};
#[derive(Default)]
pub(super) struct HirExitResiduals {
pub decisions: usize,
pub unresolved: usize,
pub fallback_unstructured: usize,
pub other_unstructured: usize,
}
impl HirExitResiduals {
pub fn has_soft_residuals(&self) -> bool {
self.decisions != 0
|| self.unresolved != 0
|| self.fallback_unstructured != 0
|| self.other_unstructured != 0
}
}
pub(super) fn collect_hir_exit_residuals(module: &HirModule) -> HirExitResiduals {
let mut residuals = HirExitResiduals::default();
for proto in &module.protos {
collect_block_residuals(&proto.body, &mut residuals);
}
residuals
}
fn collect_block_residuals(block: &HirBlock, residuals: &mut HirExitResiduals) {
for stmt in &block.stmts {
collect_stmt_residuals(stmt, residuals);
}
}
fn collect_stmt_residuals(stmt: &HirStmt, residuals: &mut HirExitResiduals) {
if let HirStmt::Unstructured(unstructured) = stmt {
if unstructured
.summary
.as_deref()
.is_some_and(|summary| summary.contains("fallback"))
{
residuals.fallback_unstructured += 1;
} else {
residuals.other_unstructured += 1;
}
}
traverse_hir_stmt_children!(
stmt,
iter = iter,
opt = as_ref,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); },
lvalue(lv) => {
traverse_hir_lvalue_children!(
lv,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); }
);
},
block(b) => { collect_block_residuals(b, residuals); },
call(c) => {
traverse_hir_call_children!(
c,
iter = iter,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); }
);
},
condition(cond) => { collect_expr_residuals(cond, residuals); }
);
}
fn collect_expr_residuals(expr: &HirExpr, residuals: &mut HirExitResiduals) {
match expr {
HirExpr::Decision(_) => residuals.decisions += 1,
HirExpr::Unresolved(_) => residuals.unresolved += 1,
_ => {}
}
traverse_hir_expr_children!(
expr,
iter = iter,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); },
call(c) => {
traverse_hir_call_children!(
c,
iter = iter,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); }
);
},
decision(d) => {
traverse_hir_decision_children!(
d,
iter = iter,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); },
condition(cond) => { collect_expr_residuals(cond, residuals); }
);
},
table_constructor(t) => {
traverse_hir_table_constructor_children!(
t,
iter = iter,
opt = as_ref,
borrow = [&],
expr(e) => { collect_expr_residuals(e, residuals); }
);
}
);
}
pub(super) fn emit_hir_warning(message: String) {
eprintln!("[unluac][hir-warning] {message}");
}