use crate::ir::{IrBlockStatement, IrExpr, IrFunction, IrSpan};
pub(in crate::ir::monomorphise) fn walk_function_spans_mut(
f: &mut IrFunction,
visit: &mut impl FnMut(&mut IrSpan),
) {
for p in &mut f.params {
visit(&mut p.span);
if let Some(d) = &mut p.default {
walk_expr_spans_mut(d, visit);
}
}
if let Some(body) = &mut f.body {
walk_expr_spans_mut(body, visit);
}
}
pub(in crate::ir::monomorphise) fn walk_expr_spans_mut(
expr: &mut IrExpr,
visit: &mut impl FnMut(&mut IrSpan),
) {
walk_expr_spans_mut_inner(expr, visit);
}
fn walk_expr_spans_mut_inner(expr: &mut IrExpr, visit: &mut impl FnMut(&mut IrSpan)) {
visit(expr.span_mut());
match expr {
IrExpr::Literal { .. }
| IrExpr::Reference { .. }
| IrExpr::SelfFieldRef { .. }
| IrExpr::LetRef { .. } => {}
IrExpr::StructInst { fields, .. } | IrExpr::EnumInst { fields, .. } => {
for (_, _, e) in fields {
walk_expr_spans_mut_inner(e, visit);
}
}
IrExpr::Tuple { fields, .. } => {
for (_, e) in fields {
walk_expr_spans_mut_inner(e, visit);
}
}
IrExpr::Array { elements, .. } => {
for e in elements {
walk_expr_spans_mut_inner(e, visit);
}
}
IrExpr::FieldAccess { object, .. } => walk_expr_spans_mut_inner(object, visit),
IrExpr::BinaryOp { left, right, .. } => {
walk_expr_spans_mut_inner(left, visit);
walk_expr_spans_mut_inner(right, visit);
}
IrExpr::UnaryOp { operand, .. } => walk_expr_spans_mut_inner(operand, visit),
IrExpr::If {
condition,
then_branch,
else_branch,
..
} => {
walk_expr_spans_mut_inner(condition, visit);
walk_expr_spans_mut_inner(then_branch, visit);
if let Some(e) = else_branch {
walk_expr_spans_mut_inner(e, visit);
}
}
IrExpr::For {
collection, body, ..
} => {
walk_expr_spans_mut_inner(collection, visit);
walk_expr_spans_mut_inner(body, visit);
}
IrExpr::Match {
scrutinee, arms, ..
} => {
walk_expr_spans_mut_inner(scrutinee, visit);
for arm in arms {
walk_expr_spans_mut_inner(&mut arm.body, visit);
}
}
IrExpr::FunctionCall { args, .. } => {
for (_, a) in args {
walk_expr_spans_mut_inner(a, visit);
}
}
IrExpr::CallClosure { closure, args, .. } => {
walk_expr_spans_mut_inner(closure, visit);
for (_, a) in args {
walk_expr_spans_mut_inner(a, visit);
}
}
IrExpr::MethodCall { receiver, args, .. } => {
walk_expr_spans_mut_inner(receiver, visit);
for (_, a) in args {
walk_expr_spans_mut_inner(a, visit);
}
}
IrExpr::DictLiteral { entries, .. } => {
for (k, v) in entries {
walk_expr_spans_mut_inner(k, visit);
walk_expr_spans_mut_inner(v, visit);
}
}
IrExpr::DictAccess { dict, key, .. } => {
walk_expr_spans_mut_inner(dict, visit);
walk_expr_spans_mut_inner(key, visit);
}
IrExpr::Block {
statements, result, ..
} => {
for stmt in statements {
walk_block_stmt_spans_mut(stmt, visit);
}
walk_expr_spans_mut_inner(result, visit);
}
IrExpr::Closure { body, .. } => walk_expr_spans_mut_inner(body, visit),
IrExpr::ClosureRef { env_struct, .. } => walk_expr_spans_mut_inner(env_struct, visit),
}
}
fn walk_block_stmt_spans_mut(stmt: &mut IrBlockStatement, visit: &mut impl FnMut(&mut IrSpan)) {
match stmt {
IrBlockStatement::Let { value, span, .. } => {
visit(span);
walk_expr_spans_mut_inner(value, visit);
}
IrBlockStatement::Assign {
target,
value,
span,
} => {
visit(span);
walk_expr_spans_mut_inner(target, visit);
walk_expr_spans_mut_inner(value, visit);
}
IrBlockStatement::Expr(e) => walk_expr_spans_mut_inner(e, visit),
}
}