let opt_useless program =
  let rec check_expr e =
    match e.expr_val with
      | Var(f, l) ->
          (
            match f.var_def with
              | None -> failwith "internal error"
              | Some d ->
                  List.iter check_expr l;
                  match d.def_value with
                    | Function f ->
                        if not f.func_used then
                          (
                            f.func_used <- true;
                            check_block f.func_value
                          )
                    | _ -> () 
                        (** This is a variable. *)

          )
      | Arr(e1, e2)
      | Lt(e1, e2)
      | Le(e1, e2)
      | Eq(e1, e2)
      | Neq(e1, e2)
      | Or(e1, e2)
      | And(e1, e2)
      | Plus(e1, e2)
      | Minus(e1, e2)
      | Mult(e1, e2)
      | Div(e1, e2)
      | Mod(e1, e2) ->
          check_expr e1;
          check_expr e2
      | Rec(e, _)
      | Address_of e
      | Bang e
      | Not e
      | Uminus e ->
          check_expr e
      | New _
      | Int _
      | Bool _ -> ()
  and check_instr = function
    | Proc(p, l) ->
        let d =
          match p.var_def with
            | Some d -> d
            | None -> failwith "internal error"
        in
          (
            List.iter check_expr l;
            match d.def_value with
              | Function f ->
                  if not f.func_used then
                    (
                      f.func_used <- true;
                      check_block f.func_value
                    )
              | _ -> failwith "internal error"
          )
    | If(e, s1, s2) ->
        check_expr e;
        check_instr s1.stt_value;
        check_instr s2.stt_value
    | While(e, s) ->
        check_expr e;
        check_instr s.stt_value
    | Compound ss ->
        List.iter (fun s -> check_instr s.stt_value) ss
    | Assign(e1, e2) ->
        check_expr e1;
        check_expr e2
    | Delete e
    | Return e ->
        check_expr e
    | Noop -> ()
  and check_block block =
    List.iter (fun s -> check_instr s.stt_value) block.block_stts
  in
    check_block (snd program)