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)