use super::*;
pub(super) fn pure_handler_bindings(
module: &Module,
) -> HashMap<typed_ir::Path, Vec<typed_ir::Path>> {
module
.bindings
.iter()
.filter_map(|binding| {
expr_pure_handler_consumes(&binding.body)
.map(|consumes| (binding.name.clone(), consumes))
})
.collect()
}
pub(super) fn expr_pure_handler_consumes(expr: &Expr) -> Option<Vec<typed_ir::Path>> {
match &expr.kind {
ExprKind::Handle { handler, .. }
if handler.residual_after.as_ref().is_some_and(effect_is_empty) =>
{
Some(handler.consumes.clone())
}
ExprKind::Lambda { body, .. }
| ExprKind::BindHere { expr: body }
| ExprKind::Thunk { expr: body, .. }
| ExprKind::LocalPushId { body, .. }
| ExprKind::AddId { thunk: body, .. }
| ExprKind::Coerce { expr: body, .. }
| ExprKind::Pack { expr: body, .. } => expr_pure_handler_consumes(body),
ExprKind::Block {
tail: Some(tail), ..
} => expr_pure_handler_consumes(tail),
ExprKind::Block { stmts, tail: None } => match stmts.last() {
Some(Stmt::Expr(expr)) => expr_pure_handler_consumes(expr),
_ => None,
},
_ => None,
}
}
pub(super) fn effect_path_sets_intersect(
left: &[typed_ir::Path],
right: &[typed_ir::Path],
) -> bool {
left.iter()
.any(|left| right.iter().any(|right| effect_paths_match(left, right)))
}