open Types
open Expressions
open GAst

let option_to_string (to_string : 'a -> string) (x : 'a option) : string =
  match x with
  | Some x -> "Some (" ^ to_string x ^ ")"
  | None -> "None"

let block_id_to_string (id : UllbcAst.BlockId.id) : string =
  "bb" ^ UllbcAst.BlockId.to_string id

(** The formatting environment can be incomplete: if some information is missing
    (for instance we can't find the type variable for a given index) we print
    the id in raw format. *)
type fmt_env = {
  crate : crate;
  generics : generic_params list;
      (** We have a stack of generic parameters, because we can dive into
          binders (for instance because of the arrow type). *)
  locals : (local_id * string option) list;
      (** The local variable display names don't need to be ordered (same as the
          generics). *)
}

let of_crate (crate : crate) : fmt_env = { crate; generics = []; locals = [] }

let fmt_env_push_generics_and_preds (env : fmt_env) (generics : generic_params)
    : fmt_env =
  { env with generics = generics :: env.generics }

let fmt_env_replace_generics_and_preds (env : fmt_env)
    (generics : generic_params) : fmt_env =
  { env with generics = [ generics ] }

let fmt_env_push_regions (env : fmt_env) (regions : region_param list) : fmt_env
    =
  {
    env with
    generics = { TypesUtils.empty_generic_params with regions } :: env.generics;
  }
