open Prims
type doc =
  | Doc of Prims.string 
let uu___is_Doc (projectee : doc) : Prims.bool= true
let __proj__Doc__item___0 (projectee : doc) : Prims.string=
  match projectee with | Doc _0 -> _0
type assoc =
  | ILeft 
  | IRight 
  | Left 
  | Right 
  | NonAssoc 
let uu___is_ILeft (projectee : assoc) : Prims.bool=
  match projectee with | ILeft -> true | uu___ -> false
let uu___is_IRight (projectee : assoc) : Prims.bool=
  match projectee with | IRight -> true | uu___ -> false
let uu___is_Left (projectee : assoc) : Prims.bool=
  match projectee with | Left -> true | uu___ -> false
let uu___is_Right (projectee : assoc) : Prims.bool=
  match projectee with | Right -> true | uu___ -> false
let uu___is_NonAssoc (projectee : assoc) : Prims.bool=
  match projectee with | NonAssoc -> true | uu___ -> false
type fixity =
  | Prefix 
  | Postfix 
  | Infix of assoc 
let uu___is_Prefix (projectee : fixity) : Prims.bool=
  match projectee with | Prefix -> true | uu___ -> false
let uu___is_Postfix (projectee : fixity) : Prims.bool=
  match projectee with | Postfix -> true | uu___ -> false
let uu___is_Infix (projectee : fixity) : Prims.bool=
  match projectee with | Infix _0 -> true | uu___ -> false
let __proj__Infix__item___0 (projectee : fixity) : assoc=
  match projectee with | Infix _0 -> _0
type opprec = (Prims.int * fixity)
type level = (opprec * assoc)
let t_prio_fun : (Prims.int * fixity)= ((Prims.of_int 10), (Infix Right))
let t_prio_tpl : (Prims.int * fixity)= ((Prims.of_int 20), (Infix NonAssoc))
let t_prio_name : (Prims.int * fixity)= ((Prims.of_int 30), Postfix)
let e_bin_prio_lambda : (Prims.int * fixity)= ((Prims.of_int 5), Prefix)
let e_bin_prio_if : (Prims.int * fixity)= ((Prims.of_int 15), Prefix)
let e_bin_prio_letin : (Prims.int * fixity)= ((Prims.of_int 19), Prefix)
let e_bin_prio_or : (Prims.int * fixity)= ((Prims.of_int 20), (Infix Left))
let e_bin_prio_and : (Prims.int * fixity)= ((Prims.of_int 25), (Infix Left))
let e_bin_prio_eq : (Prims.int * fixity)=
  ((Prims.of_int 27), (Infix NonAssoc))
let e_bin_prio_order : (Prims.int * fixity)=
  ((Prims.of_int 29), (Infix NonAssoc))
let e_bin_prio_op1 : (Prims.int * fixity)= ((Prims.of_int 30), (Infix Left))
let e_bin_prio_op2 : (Prims.int * fixity)= ((Prims.of_int 40), (Infix Left))
let e_bin_prio_op3 : (Prims.int * fixity)= ((Prims.of_int 50), (Infix Left))
let e_bin_prio_op4 : (Prims.int * fixity)= ((Prims.of_int 60), (Infix Left))
let e_bin_prio_comb : (Prims.int * fixity)= ((Prims.of_int 70), (Infix Left))
let e_bin_prio_seq : (Prims.int * fixity)= ((Prims.of_int 100), (Infix Left))
let e_app_prio : (Prims.int * fixity)= ((Prims.of_int 10000), (Infix Left))
let min_op_prec : (Prims.int * fixity)=
  ((Prims.of_int (-1)), (Infix NonAssoc))
let max_op_prec : (Prims.int * fixity)=
  (FStarC_Util.max_int, (Infix NonAssoc))
let empty : doc= Doc ""
let hardline : doc= Doc "\n"
let text (s : Prims.string) : doc= Doc s
let num (i : Prims.int) : doc=
  let uu___ = FStarC_Class_Show.show FStarC_Class_Show.showable_int i in
  Doc uu___
let break1 : doc= text " "
let enclose (uu___ : doc) (uu___1 : doc) (uu___2 : doc) : doc=
  match (uu___, uu___1, uu___2) with
  | (Doc l, Doc r, Doc x) -> Doc (Prims.strcat l (Prims.strcat x r))
let cbrackets (uu___ : doc) : doc=
  match uu___ with | Doc d -> enclose (text "{") (text "}") (Doc d)
let parens (uu___ : doc) : doc=
  match uu___ with | Doc d -> enclose (text "(") (text ")") (Doc d)
let cat (uu___ : doc) (uu___1 : doc) : doc=
  match (uu___, uu___1) with | (Doc d1, Doc d2) -> Doc (Prims.strcat d1 d2)
let reduce (docs : doc Prims.list) : doc=
  FStarC_List.fold_left cat empty docs
let combine (uu___ : doc) (docs : doc Prims.list) : doc=
  match uu___ with
  | Doc sep ->
      let select uu___1 =
        match uu___1 with
        | Doc d ->
            if d = ""
            then FStar_Pervasives_Native.None
            else FStar_Pervasives_Native.Some d in
      let docs1 = FStarC_List.choose select docs in
      Doc (FStarC_String.concat sep docs1)
let reduce1 (docs : doc Prims.list) : doc= combine break1 docs
let hbox (d : doc) : doc= d
let rec in_ns : 'a . ('a Prims.list * 'a Prims.list) -> Prims.bool =
  fun x ->
    match x with
    | ([], uu___) -> true
    | (x1::t1, x2::t2) when x1 = x2 -> in_ns (t1, t2)
    | (uu___, uu___1) -> false
