Fixpoint BDDof_bool_expr (cfg : BDDconfig) (ul : list ad) 
 (be : bool_expr) {struct be} : BDDconfig * ad :=
  match be with
  | Zero => (cfg, BDDzero)
  | One => (cfg, BDDone)
  | Var x => BDDvar_make gc cfg ul x
  | Neg be1 =>
      match BDDof_bool_expr cfg ul be1 with
      | (cfg1, node1) => BDDneg gc cfg1 (node1 :: ul) node1
      end
  | Or be1 be2 =>
      match BDDof_bool_expr cfg ul be1 with
      | (cfg1, node1) =>
          match BDDof_bool_expr cfg1 (node1 :: ul) be2 with
          | (cfg2, node2) => BDDor gc cfg2 (node2 :: node1 :: ul) node1 node2
          end
      end
  | ANd be1 be2 =>
      match BDDof_bool_expr cfg ul be1 with
      | (cfg1, node1) =>
          match BDDof_bool_expr cfg1 (node1 :: ul) be2 with
          | (cfg2, node2) =>
              BDDand gc cfg2 (node2 :: node1 :: ul) node1 node2
          end
      end
  | Impl be1 be2 =>
      match BDDof_bool_expr cfg ul be1 with
      | (cfg1, node1) =>
          match BDDof_bool_expr cfg1 (node1 :: ul) be2 with
          | (cfg2, node2) =>
              BDDimpl gc cfg2 (node2 :: node1 :: ul) node1 node2
          end
      end
  | Iff be1 be2 =>
      match BDDof_bool_expr cfg ul be1 with
      | (cfg1, node1) =>
          match BDDof_bool_expr cfg1 (node1 :: ul) be2 with
          | (cfg2, node2) =>
              BDDiff gc cfg2 (node2 :: node1 :: ul) node1 node2
          end
      end
  end.

(* Specifications: *)
Lemma BDDof_bool_expr_correct : forall (be : bool_expr) (cfg : BDDconfig) (ul : list ad), BDDconfig_OK cfg -> used_list_OK cfg ul -> BDDconfig_OK (fst (BDDof_bool_expr cfg ul be)) /\ used_nodes_preserved cfg (fst (BDDof_bool_expr cfg ul be)) ul /\ config_node_OK (fst (BDDof_bool_expr cfg ul be)) (snd (BDDof_bool_expr cfg ul be)) /\ bool_fun_eq (bool_fun_of_BDD (fst (BDDof_bool_expr cfg ul be)) (snd (BDDof_bool_expr cfg ul be))) (bool_fun_of_bool_expr be).
Lemma init_list_OK : forall cfg : BDDconfig, used_list_OK cfg nil.