let rec collect_dispatches_exprs exprs = List.iter collect_dispatches_expr exprs
and collect_dispatches_stmts stmts = List.iter collect_dispatches_stmt stmts
and collect_dispatches_expr (_, detail) = match detail with
    | This -> ()
    | Null -> ()
    | Id(_,_) -> ()
    | NewObj(_, _, args) -> collect_dispatches_exprs args
    | NewArr(arrtype, fname, args) -> collect_dispatch_arr arrtype fname args
    | Literal(_) -> ()
    | Assign(mem, data) -> collect_dispatches_exprs [mem; data]
    | Deref(arr, idx) -> collect_dispatches_exprs [arr; idx]
    | Field(obj, _) -> collect_dispatches_expr obj
    | Invoc(recvr, _, args) -> collect_dispatches_exprs (recvr::args)
    | Unop(_, expr) -> collect_dispatches_expr expr
    | Binop(l, _, r) -> collect_dispatches_exprs [l; r]
    | Refine(args, ret, switch) -> collect_dispatch args ret switch
    | Refinable(switch) -> collect_dispatch_on switch
and collect_dispatches_stmt = function
    | Decl(_, Some(expr), _) -> collect_dispatches_expr expr
    | Decl(_, None, _) -> ()
    | If(iflist, env) -> collect_dispatches_clauses iflist
    | While(pred, body, _) -> collect_dispatches_expr pred; collect_dispatches_stmts body
    | Expr(expr, _) -> collect_dispatches_expr expr
    | Return(Some(expr), _) -> collect_dispatches_expr expr
    | Super(_, _, args) -> collect_dispatches_exprs args
    | Return(None, _) -> ()
and collect_dispatches_clauses pieces =
    let (preds, bodies) = List.split pieces in
    collect_dispatches_exprs (Util.filter_option preds);
    collect_dispatches_stmts (List.flatten bodies)
and collect_dispatch args ret = function
    | Sast.Switch(klass, cases, dispatch) -> dispatches := (klass, ret, (List.map fst args), dispatch, cases)::(!dispatches);
    | Sast.Test(_, _, _) -> raise(Failure("Impossible (wrong switch -- compiler error)"))
and collect_dispatch_on = function
    | Sast.Test(klass, klasses, dispatchby) -> dispatchon := (klass, klasses, dispatchby)::(!dispatchon);
    | Sast.Switch(_, _, _) -> raise(Failure("Impossible (wrong switch -- compiler error)"))
and collect_dispatch_func func = collect_dispatches_stmts func.body
and collect_dispatch_arr arrtype fname args =
    dispatcharr := (arrtype, fname, args)::(!dispatcharr)