let path_of_ns (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (ns : Prims.string Prims.list) : Prims.string Prims.list=
  let ns' = FStarC_Extraction_ML_Util.flatten_ns ns in
  if ns' = currentModule
  then []
  else
    (let cg_libs = FStarC_Options.codegen_libs () in
     let ns_len = FStarC_List.length ns in
     let found =
       FStarC_Util.find_map cg_libs
         (fun cg_path ->
            let cg_len = FStarC_List.length cg_path in
            if (FStarC_List.length cg_path) < ns_len
            then
              let uu___ = FStarC_Util.first_N cg_len ns in
              match uu___ with
              | (pfx, sfx) ->
                  (if pfx = cg_path
                   then
                     FStar_Pervasives_Native.Some
                       (FStarC_List.op_At pfx
                          [FStarC_Extraction_ML_Util.flatten_ns sfx])
                   else FStar_Pervasives_Native.None)
            else FStar_Pervasives_Native.None) in
     match found with
     | FStar_Pervasives_Native.None -> [ns']
     | FStar_Pervasives_Native.Some x -> x)
let mlpath_of_mlpath (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (x : FStarC_Extraction_ML_Syntax.mlpath) :
  FStarC_Extraction_ML_Syntax.mlpath=
  match FStarC_Extraction_ML_Syntax.string_of_mlpath x with
  | "Prims.Some" -> ([], "Some")
  | "Prims.None" -> ([], "None")
  | "Prims.op_Modulus" -> (["Prims"], "mod_f")
  | uu___ ->
      let uu___1 = x in
      (match uu___1 with
       | (ns, x1) -> let uu___2 = path_of_ns currentModule ns in (uu___2, x1))
let ptsym_of_symbol (s : FStarC_Extraction_ML_Syntax.mlsymbol) :
  FStarC_Extraction_ML_Syntax.mlsymbol=
  let uu___ =
    let uu___1 =
      let uu___2 = FStarC_String.get s Prims.int_zero in
      FStar_Char.lowercase uu___2 in
    let uu___2 = FStarC_String.get s Prims.int_zero in uu___1 <> uu___2 in
  if uu___ then Prims.strcat "l__" s else s
let ptsym (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (mlp : FStarC_Extraction_ML_Syntax.mlpath) :
  FStarC_Extraction_ML_Syntax.mlsymbol=
  if Prims.uu___is_Nil (FStar_Pervasives_Native.fst mlp)
  then ptsym_of_symbol (FStar_Pervasives_Native.snd mlp)
  else
    (let uu___ = mlpath_of_mlpath currentModule mlp in
     match uu___ with
     | (p, s) ->
         let uu___1 =
           let uu___2 = let uu___3 = ptsym_of_symbol s in [uu___3] in
           FStarC_List.op_At p uu___2 in
         FStarC_String.concat "." uu___1)
let ptctor (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (mlp : FStarC_Extraction_ML_Syntax.mlpath) :
  FStarC_Extraction_ML_Syntax.mlsymbol=
  let uu___ = mlpath_of_mlpath currentModule mlp in
  match uu___ with
  | (p, s) ->
      let s1 =
        let uu___1 =
          let uu___2 =
            let uu___3 = FStarC_String.get s Prims.int_zero in
            FStar_Char.uppercase uu___3 in
          let uu___3 = FStarC_String.get s Prims.int_zero in uu___2 <> uu___3 in
        if uu___1 then Prims.strcat "U__" s else s in
      FStarC_String.concat "." (FStarC_List.op_At p [s1])
let infix_prim_ops :
  (Prims.string * (Prims.int * fixity) * Prims.string) Prims.list=
  [("op_Addition", e_bin_prio_op1, "+");
  ("op_Subtraction", e_bin_prio_op1, "-");
  ("op_Star", e_bin_prio_op1, "*");
  ("op_Division", e_bin_prio_op1, "/");
  ("op_Equality", e_bin_prio_eq, "=");
  ("op_Colon_Equals", e_bin_prio_eq, ":=");
  ("op_disEquality", e_bin_prio_eq, "<>");
  ("op_AmpAmp", e_bin_prio_and, "&&");
  ("op_BarBar", e_bin_prio_or, "||");
  ("op_LessThanOrEqual", e_bin_prio_order, "<=");
  ("op_GreaterThanOrEqual", e_bin_prio_order, ">=");
  ("op_LessThan", e_bin_prio_order, "<");
  ("op_GreaterThan", e_bin_prio_order, ">")]
let prim_uni_ops (uu___ : unit) : (Prims.string * Prims.string) Prims.list=
  let op_minus =
    let uu___1 = FStarC_Extraction_ML_Util.codegen_fsharp () in
    if uu___1 then "-" else "~-" in
  [("op_Negation", "not");
  ("op_Minus", op_minus);
  ("op_Bang", "Support.ST.read")]
let prim_types (uu___ : unit) : 'uuuuu Prims.list= []
let prim_constructors : (Prims.string * Prims.string) Prims.list=
  [("Some", "Some"); ("None", "None"); ("Nil", "[]"); ("Cons", "::")]
let is_prims_ns (ns : FStarC_Extraction_ML_Syntax.mlsymbol Prims.list) :
  Prims.bool= (ns = ["Prims"]) || (ns = ["Fstarcompiler.Prims"])
let as_bin_op (uu___ : FStarC_Extraction_ML_Syntax.mlpath) :
  (FStarC_Extraction_ML_Syntax.mlsymbol * (Prims.int * fixity) *
    Prims.string) FStar_Pervasives_Native.option=
  match uu___ with
  | (ns, x) ->
      if is_prims_ns ns
      then
        FStarC_List.tryFind
          (fun uu___1 -> match uu___1 with | (y, uu___2, uu___3) -> x = y)
          infix_prim_ops
      else FStar_Pervasives_Native.None
let is_bin_op (p : FStarC_Extraction_ML_Syntax.mlpath) : Prims.bool=
  let uu___ = as_bin_op p in uu___ <> FStar_Pervasives_Native.None
let as_uni_op (uu___ : FStarC_Extraction_ML_Syntax.mlpath) :
  (FStarC_Extraction_ML_Syntax.mlsymbol * Prims.string)
    FStar_Pervasives_Native.option=
  match uu___ with
  | (ns, x) ->
      if is_prims_ns ns
      then
        let uu___1 = prim_uni_ops () in
        FStarC_List.tryFind
          (fun uu___2 -> match uu___2 with | (y, uu___3) -> x = y) uu___1
      else FStar_Pervasives_Native.None
let is_uni_op (p : FStarC_Extraction_ML_Syntax.mlpath) : Prims.bool=
  let uu___ = as_uni_op p in uu___ <> FStar_Pervasives_Native.None
let is_standard_type (p : FStarC_Extraction_ML_Syntax.mlpath) : Prims.bool=
  false
let as_standard_constructor (uu___ : FStarC_Extraction_ML_Syntax.mlpath) :
  (FStarC_Extraction_ML_Syntax.mlsymbol * Prims.string)
    FStar_Pervasives_Native.option=
  match uu___ with
  | (ns, x) ->
      if is_prims_ns ns
      then
        FStarC_List.tryFind
          (fun uu___1 -> match uu___1 with | (y, uu___2) -> x = y)
          prim_constructors
      else FStar_Pervasives_Native.None
let is_standard_constructor (p : FStarC_Extraction_ML_Syntax.mlpath) :
  Prims.bool=
  let uu___ = as_standard_constructor p in
  uu___ <> FStar_Pervasives_Native.None
let maybe_paren (uu___ : ((Prims.int * fixity) * assoc))
  (inner : (Prims.int * fixity)) (doc1 : doc) : doc=
  match uu___ with
  | (outer, side) ->
      let noparens _inner _outer side1 =
        let uu___1 = _inner in
        match uu___1 with
        | (pi, fi) ->
            let uu___2 = _outer in
            (match uu___2 with
             | (po, fo) ->
                 (pi > po) ||
                   ((match (fi, side1) with
                     | (Postfix, Left) -> true
                     | (Prefix, Right) -> true
                     | (Infix (Left), Left) ->
                         (pi = po) && (fo = (Infix Left))
                     | (Infix (Right), Right) ->
                         (pi = po) && (fo = (Infix Right))
                     | (Infix (Left), ILeft) ->
                         (pi = po) && (fo = (Infix Left))
                     | (Infix (Right), IRight) ->
                         (pi = po) && (fo = (Infix Right))
                     | (uu___3, NonAssoc) -> (pi = po) && (fi = fo)
                     | (uu___3, uu___4) -> false))) in
      if noparens inner outer side then doc1 else parens doc1
let escape_byte_hex (x : FStarC_BaseTypes.byte) : Prims.string=
  Prims.strcat "\\x" (FStarC_Util.hex_string_of_byte x)
let escape_char_hex (x : FStarC_BaseTypes.char) : Prims.string=
  escape_byte_hex (FStarC_Util.byte_of_char x)
let escape_or (fallback : FStarC_BaseTypes.char -> Prims.string)
  (uu___ : FStarC_BaseTypes.char) : Prims.string=
  if uu___ = 92
  then "\\\\"
  else
    if uu___ = 32
    then " "
    else
      if uu___ = 8
      then "\\b"
      else
        if uu___ = 9
        then "\\t"
        else
          if uu___ = 13
          then "\\r"
          else
            if uu___ = 10
            then "\\n"
            else
              if uu___ = 39
              then "\\'"
              else
                if uu___ = 34
                then "\\\""
                else
                  if FStarC_Util.is_letter_or_digit uu___
                  then FStarC_Util.string_of_char uu___
                  else
                    if FStarC_Util.is_punctuation uu___
                    then FStarC_Util.string_of_char uu___
                    else
                      if FStarC_Util.is_symbol uu___
                      then FStarC_Util.string_of_char uu___
                      else fallback uu___
let string_of_mlconstant (sctt : FStarC_Extraction_ML_Syntax.mlconstant) :
  Prims.string=
  match sctt with
  | FStarC_Extraction_ML_Syntax.MLC_Unit -> "()"
  | FStarC_Extraction_ML_Syntax.MLC_Bool true -> "true"
  | FStarC_Extraction_ML_Syntax.MLC_Bool false -> "false"
  | FStarC_Extraction_ML_Syntax.MLC_Char c ->
      let uu___ = FStarC_Extraction_ML_Util.codegen_fsharp () in
      if uu___
      then Prims.strcat "'" (Prims.strcat (FStarC_Util.string_of_char c) "'")
      else
        (let nc = FStar_Char.int_of_char c in
         let uu___1 =
           FStarC_Class_Show.show FStarC_Class_Show.showable_nat nc in
         Prims.strcat uu___1
           (if
              ((nc >= (Prims.of_int 32)) && (nc = (Prims.of_int 127))) &&
                (nc < (Prims.of_int 34))
            then
              Prims.strcat " (*"
                (Prims.strcat (FStarC_Util.string_of_char c) "*)")
            else ""))
  | FStarC_Extraction_ML_Syntax.MLC_Int
      (s, FStar_Pervasives_Native.Some
       (FStarC_Const.Signed, FStarC_Const.Int32))
      -> Prims.strcat s "l"
  | FStarC_Extraction_ML_Syntax.MLC_Int
      (s, FStar_Pervasives_Native.Some
       (FStarC_Const.Signed, FStarC_Const.Int64))
      -> Prims.strcat s "L"
  | FStarC_Extraction_ML_Syntax.MLC_Int
      (s, FStar_Pervasives_Native.Some (uu___, FStarC_Const.Int8)) -> s
  | FStarC_Extraction_ML_Syntax.MLC_Int
      (s, FStar_Pervasives_Native.Some (uu___, FStarC_Const.Int16)) -> s
  | FStarC_Extraction_ML_Syntax.MLC_Int
      (v, FStar_Pervasives_Native.Some (uu___, FStarC_Const.Sizet)) ->
      let z = Prims.strcat "(Prims.parse_int \"" (Prims.strcat v "\")") in
      Prims.strcat "(FStar_SizeT.uint_to_t (" (Prims.strcat z "))")
  | FStarC_Extraction_ML_Syntax.MLC_Int
      (v, FStar_Pervasives_Native.Some (s, w)) ->
      let sign =
        match s with
        | FStarC_Const.Signed -> "Int"
        | FStarC_Const.Unsigned -> "UInt" in
      let ws =
        match w with
        | FStarC_Const.Int8 -> "8"
        | FStarC_Const.Int16 -> "16"
        | FStarC_Const.Int32 -> "32"
        | FStarC_Const.Int64 -> "64" in
      let z = Prims.strcat "(Prims.parse_int \"" (Prims.strcat v "\")") in
      let u =
        match s with
        | FStarC_Const.Signed -> ""
        | FStarC_Const.Unsigned -> "u" in
      Prims.strcat "(FStar_"
        (Prims.strcat sign
           (Prims.strcat ws
              (Prims.strcat "."
                 (Prims.strcat u
                    (Prims.strcat "int_to_t (" (Prims.strcat z "))"))))))
  | FStarC_Extraction_ML_Syntax.MLC_Int (s, FStar_Pervasives_Native.None) ->
      Prims.strcat "(Prims.parse_int \"" (Prims.strcat s "\")")
  | FStarC_Extraction_ML_Syntax.MLC_Float d -> FStarC_Util.string_of_float d
  | FStarC_Extraction_ML_Syntax.MLC_String chars ->
      let uu___ =
        let uu___1 =
          FStarC_String.collect (escape_or FStarC_Util.string_of_char) chars in
        Prims.strcat uu___1 "\"" in
      Prims.strcat "\"" uu___
  | uu___ ->
      FStarC_Effect.failwith
        "TODO: extract integer constants properly into OCaml"
let string_of_etag (uu___ : FStarC_Extraction_ML_Syntax.e_tag) :
  Prims.string=
  match uu___ with
  | FStarC_Extraction_ML_Syntax.E_PURE -> ""
  | FStarC_Extraction_ML_Syntax.E_ERASABLE -> "Erased"
  | FStarC_Extraction_ML_Syntax.E_IMPURE -> "Impure"
let rec doc_of_mltype' (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (outer : level) (ty : FStarC_Extraction_ML_Syntax.mlty) : doc=
  match ty with
  | FStarC_Extraction_ML_Syntax.MLTY_Var x ->
      let escape_tyvar s =
        if FStarC_Util.starts_with s "'_"
        then FStarC_Util.replace_char s 95 117
        else s in
      text (escape_tyvar x)
  | FStarC_Extraction_ML_Syntax.MLTY_Tuple tys ->
      let doc1 =
        FStarC_List.map (doc_of_mltype currentModule (t_prio_tpl, Left)) tys in
      let doc2 =
        let uu___ = let uu___1 = combine (text " * ") doc1 in hbox uu___1 in
        parens uu___ in
      doc2
  | FStarC_Extraction_ML_Syntax.MLTY_Named (args, name) ->
      let args1 =
        match args with
        | [] -> empty
        | arg::[] -> doc_of_mltype currentModule (t_prio_name, Left) arg
        | uu___ ->
            let args2 =
              FStarC_List.map
                (doc_of_mltype currentModule (min_op_prec, NonAssoc)) args in
            let uu___1 =
              let uu___2 = combine (text ", ") args2 in hbox uu___2 in
            parens uu___1 in
      let name1 = ptsym currentModule name in
      let uu___ = reduce1 [args1; text name1] in hbox uu___
  | FStarC_Extraction_ML_Syntax.MLTY_Fun (t1, et, t2) ->
      let d1 = doc_of_mltype currentModule (t_prio_fun, Left) t1 in
      let d2 = doc_of_mltype currentModule (t_prio_fun, Right) t2 in
      let uu___ = let uu___1 = reduce1 [d1; text " -> "; d2] in hbox uu___1 in
      maybe_paren outer t_prio_fun uu___
  | FStarC_Extraction_ML_Syntax.MLTY_Top ->
      let uu___ = FStarC_Extraction_ML_Util.codegen_fsharp () in
      if uu___ then text "obj" else text "Obj.t"
  | FStarC_Extraction_ML_Syntax.MLTY_Erased -> text "unit"
and doc_of_mltype (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (outer : level) (ty : FStarC_Extraction_ML_Syntax.mlty) : doc=
  doc_of_mltype' currentModule outer
    (FStarC_Extraction_ML_Util.resugar_mlty ty)
let rec doc_of_expr (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (outer : level) (e : FStarC_Extraction_ML_Syntax.mlexpr) : doc=
  match e.FStarC_Extraction_ML_Syntax.expr with
  | FStarC_Extraction_ML_Syntax.MLE_Coerce (e1, t, t') ->
      let doc1 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
      let uu___ = FStarC_Extraction_ML_Util.codegen_fsharp () in
      if uu___
      then
        let uu___1 = reduce [text "Prims.unsafe_coerce "; doc1] in
        parens uu___1
      else
        (let uu___1 = reduce [text "Obj.magic "; parens doc1] in
         parens uu___1)
  | FStarC_Extraction_ML_Syntax.MLE_Seq es ->
      let docs =
        FStarC_List.map (doc_of_expr currentModule (min_op_prec, NonAssoc))
          es in
      let docs1 =
        FStarC_List.map (fun d -> reduce [d; text ";"; hardline]) docs in
      let uu___ = reduce docs1 in parens uu___
  | FStarC_Extraction_ML_Syntax.MLE_Const c ->
      let uu___ = string_of_mlconstant c in text uu___
  | FStarC_Extraction_ML_Syntax.MLE_Var x -> text x
  | FStarC_Extraction_ML_Syntax.MLE_Name path ->
      let uu___ = ptsym currentModule path in text uu___
  | FStarC_Extraction_ML_Syntax.MLE_Record (path, uu___, fields) ->
      let for1 uu___1 =
        match uu___1 with
        | (name, e1) ->
            let doc1 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
            let uu___2 =
              let uu___3 =
                let uu___4 = ptsym currentModule (path, name) in text uu___4 in
              [uu___3; text "="; doc1] in
            reduce1 uu___2 in
      let uu___1 =
        let uu___2 = FStarC_List.map for1 fields in
        combine (text "; ") uu___2 in
      cbrackets uu___1
  | FStarC_Extraction_ML_Syntax.MLE_CTor (ctor, []) ->
      let name =
        let uu___ = is_standard_constructor ctor in
        if uu___
        then
          let uu___1 =
            let uu___2 = as_standard_constructor ctor in
            FStarC_Option.must uu___2 in
          FStar_Pervasives_Native.snd uu___1
        else ptctor currentModule ctor in
      text name
  | FStarC_Extraction_ML_Syntax.MLE_CTor (ctor, args) ->
      let name =
        let uu___ = is_standard_constructor ctor in
        if uu___
        then
          let uu___1 =
            let uu___2 = as_standard_constructor ctor in
            FStarC_Option.must uu___2 in
          FStar_Pervasives_Native.snd uu___1
        else ptctor currentModule ctor in
      let args1 =
        FStarC_List.map (doc_of_expr currentModule (min_op_prec, NonAssoc))
          args in
      let doc1 =
        match (name, args1) with
        | ("::", x::xs::[]) -> reduce [parens x; text "::"; xs]
        | (uu___, uu___1) ->
            let uu___2 =
              let uu___3 =
                let uu___4 =
                  let uu___5 = combine (text ", ") args1 in parens uu___5 in
                [uu___4] in
              (text name) :: uu___3 in
            reduce1 uu___2 in
      maybe_paren outer e_app_prio doc1
  | FStarC_Extraction_ML_Syntax.MLE_Tuple es ->
      let docs =
        FStarC_List.map
          (fun x ->
             let uu___ = doc_of_expr currentModule (min_op_prec, NonAssoc) x in
             parens uu___) es in
      let docs1 = let uu___ = combine (text ", ") docs in parens uu___ in
      docs1
  | FStarC_Extraction_ML_Syntax.MLE_Let ((rec_, lets), body) ->
      let pre =
        if
          e.FStarC_Extraction_ML_Syntax.loc <>
            FStarC_Extraction_ML_Syntax.dummy_loc
        then
          let uu___ =
            let uu___1 =
              let uu___2 = doc_of_loc e.FStarC_Extraction_ML_Syntax.loc in
              [uu___2] in
            hardline :: uu___1 in
          reduce uu___
        else empty in
      let doc1 = doc_of_lets currentModule (rec_, false, lets) in
      let body1 = doc_of_expr currentModule (min_op_prec, NonAssoc) body in
      let uu___ =
        let uu___1 =
          let uu___2 =
            let uu___3 = let uu___4 = reduce1 [text "in"; body1] in [uu___4] in
            doc1 :: uu___3 in
          pre :: uu___2 in
        combine hardline uu___1 in
      parens uu___
  | FStarC_Extraction_ML_Syntax.MLE_App (e1, args) ->
      (match ((e1.FStarC_Extraction_ML_Syntax.expr), args) with
       | (FStarC_Extraction_ML_Syntax.MLE_Name p,
          {
            FStarC_Extraction_ML_Syntax.expr =
              FStarC_Extraction_ML_Syntax.MLE_Fun (uu___::[], scrutinee);
            FStarC_Extraction_ML_Syntax.mlty = uu___1;
            FStarC_Extraction_ML_Syntax.loc = uu___2;_}::{
                                                           FStarC_Extraction_ML_Syntax.expr
                                                             =
                                                             FStarC_Extraction_ML_Syntax.MLE_Fun
                                                             ({
                                                                FStarC_Extraction_ML_Syntax.mlbinder_name
                                                                  = arg;
                                                                FStarC_Extraction_ML_Syntax.mlbinder_ty
                                                                  = uu___3;
                                                                FStarC_Extraction_ML_Syntax.mlbinder_attrs
                                                                  = uu___4;_}::[],
                                                              possible_match);
                                                           FStarC_Extraction_ML_Syntax.mlty
                                                             = uu___5;
                                                           FStarC_Extraction_ML_Syntax.loc
                                                             = uu___6;_}::[])
           when
           ((FStarC_Extraction_ML_Syntax.string_of_mlpath p) =
              "FStarC.Effect.try_with")
             ||
             ((FStarC_Extraction_ML_Syntax.string_of_mlpath p) =
                "FStar.All.try_with")
           ->
           let branches =
             match possible_match with
             | {
                 FStarC_Extraction_ML_Syntax.expr =
                   FStarC_Extraction_ML_Syntax.MLE_Match
                   ({
                      FStarC_Extraction_ML_Syntax.expr =
                        FStarC_Extraction_ML_Syntax.MLE_Var arg';
                      FStarC_Extraction_ML_Syntax.mlty = uu___7;
                      FStarC_Extraction_ML_Syntax.loc = uu___8;_},
                    branches1);
                 FStarC_Extraction_ML_Syntax.mlty = uu___9;
                 FStarC_Extraction_ML_Syntax.loc = uu___10;_} when arg = arg'
                 -> branches1
             | e2 ->
                 [(FStarC_Extraction_ML_Syntax.MLP_Wild,
                    FStar_Pervasives_Native.None, e2)] in
           doc_of_expr currentModule outer
             {
               FStarC_Extraction_ML_Syntax.expr =
                 (FStarC_Extraction_ML_Syntax.MLE_Try (scrutinee, branches));
               FStarC_Extraction_ML_Syntax.mlty =
                 (possible_match.FStarC_Extraction_ML_Syntax.mlty);
               FStarC_Extraction_ML_Syntax.loc =
                 (possible_match.FStarC_Extraction_ML_Syntax.loc)
             }
       | (FStarC_Extraction_ML_Syntax.MLE_Name p, e11::e2::[]) when
           is_bin_op p -> doc_of_binop currentModule p e11 e2
       | (FStarC_Extraction_ML_Syntax.MLE_App
          ({
             FStarC_Extraction_ML_Syntax.expr =
               FStarC_Extraction_ML_Syntax.MLE_Name p;
             FStarC_Extraction_ML_Syntax.mlty = uu___;
             FStarC_Extraction_ML_Syntax.loc = uu___1;_},
           unitVal::[]),
          e11::e2::[]) when
           let uu___2 = is_bin_op p in
           if uu___2
           then unitVal = FStarC_Extraction_ML_Syntax.ml_unit
           else false -> doc_of_binop currentModule p e11 e2
       | (FStarC_Extraction_ML_Syntax.MLE_Name p, e11::[]) when is_uni_op p
           -> doc_of_uniop currentModule p e11
       | (FStarC_Extraction_ML_Syntax.MLE_App
          ({
             FStarC_Extraction_ML_Syntax.expr =
               FStarC_Extraction_ML_Syntax.MLE_Name p;
             FStarC_Extraction_ML_Syntax.mlty = uu___;
             FStarC_Extraction_ML_Syntax.loc = uu___1;_},
           unitVal::[]),
          e11::[]) when
           let uu___2 = is_uni_op p in
           if uu___2
           then unitVal = FStarC_Extraction_ML_Syntax.ml_unit
           else false -> doc_of_uniop currentModule p e11
       | uu___ ->
           let e2 = doc_of_expr currentModule (e_app_prio, ILeft) e1 in
           let args1 =
             FStarC_List.map (doc_of_expr currentModule (e_app_prio, IRight))
               args in
           let uu___1 = reduce1 (e2 :: args1) in parens uu___1)
  | FStarC_Extraction_ML_Syntax.MLE_Proj (e1, f) ->
      let e2 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
      let doc1 =
        let uu___ = FStarC_Extraction_ML_Util.codegen_fsharp () in
        if uu___
        then reduce [e2; text "."; text (FStar_Pervasives_Native.snd f)]
        else
          (let uu___1 =
             let uu___2 =
               let uu___3 =
                 let uu___4 =
                   let uu___5 = ptsym currentModule f in text uu___5 in
                 [uu___4] in
               (text ".") :: uu___3 in
             e2 :: uu___2 in
           reduce uu___1) in
      doc1
  | FStarC_Extraction_ML_Syntax.MLE_Fun (ids, body) ->
      let bvar_annot x xt =
        let uu___ = FStarC_Extraction_ML_Util.codegen_fsharp () in
        if uu___
        then
          let uu___1 =
            let uu___2 =
              let uu___3 =
                let uu___4 =
                  match xt with
                  | FStar_Pervasives_Native.Some xxt ->
                      let uu___5 =
                        let uu___6 =
                          let uu___7 = doc_of_mltype currentModule outer xxt in
                          [uu___7] in
                        (text " : ") :: uu___6 in
                      reduce1 uu___5
                  | uu___5 -> text "" in
                [uu___4; text ")"] in
              (text x) :: uu___3 in
            (text "(") :: uu___2 in
          reduce1 uu___1
        else text x in
      let ids1 =
        FStarC_List.map
          (fun uu___ ->
             match uu___ with
             | { FStarC_Extraction_ML_Syntax.mlbinder_name = x;
                 FStarC_Extraction_ML_Syntax.mlbinder_ty = xt;
                 FStarC_Extraction_ML_Syntax.mlbinder_attrs = uu___1;_} ->
                 bvar_annot x (FStar_Pervasives_Native.Some xt)) ids in
      let body1 = doc_of_expr currentModule (min_op_prec, NonAssoc) body in
      let doc1 =
        let uu___ =
          let uu___1 =
            let uu___2 = reduce1 ids1 in [uu___2; text "->"; body1] in
          (text "fun") :: uu___1 in
        reduce1 uu___ in
      parens doc1
  | FStarC_Extraction_ML_Syntax.MLE_If
      (cond, e1, FStar_Pervasives_Native.None) ->
      let cond1 = doc_of_expr currentModule (min_op_prec, NonAssoc) cond in
      let doc1 =
        let uu___ =
          let uu___1 = reduce1 [text "if"; cond1; text "then"; text "begin"] in
          let uu___2 =
            let uu___3 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
            [uu___3; text "end"] in
          uu___1 :: uu___2 in
        combine hardline uu___ in
      maybe_paren outer e_bin_prio_if doc1
  | FStarC_Extraction_ML_Syntax.MLE_If
      (cond, e1, FStar_Pervasives_Native.Some e2) ->
      let cond1 = doc_of_expr currentModule (min_op_prec, NonAssoc) cond in
      let doc1 =
        let uu___ =
          let uu___1 = reduce1 [text "if"; cond1; text "then"; text "begin"] in
          let uu___2 =
            let uu___3 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
            let uu___4 =
              let uu___5 = reduce1 [text "end"; text "else"; text "begin"] in
              let uu___6 =
                let uu___7 =
                  doc_of_expr currentModule (min_op_prec, NonAssoc) e2 in
                [uu___7; text "end"] in
              uu___5 :: uu___6 in
            uu___3 :: uu___4 in
          uu___1 :: uu___2 in
        combine hardline uu___ in
      maybe_paren outer e_bin_prio_if doc1
  | FStarC_Extraction_ML_Syntax.MLE_Match (cond, pats) ->
      let cond1 = doc_of_expr currentModule (min_op_prec, NonAssoc) cond in
      let pats1 = FStarC_List.map (doc_of_branch currentModule) pats in
      let doc1 =
        let uu___ = reduce1 [text "match"; parens cond1; text "with"] in
        uu___ :: pats1 in
      let doc2 = combine hardline doc1 in parens doc2
  | FStarC_Extraction_ML_Syntax.MLE_Raise (exn, []) ->
      let uu___ =
        let uu___1 =
          let uu___2 = let uu___3 = ptctor currentModule exn in text uu___3 in
          [uu___2] in
        (text "raise") :: uu___1 in
      reduce1 uu___
  | FStarC_Extraction_ML_Syntax.MLE_Raise (exn, args) ->
      let args1 =
        FStarC_List.map (doc_of_expr currentModule (min_op_prec, NonAssoc))
          args in
      let uu___ =
        let uu___1 =
          let uu___2 = let uu___3 = ptctor currentModule exn in text uu___3 in
          let uu___3 =
            let uu___4 =
              let uu___5 = combine (text ", ") args1 in parens uu___5 in
            [uu___4] in
          uu___2 :: uu___3 in
        (text "raise") :: uu___1 in
      reduce1 uu___
  | FStarC_Extraction_ML_Syntax.MLE_Try (e1, pats) ->
      let uu___ =
        let uu___1 =
          let uu___2 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
          let uu___3 =
            let uu___4 =
              let uu___5 =
                let uu___6 =
                  FStarC_List.map (doc_of_branch currentModule) pats in
                combine hardline uu___6 in
              [uu___5] in
            (text "with") :: uu___4 in
          uu___2 :: uu___3 in
        (text "try") :: uu___1 in
      combine hardline uu___
  | FStarC_Extraction_ML_Syntax.MLE_TApp (head, ty_args) ->
      doc_of_expr currentModule outer head
and doc_of_binop (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (p : FStarC_Extraction_ML_Syntax.mlpath)
  (e1 : FStarC_Extraction_ML_Syntax.mlexpr)
  (e2 : FStarC_Extraction_ML_Syntax.mlexpr) : doc=
  let uu___ = let uu___1 = as_bin_op p in FStarC_Option.must uu___1 in
  match uu___ with
  | (uu___1, prio, txt) ->
      let e11 = doc_of_expr currentModule (prio, Left) e1 in
      let e21 = doc_of_expr currentModule (prio, Right) e2 in
      let doc1 = reduce1 [e11; text txt; e21] in parens doc1
and doc_of_uniop (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (p : FStarC_Extraction_ML_Syntax.mlpath)
  (e1 : FStarC_Extraction_ML_Syntax.mlexpr) : doc=
  let uu___ = let uu___1 = as_uni_op p in FStarC_Option.must uu___1 in
  match uu___ with
  | (uu___1, txt) ->
      let e11 = doc_of_expr currentModule (min_op_prec, NonAssoc) e1 in
      let doc1 = reduce1 [text txt; parens e11] in parens doc1
and doc_of_pattern (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (pattern : FStarC_Extraction_ML_Syntax.mlpattern) : doc=
  match pattern with
  | FStarC_Extraction_ML_Syntax.MLP_Wild -> text "_"
  | FStarC_Extraction_ML_Syntax.MLP_Const c ->
      let uu___ = string_of_mlconstant c in text uu___
  | FStarC_Extraction_ML_Syntax.MLP_Var x -> text x
  | FStarC_Extraction_ML_Syntax.MLP_Record (path, fields) ->
      let for1 uu___ =
        match uu___ with
        | (name, p) ->
            let uu___1 =
              let uu___2 =
                let uu___3 = ptsym currentModule (path, name) in text uu___3 in
              let uu___3 =
                let uu___4 =
                  let uu___5 = doc_of_pattern currentModule p in [uu___5] in
                (text "=") :: uu___4 in
              uu___2 :: uu___3 in
            reduce1 uu___1 in
      let uu___ =
        let uu___1 = FStarC_List.map for1 fields in
        combine (text "; ") uu___1 in
      cbrackets uu___
  | FStarC_Extraction_ML_Syntax.MLP_CTor (ctor, []) ->
      let name =
        let uu___ = is_standard_constructor ctor in
        if uu___
        then
          let uu___1 =
            let uu___2 = as_standard_constructor ctor in
            FStarC_Option.must uu___2 in
          FStar_Pervasives_Native.snd uu___1
        else ptctor currentModule ctor in
      text name
  | FStarC_Extraction_ML_Syntax.MLP_CTor (ctor, pats) ->
      let name =
        let uu___ = is_standard_constructor ctor in
        if uu___
        then
          let uu___1 =
            let uu___2 = as_standard_constructor ctor in
            FStarC_Option.must uu___2 in
          FStar_Pervasives_Native.snd uu___1
        else ptctor currentModule ctor in
      let doc1 =
        match (name, pats) with
        | ("::", x::xs::[]) ->
            let uu___ =
              let uu___1 =
                let uu___2 = doc_of_pattern currentModule x in parens uu___2 in
              let uu___2 =
                let uu___3 =
                  let uu___4 = doc_of_pattern currentModule xs in [uu___4] in
                (text "::") :: uu___3 in
              uu___1 :: uu___2 in
            reduce uu___
        | (uu___, (FStarC_Extraction_ML_Syntax.MLP_Tuple uu___1)::[]) ->
            let uu___2 =
              let uu___3 =
                let uu___4 =
                  doc_of_pattern currentModule (FStarC_List.hd pats) in
                [uu___4] in
              (text name) :: uu___3 in
            reduce1 uu___2
        | uu___ ->
            let uu___1 =
              let uu___2 =
                let uu___3 =
                  let uu___4 =
                    let uu___5 =
                      FStarC_List.map (doc_of_pattern currentModule) pats in
                    combine (text ", ") uu___5 in
                  parens uu___4 in
                [uu___3] in
              (text name) :: uu___2 in
            reduce1 uu___1 in
      maybe_paren (min_op_prec, NonAssoc) e_app_prio doc1
  | FStarC_Extraction_ML_Syntax.MLP_Tuple ps ->
      let ps1 = FStarC_List.map (doc_of_pattern currentModule) ps in
      let uu___ = combine (text ", ") ps1 in parens uu___
  | FStarC_Extraction_ML_Syntax.MLP_Branch ps ->
      let ps1 = FStarC_List.map (doc_of_pattern currentModule) ps in
      let ps2 = FStarC_List.map parens ps1 in combine (text " | ") ps2
and doc_of_branch (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (br : FStarC_Extraction_ML_Syntax.mlbranch) : doc=
  let uu___ = br in
  match uu___ with
  | (p, cond, e) ->
      let case =
        match cond with
        | FStar_Pervasives_Native.None ->
            let uu___1 =
              let uu___2 =
                let uu___3 = doc_of_pattern currentModule p in [uu___3] in
              (text "|") :: uu___2 in
            reduce1 uu___1
        | FStar_Pervasives_Native.Some c ->
            let c1 = doc_of_expr currentModule (min_op_prec, NonAssoc) c in
            let uu___1 =
              let uu___2 =
                let uu___3 = doc_of_pattern currentModule p in
                [uu___3; text "when"; c1] in
              (text "|") :: uu___2 in
            reduce1 uu___1 in
      let uu___1 =
        let uu___2 = reduce1 [case; text "->"; text "begin"] in
        let uu___3 =
          let uu___4 = doc_of_expr currentModule (min_op_prec, NonAssoc) e in
          [uu___4; text "end"] in
        uu___2 :: uu___3 in
      combine hardline uu___1
and doc_of_lets (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (arg :
    (FStarC_Extraction_ML_Syntax.mlletflavor * Prims.bool *
      FStarC_Extraction_ML_Syntax.mllb Prims.list))
  : doc=
  let uu___ = arg in
  match uu___ with
  | (rec_, top_level, lets) ->
      let for1 uu___1 =
        match uu___1 with
        | { FStarC_Extraction_ML_Syntax.mllb_name = name;
            FStarC_Extraction_ML_Syntax.mllb_tysc = tys;
            FStarC_Extraction_ML_Syntax.mllb_add_unit = uu___2;
            FStarC_Extraction_ML_Syntax.mllb_def = e;
            FStarC_Extraction_ML_Syntax.mllb_attrs = uu___3;
            FStarC_Extraction_ML_Syntax.mllb_meta = uu___4;
            FStarC_Extraction_ML_Syntax.print_typ = pt;_} ->
            let e1 = doc_of_expr currentModule (min_op_prec, NonAssoc) e in
            let ids = [] in
            let ty_annot =
              if Prims.op_Negation pt
              then text ""
              else
                (let uu___5 =
                   let uu___6 = FStarC_Extraction_ML_Util.codegen_fsharp () in
                   if uu___6
                   then (rec_ = FStarC_Extraction_ML_Syntax.Rec) || top_level
                   else false in
                 if uu___5
                 then
                   match tys with
                   | FStar_Pervasives_Native.Some (uu___6::uu___7, uu___8) ->
                       text ""
                   | FStar_Pervasives_Native.None -> text ""
                   | FStar_Pervasives_Native.Some ([], ty) ->
                       let ty1 =
                         doc_of_mltype currentModule (min_op_prec, NonAssoc)
                           ty in
                       reduce1 [text ":"; ty1]
                 else
                   if top_level
                   then
                     (match tys with
                      | FStar_Pervasives_Native.None -> text ""
                      | FStar_Pervasives_Native.Some ([], ty) ->
                          let ty1 =
                            doc_of_mltype currentModule
                              (min_op_prec, NonAssoc) ty in
                          reduce1 [text ":"; ty1]
                      | FStar_Pervasives_Native.Some (vs, ty) ->
                          let ty1 =
                            doc_of_mltype currentModule
                              (min_op_prec, NonAssoc) ty in
                          let vars =
                            let uu___6 =
                              let uu___7 =
                                FStarC_Extraction_ML_Syntax.ty_param_names vs in
                              FStarC_List.map
                                (fun x ->
                                   doc_of_mltype currentModule
                                     (min_op_prec, NonAssoc)
                                     (FStarC_Extraction_ML_Syntax.MLTY_Var x))
                                uu___7 in
                            reduce1 uu___6 in
                          reduce1 [text ":"; vars; text "."; ty1])
                   else text "") in
            let uu___5 =
              let uu___6 =
                let uu___7 = reduce1 ids in [uu___7; ty_annot; text "="; e1] in
              (text name) :: uu___6 in
            reduce1 uu___5 in
      let letdoc =
        if rec_ = FStarC_Extraction_ML_Syntax.Rec
        then reduce1 [text "let"; text "rec"]
        else text "let" in
      let lets1 = FStarC_List.map for1 lets in
      let lets2 =
        FStarC_List.mapi
          (fun i doc1 ->
             reduce1
               [if i = Prims.int_zero then letdoc else text "and"; doc1])
          lets1 in
      combine hardline lets2
and doc_of_loc (arg : (Prims.int * Prims.string)) : doc=
  let uu___ = arg in
  match uu___ with
  | (lineno, file) ->
      let uu___1 =
        let uu___2 =
          let uu___3 = FStarC_Options.no_location_info () in
          if uu___3
          then true
          else FStarC_Extraction_ML_Util.codegen_fsharp () in
        if uu___2 then true else file = " dummy" in
      if uu___1
      then empty
      else
        (let file1 = FStarC_Filepath.basename file in
         let uu___2 =
           let uu___3 =
             let uu___4 = num lineno in
             [uu___4; text (Prims.strcat "\"" (Prims.strcat file1 "\""))] in
           (text "#") :: uu___3 in
         reduce1 uu___2)
let doc_of_mltydecl (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (decls : FStarC_Extraction_ML_Syntax.mltydecl) : doc=
  let for1 uu___ =
    match uu___ with
    | { FStarC_Extraction_ML_Syntax.tydecl_assumed = uu___1;
        FStarC_Extraction_ML_Syntax.tydecl_name = x;
        FStarC_Extraction_ML_Syntax.tydecl_ignored = mangle_opt;
        FStarC_Extraction_ML_Syntax.tydecl_parameters = tparams;
        FStarC_Extraction_ML_Syntax.tydecl_meta = uu___2;
        FStarC_Extraction_ML_Syntax.tydecl_defn = body;_} ->
        let x1 =
          match mangle_opt with
          | FStar_Pervasives_Native.None -> x
          | FStar_Pervasives_Native.Some y -> y in
        let tparams1 =
          let tparams2 = FStarC_Extraction_ML_Syntax.ty_param_names tparams in
          match tparams2 with
          | [] -> empty
          | x2::[] -> text x2
          | uu___3 ->
              let doc1 = FStarC_List.map (fun x2 -> text x2) tparams2 in
              let uu___4 = combine (text ", ") doc1 in parens uu___4 in
        let forbody body1 =
          match body1 with
          | FStarC_Extraction_ML_Syntax.MLTD_Abbrev ty ->
              doc_of_mltype currentModule (min_op_prec, NonAssoc) ty
          | FStarC_Extraction_ML_Syntax.MLTD_Record fields ->
              let forfield uu___3 =
                match uu___3 with
                | (name, ty) ->
                    let name1 = text name in
                    let ty1 =
                      doc_of_mltype currentModule (min_op_prec, NonAssoc) ty in
                    reduce1 [name1; text ":"; ty1] in
              let uu___3 =
                let uu___4 = FStarC_List.map forfield fields in
                combine (text "; ") uu___4 in
              cbrackets uu___3
          | FStarC_Extraction_ML_Syntax.MLTD_DType ctors ->
              let forctor uu___3 =
                match uu___3 with
                | (name, tys) ->
                    let uu___4 = FStarC_List.split tys in
                    (match uu___4 with
                     | (_names, tys1) ->
                         (match tys1 with
                          | [] -> text name
                          | uu___5 ->
                              let tys2 =
                                FStarC_List.map
                                  (doc_of_mltype currentModule
                                     (t_prio_tpl, Left)) tys1 in
                              let tys3 = combine (text " * ") tys2 in
                              reduce1 [text name; text "of"; tys3])) in
              let ctors1 = FStarC_List.map forctor ctors in
              let ctors2 =
                FStarC_List.map (fun d -> reduce1 [text "|"; d]) ctors1 in
              combine hardline ctors2 in
        let doc1 =
          let uu___3 =
            let uu___4 =
              let uu___5 =
                let uu___6 = ptsym currentModule ([], x1) in text uu___6 in
              [uu___5] in
            tparams1 :: uu___4 in
          reduce1 uu___3 in
        (match body with
         | FStar_Pervasives_Native.None -> doc1
         | FStar_Pervasives_Native.Some body1 ->
             let body2 = forbody body1 in
             let uu___3 =
               let uu___4 = reduce1 [doc1; text "="] in [uu___4; body2] in
             combine hardline uu___3) in
  let doc1 = FStarC_List.map for1 decls in
  let doc2 =
    if Prims.uu___is_Cons doc1
    then
      let uu___ =
        let uu___1 = let uu___2 = combine (text " \n and ") doc1 in [uu___2] in
        (text "type") :: uu___1 in
      reduce1 uu___
    else text "" in
  doc2
let rec doc_of_sig1 (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (s : FStarC_Extraction_ML_Syntax.mlsig1) : doc=
  match s with
  | FStarC_Extraction_ML_Syntax.MLS_Mod (x, subsig) ->
      let uu___ =
        let uu___1 = reduce1 [text "module"; text x; text "="] in
        let uu___2 =
          let uu___3 = doc_of_sig currentModule subsig in
          let uu___4 = let uu___5 = reduce1 [text "end"] in [uu___5] in
          uu___3 :: uu___4 in
        uu___1 :: uu___2 in
      combine hardline uu___
  | FStarC_Extraction_ML_Syntax.MLS_Exn (x, []) ->
      reduce1 [text "exception"; text x]
  | FStarC_Extraction_ML_Syntax.MLS_Exn (x, args) ->
      let args1 =
        FStarC_List.map (doc_of_mltype currentModule (min_op_prec, NonAssoc))
          args in
      let args2 = let uu___ = combine (text " * ") args1 in parens uu___ in
      reduce1 [text "exception"; text x; text "of"; args2]
  | FStarC_Extraction_ML_Syntax.MLS_Val (x, (uu___, ty)) ->
      let ty1 = doc_of_mltype currentModule (min_op_prec, NonAssoc) ty in
      reduce1 [text "val"; text x; text ": "; ty1]
  | FStarC_Extraction_ML_Syntax.MLS_Ty decls ->
      doc_of_mltydecl currentModule decls
and doc_of_sig (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (s : FStarC_Extraction_ML_Syntax.mlsig) : doc=
  let docs = FStarC_List.map (doc_of_sig1 currentModule) s in
  let docs1 = FStarC_List.map (fun x -> reduce [x; hardline; hardline]) docs in
  reduce docs1
let doc_of_mod1 (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (m : FStarC_Extraction_ML_Syntax.mlmodule1) : doc=
  match m.FStarC_Extraction_ML_Syntax.mlmodule1_m with
  | FStarC_Extraction_ML_Syntax.MLM_Exn (x, []) ->
      reduce1 [text "exception"; text x]
  | FStarC_Extraction_ML_Syntax.MLM_Exn (x, args) ->
      let args1 = FStarC_List.map FStar_Pervasives_Native.snd args in
      let args2 =
        FStarC_List.map (doc_of_mltype currentModule (min_op_prec, NonAssoc))
          args1 in
      let args3 = let uu___ = combine (text " * ") args2 in parens uu___ in
      reduce1 [text "exception"; text x; text "of"; args3]
  | FStarC_Extraction_ML_Syntax.MLM_Ty decls ->
      doc_of_mltydecl currentModule decls
  | FStarC_Extraction_ML_Syntax.MLM_Let (rec_, lets) ->
      doc_of_lets currentModule (rec_, true, lets)
  | FStarC_Extraction_ML_Syntax.MLM_Top e ->
      let uu___ =
        let uu___1 =
          let uu___2 =
            let uu___3 =
              let uu___4 =
                doc_of_expr currentModule (min_op_prec, NonAssoc) e in
              [uu___4] in
            (text "=") :: uu___3 in
          (text "_") :: uu___2 in
        (text "let") :: uu___1 in
      reduce1 uu___
  | FStarC_Extraction_ML_Syntax.MLM_Loc loc -> doc_of_loc loc
let doc_of_modbody (currentModule : FStarC_Extraction_ML_Syntax.mlsymbol)
  (m : FStarC_Extraction_ML_Syntax.mlmodulebody) : doc=
  let docs =
    FStarC_List.map
      (fun x ->
         let doc1 = doc_of_mod1 currentModule x in
         [doc1;
         (match x.FStarC_Extraction_ML_Syntax.mlmodule1_m with
          | FStarC_Extraction_ML_Syntax.MLM_Loc uu___ -> empty
          | uu___ -> hardline);
         hardline]) m in
  reduce (FStarC_List.flatten docs)
let doc_of_mlmodule_r (fsharp : Prims.bool)
  (mod1 : FStarC_Extraction_ML_Syntax.mlmodule) : doc=
  let p_mod istop mod2 =
    let uu___ = mod2 in
    match uu___ with
    | (mod_name, sigmod) ->
        let target_mod_name =
          FStarC_Extraction_ML_Util.flatten_mlpath mod_name in
        let head =
          reduce1
            (if fsharp
             then [text "module"; text target_mod_name]
             else
               if Prims.op_Negation istop
               then
                 [text "module";
                 text target_mod_name;
                 text "=";
                 text "struct"]
               else []) in
        let tail =
          if Prims.op_Negation istop
          then reduce1 [text "end"]
          else reduce1 [] in
        let doc1 =
          FStarC_Option.map
            (fun uu___1 ->
               match uu___1 with
               | (uu___2, m) -> doc_of_modbody target_mod_name m) sigmod in
        let prefix =
          if fsharp then [cat (text "#light \"off\"") hardline] else [] in
        reduce
          (FStarC_List.op_At prefix
             [head;
             hardline;
             (match doc1 with
              | FStar_Pervasives_Native.None -> empty
              | FStar_Pervasives_Native.Some s -> cat s hardline);
             cat tail hardline]) in
  p_mod true mod1
let pretty (sz : Prims.int) (uu___ : doc) : Prims.string=
  match uu___ with | Doc doc1 -> doc1
let doc_of_mlmodule (fsharp : Prims.bool)
  (mlmodule : FStarC_Extraction_ML_Syntax.mlmodule) : doc=
  doc_of_mlmodule_r fsharp mlmodule
let string_of_mlexpr (cmod : FStarC_Extraction_ML_Syntax.mlpath)
  (e : FStarC_Extraction_ML_Syntax.mlexpr) : Prims.string=
  let doc1 =
    doc_of_expr (FStarC_Extraction_ML_Util.flatten_mlpath cmod)
      (min_op_prec, NonAssoc) e in
  pretty Prims.int_zero doc1
let string_of_mlty (cmod : FStarC_Extraction_ML_Syntax.mlpath)
  (e : FStarC_Extraction_ML_Syntax.mlty) : Prims.string=
  let doc1 =
    doc_of_mltype (FStarC_Extraction_ML_Util.flatten_mlpath cmod)
      (min_op_prec, NonAssoc) e in
  pretty Prims.int_zero doc1
let showable_mlexpr :
  FStarC_Extraction_ML_Syntax.mlexpr FStarC_Class_Show.showable=
  { FStarC_Class_Show.show = (string_of_mlexpr ([], "")) }
let showable_mlty :
  FStarC_Extraction_ML_Syntax.mlty FStarC_Class_Show.showable=
  { FStarC_Class_Show.show = (string_of_mlty ([], "")) }
let showable_etag :
  FStarC_Extraction_ML_Syntax.e_tag FStarC_Class_Show.showable=
  { FStarC_Class_Show.show = string_of_etag }
