open Prims
type argument_tag =
  | Retain 
  | Omit 
let uu___is_Retain (projectee : argument_tag) : Prims.bool=
  match projectee with | Retain -> true | uu___ -> false
let uu___is_Omit (projectee : argument_tag) : Prims.bool=
  match projectee with | Omit -> true | uu___ -> false
type entry = argument_tag Prims.list
type env_t =
  {
  current_module: FStarC_Extraction_ML_Syntax.mlsymbol Prims.list ;
  tydef_map: entry FStarC_PSMap.t }
let __proj__Mkenv_t__item__current_module (projectee : env_t) :
  FStarC_Extraction_ML_Syntax.mlsymbol Prims.list=
  match projectee with | { current_module; tydef_map;_} -> current_module
let __proj__Mkenv_t__item__tydef_map (projectee : env_t) :
  entry FStarC_PSMap.t=
  match projectee with | { current_module; tydef_map;_} -> tydef_map
let initial_env : env_t=
  let uu___ = FStarC_PSMap.empty () in
  { current_module = []; tydef_map = uu___ }
type tydef =
  (FStarC_Extraction_ML_Syntax.mlsymbol *
    FStarC_Extraction_ML_Syntax.metadata *
    (FStarC_Extraction_ML_Syntax.mltyscheme, Prims.int)
    FStar_Pervasives.either)
let extend_env (env : env_t) (i : FStarC_Extraction_ML_Syntax.mlsymbol)
  (e : entry) : env_t=
  let uu___ =
    let uu___1 =
      FStarC_Extraction_ML_Syntax.string_of_mlpath ((env.current_module), i) in
    FStarC_PSMap.add env.tydef_map uu___1 e in
  { current_module = (env.current_module); tydef_map = uu___ }
let lookup_tyname (env : env_t) (name : FStarC_Extraction_ML_Syntax.mlpath) :
  entry FStar_Pervasives_Native.option=
  let uu___ = FStarC_Extraction_ML_Syntax.string_of_mlpath name in
  FStarC_PSMap.try_find env.tydef_map uu___
type var_set = FStarC_Extraction_ML_Syntax.mlident FStarC_RBSet.t
let empty_var_set : Prims.string FStarC_RBSet.t=
  Obj.magic
    (FStarC_Class_Setlike.empty ()
       (Obj.magic (FStarC_RBSet.setlike_rbset FStarC_Class_Ord.ord_string))
       ())
let rec freevars_of_mlty' (uu___1 : var_set)
  (uu___ : FStarC_Extraction_ML_Syntax.mlty) : var_set=
  (fun vars t ->
     match t with
     | FStarC_Extraction_ML_Syntax.MLTY_Var i ->
         Obj.magic
           (Obj.repr
              (FStarC_Class_Setlike.add ()
                 (Obj.magic
                    (FStarC_RBSet.setlike_rbset FStarC_Class_Ord.ord_string))
                 i (Obj.magic vars)))
     | FStarC_Extraction_ML_Syntax.MLTY_Fun (t0, uu___, t1) ->
         Obj.magic
           (Obj.repr
              (let uu___1 = freevars_of_mlty' vars t0 in
               freevars_of_mlty' uu___1 t1))
     | FStarC_Extraction_ML_Syntax.MLTY_Named (tys, uu___) ->
         Obj.magic
           (Obj.repr (FStarC_List.fold_left freevars_of_mlty' vars tys))
     | FStarC_Extraction_ML_Syntax.MLTY_Tuple tys ->
         Obj.magic
           (Obj.repr (FStarC_List.fold_left freevars_of_mlty' vars tys))
     | uu___ -> Obj.magic (Obj.repr vars)) uu___1 uu___
let freevars_of_mlty : FStarC_Extraction_ML_Syntax.mlty -> var_set=
  freevars_of_mlty' empty_var_set
let rec elim_mlty (env : env_t) (mlty : FStarC_Extraction_ML_Syntax.mlty) :
  FStarC_Extraction_ML_Syntax.mlty=
  match mlty with
  | FStarC_Extraction_ML_Syntax.MLTY_Var uu___ -> mlty
  | FStarC_Extraction_ML_Syntax.MLTY_Fun (t0, e, t1) ->
      let uu___ =
        let uu___1 = elim_mlty env t0 in
        let uu___2 = elim_mlty env t1 in (uu___1, e, uu___2) in
      FStarC_Extraction_ML_Syntax.MLTY_Fun uu___
  | FStarC_Extraction_ML_Syntax.MLTY_Named (args, name) ->
      let args1 = FStarC_List.map (elim_mlty env) args in
      let uu___ = lookup_tyname env name in
      (match uu___ with
       | FStar_Pervasives_Native.None ->
           FStarC_Extraction_ML_Syntax.MLTY_Named (args1, name)
       | FStar_Pervasives_Native.Some entry1 ->
           (if (FStarC_List.length entry1) <> (FStarC_List.length args1)
            then
              failwith
                "Impossible: arity mismatch between definition and use"
            else ();
            (let args2 =
               FStarC_List.fold_right2
                 (fun arg tag out ->
                    match tag with | Retain -> arg :: out | uu___2 -> out)
                 args1 entry1 [] in
             FStarC_Extraction_ML_Syntax.MLTY_Named (args2, name))))
  | FStarC_Extraction_ML_Syntax.MLTY_Tuple tys ->
      let uu___ = FStarC_List.map (elim_mlty env) tys in
      FStarC_Extraction_ML_Syntax.MLTY_Tuple uu___
  | FStarC_Extraction_ML_Syntax.MLTY_Top -> mlty
  | FStarC_Extraction_ML_Syntax.MLTY_Erased -> mlty
let rec elim_mlexpr' (env : env_t) (e : FStarC_Extraction_ML_Syntax.mlexpr')
  : FStarC_Extraction_ML_Syntax.mlexpr'=
  match e with
  | FStarC_Extraction_ML_Syntax.MLE_Const uu___ -> e
  | FStarC_Extraction_ML_Syntax.MLE_Var uu___ -> e
  | FStarC_Extraction_ML_Syntax.MLE_Name uu___ -> e
  | FStarC_Extraction_ML_Syntax.MLE_Let (lb, e1) ->
      let uu___ =
        let uu___1 = elim_letbinding env lb in
        let uu___2 = elim_mlexpr env e1 in (uu___1, uu___2) in
      FStarC_Extraction_ML_Syntax.MLE_Let uu___
  | FStarC_Extraction_ML_Syntax.MLE_App (e1, es) ->
      let uu___ =
        let uu___1 = elim_mlexpr env e1 in
        let uu___2 = FStarC_List.map (elim_mlexpr env) es in (uu___1, uu___2) in
      FStarC_Extraction_ML_Syntax.MLE_App uu___
  | FStarC_Extraction_ML_Syntax.MLE_TApp (e1, tys) ->
      let uu___ =
        let uu___1 = FStarC_List.map (elim_mlty env) tys in (e1, uu___1) in
      FStarC_Extraction_ML_Syntax.MLE_TApp uu___
  | FStarC_Extraction_ML_Syntax.MLE_Fun (bvs, e1) ->
      let uu___ =
        let uu___1 =
          FStarC_List.map
            (fun b ->
               let uu___2 =
                 elim_mlty env b.FStarC_Extraction_ML_Syntax.mlbinder_ty in
               let uu___3 =
                 FStarC_List.map (elim_mlexpr env)
                   b.FStarC_Extraction_ML_Syntax.mlbinder_attrs in
               {
                 FStarC_Extraction_ML_Syntax.mlbinder_name =
                   (b.FStarC_Extraction_ML_Syntax.mlbinder_name);
                 FStarC_Extraction_ML_Syntax.mlbinder_ty = uu___2;
                 FStarC_Extraction_ML_Syntax.mlbinder_attrs = uu___3
               }) bvs in
        let uu___2 = elim_mlexpr env e1 in (uu___1, uu___2) in
      FStarC_Extraction_ML_Syntax.MLE_Fun uu___
  | FStarC_Extraction_ML_Syntax.MLE_Match (e1, branches) ->
      let uu___ =
        let uu___1 = elim_mlexpr env e1 in
        let uu___2 = FStarC_List.map (elim_branch env) branches in
        (uu___1, uu___2) in
      FStarC_Extraction_ML_Syntax.MLE_Match uu___
  | FStarC_Extraction_ML_Syntax.MLE_Coerce (e1, t0, t1) ->
      let uu___ =
        let uu___1 = elim_mlexpr env e1 in
        let uu___2 = elim_mlty env t0 in
        let uu___3 = elim_mlty env t1 in (uu___1, uu___2, uu___3) in
      FStarC_Extraction_ML_Syntax.MLE_Coerce uu___
  | FStarC_Extraction_ML_Syntax.MLE_CTor (l, es) ->
      let uu___ =
        let uu___1 = FStarC_List.map (elim_mlexpr env) es in (l, uu___1) in
      FStarC_Extraction_ML_Syntax.MLE_CTor uu___
  | FStarC_Extraction_ML_Syntax.MLE_Seq es ->
      let uu___ = FStarC_List.map (elim_mlexpr env) es in
      FStarC_Extraction_ML_Syntax.MLE_Seq uu___
  | FStarC_Extraction_ML_Syntax.MLE_Tuple es ->
      let uu___ = FStarC_List.map (elim_mlexpr env) es in
      FStarC_Extraction_ML_Syntax.MLE_Tuple uu___
  | FStarC_Extraction_ML_Syntax.MLE_Record (syms, nm, fields) ->
      let uu___ =
        let uu___1 =
          FStarC_List.map
            (fun uu___2 ->
               match uu___2 with
               | (s, e1) -> let uu___3 = elim_mlexpr env e1 in (s, uu___3))
            fields in
        (syms, nm, uu___1) in
      FStarC_Extraction_ML_Syntax.MLE_Record uu___
  | FStarC_Extraction_ML_Syntax.MLE_Proj (e1, p) ->
      let uu___ = let uu___1 = elim_mlexpr env e1 in (uu___1, p) in
      FStarC_Extraction_ML_Syntax.MLE_Proj uu___
  | FStarC_Extraction_ML_Syntax.MLE_If (e1, e11, e2_opt) ->
      let uu___ =
        let uu___1 = elim_mlexpr env e1 in
        let uu___2 = elim_mlexpr env e11 in
        let uu___3 = FStarC_Option.map (elim_mlexpr env) e2_opt in
        (uu___1, uu___2, uu___3) in
      FStarC_Extraction_ML_Syntax.MLE_If uu___
  | FStarC_Extraction_ML_Syntax.MLE_Raise (p, es) ->
      let uu___ =
        let uu___1 = FStarC_List.map (elim_mlexpr env) es in (p, uu___1) in
      FStarC_Extraction_ML_Syntax.MLE_Raise uu___
  | FStarC_Extraction_ML_Syntax.MLE_Try (e1, branches) ->
      let uu___ =
        let uu___1 = elim_mlexpr env e1 in
        let uu___2 = FStarC_List.map (elim_branch env) branches in
        (uu___1, uu___2) in
      FStarC_Extraction_ML_Syntax.MLE_Try uu___
and elim_letbinding (env : env_t)
  (uu___ :
    (FStarC_Extraction_ML_Syntax.mlletflavor *
      FStarC_Extraction_ML_Syntax.mllb Prims.list))
  :
  (FStarC_Extraction_ML_Syntax.mlletflavor * FStarC_Extraction_ML_Syntax.mllb
    Prims.list)=
  match uu___ with
  | (flavor, lbs) ->
      let elim_one_lb lb =
        let ts =
          FStarC_Option.map
            (fun uu___1 ->
               match uu___1 with
               | (vars, t) -> let uu___2 = elim_mlty env t in (vars, uu___2))
            lb.FStarC_Extraction_ML_Syntax.mllb_tysc in
        let expr = elim_mlexpr env lb.FStarC_Extraction_ML_Syntax.mllb_def in
        {
          FStarC_Extraction_ML_Syntax.mllb_name =
            (lb.FStarC_Extraction_ML_Syntax.mllb_name);
          FStarC_Extraction_ML_Syntax.mllb_tysc = ts;
          FStarC_Extraction_ML_Syntax.mllb_add_unit =
            (lb.FStarC_Extraction_ML_Syntax.mllb_add_unit);
          FStarC_Extraction_ML_Syntax.mllb_def = expr;
          FStarC_Extraction_ML_Syntax.mllb_attrs =
            (lb.FStarC_Extraction_ML_Syntax.mllb_attrs);
          FStarC_Extraction_ML_Syntax.mllb_meta =
            (lb.FStarC_Extraction_ML_Syntax.mllb_meta);
          FStarC_Extraction_ML_Syntax.print_typ =
            (lb.FStarC_Extraction_ML_Syntax.print_typ)
        } in
      let uu___1 = FStarC_List.map elim_one_lb lbs in (flavor, uu___1)
and elim_branch (env : env_t)
  (uu___ :
    (FStarC_Extraction_ML_Syntax.mlpattern *
      FStarC_Extraction_ML_Syntax.mlexpr FStar_Pervasives_Native.option *
      FStarC_Extraction_ML_Syntax.mlexpr))
  :
  (FStarC_Extraction_ML_Syntax.mlpattern * FStarC_Extraction_ML_Syntax.mlexpr
    FStar_Pervasives_Native.option * FStarC_Extraction_ML_Syntax.mlexpr)=
  match uu___ with
  | (pat, wopt, e) ->
      let uu___1 = FStarC_Option.map (elim_mlexpr env) wopt in
      let uu___2 = elim_mlexpr env e in (pat, uu___1, uu___2)
and elim_mlexpr (env : env_t) (e : FStarC_Extraction_ML_Syntax.mlexpr) :
  FStarC_Extraction_ML_Syntax.mlexpr=
  let uu___ = elim_mlexpr' env e.FStarC_Extraction_ML_Syntax.expr in
  let uu___1 = elim_mlty env e.FStarC_Extraction_ML_Syntax.mlty in
  {
    FStarC_Extraction_ML_Syntax.expr = uu___;
    FStarC_Extraction_ML_Syntax.mlty = uu___1;
    FStarC_Extraction_ML_Syntax.loc = (e.FStarC_Extraction_ML_Syntax.loc)
  }
exception Drop_tydef 
let uu___is_Drop_tydef (projectee : Prims.exn) : Prims.bool=
  match projectee with | Drop_tydef -> true | uu___ -> false
let elim_tydef (env : env_t) (name : Prims.string)
  (metadata : FStarC_Extraction_ML_Syntax.meta Prims.list)
  (parameters : FStarC_Extraction_ML_Syntax.ty_param Prims.list)
  (mlty : FStarC_Extraction_ML_Syntax.mlty) :
  (env_t * (Prims.string * FStarC_Extraction_ML_Syntax.meta Prims.list *
    FStarC_Extraction_ML_Syntax.ty_param Prims.list *
    FStarC_Extraction_ML_Syntax.mlty))=
  let val_decl_range =
    FStarC_Util.find_map metadata
      (fun uu___ ->
         match uu___ with
         | FStarC_Extraction_ML_Syntax.HasValDecl r ->
             FStar_Pervasives_Native.Some r
         | uu___1 -> FStar_Pervasives_Native.None) in
  let remove_typars_list =
    FStarC_Util.try_find
      (fun uu___ ->
         match uu___ with
         | FStarC_Extraction_ML_Syntax.RemoveUnusedTypeParameters uu___1 ->
             true
         | uu___1 -> false) metadata in
  let range_of_tydef =
    match remove_typars_list with
    | FStar_Pervasives_Native.None -> FStarC_Range_Type.dummyRange
    | FStar_Pervasives_Native.Some
        (FStarC_Extraction_ML_Syntax.RemoveUnusedTypeParameters (uu___, r))
        -> r in
  let must_eliminate i =
    match remove_typars_list with
    | FStar_Pervasives_Native.Some
        (FStarC_Extraction_ML_Syntax.RemoveUnusedTypeParameters (l, r)) ->
        FStarC_List.contains i l
    | uu___ -> false in
  let can_eliminate i =
    match (val_decl_range, remove_typars_list) with
    | (FStar_Pervasives_Native.None, FStar_Pervasives_Native.None) -> true
    | uu___ -> false in
  let mlty1 = elim_mlty env mlty in
  let freevars = freevars_of_mlty mlty1 in
  let uu___ =
    FStarC_List.fold_left
      (fun uu___1 param ->
         match uu___1 with
         | (i, params, entry1) ->
             let p = param.FStarC_Extraction_ML_Syntax.ty_param_name in
             let uu___2 =
               FStarC_Class_Setlike.mem ()
                 (Obj.magic
                    (FStarC_RBSet.setlike_rbset FStarC_Class_Ord.ord_string))
                 p (Obj.magic freevars) in
             if uu___2
             then
               (if must_eliminate i
                then
                  (let uu___4 =
                     FStarC_Format.fmt2
                       "Expected parameter %s of %s to be unused in its definition and eliminated"
                       p name in
                   FStarC_Errors.log_issue
                     FStarC_Class_HasRange.hasRange_range range_of_tydef
                     FStarC_Errors_Codes.Error_RemoveUnusedTypeParameter ()
                     (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                     (Obj.magic uu___4))
                else ();
                ((i + Prims.int_one), (param :: params), (Retain :: entry1)))
             else
               if (can_eliminate i) || (must_eliminate i)
               then ((i + Prims.int_one), params, (Omit :: entry1))
               else
                 (let uu___5 =
                    let uu___6 = FStarC_Options.codegen () in
                    uu___6 =
                      (FStar_Pervasives_Native.Some FStarC_Options.FSharp) in
                  if uu___5
                  then
                    let range =
                      match val_decl_range with
                      | FStar_Pervasives_Native.Some r -> r
                      | uu___6 -> range_of_tydef in
                    ((let uu___7 =
                        let uu___8 =
                          let uu___9 =
                            let uu___10 =
                              FStarC_Class_Show.show
                                FStarC_Class_Show.showable_int i in
                            let uu___11 =
                              FStarC_Class_Show.show
                                FStarC_Class_Show.showable_int i in
                            FStarC_Format.fmt3
                              "Parameter %s of %s is unused and must be eliminated for F#; add `[@@ remove_unused_type_parameters [%s; ...]]` to the interface signature."
                              uu___10 name uu___11 in
                          FStarC_Errors_Msg.text uu___9 in
                        let uu___9 =
                          let uu___10 =
                            FStarC_Errors_Msg.text
                              "This type definition is being dropped" in
                          [uu___10] in
                        uu___8 :: uu___9 in
                      FStarC_Errors.log_issue
                        FStarC_Class_HasRange.hasRange_range range
                        FStarC_Errors_Codes.Error_RemoveUnusedTypeParameter
                        ()
                        (Obj.magic
                           FStarC_Errors_Msg.is_error_message_list_doc)
                        (Obj.magic uu___7));
                     FStarC_Effect.raise Drop_tydef)
                  else
                    ((i + Prims.int_one), (param :: params), (Retain ::
                      entry1)))) (Prims.int_zero, [], []) parameters in
  match uu___ with
  | (uu___1, parameters1, entry1) ->
      let uu___2 = extend_env env name (FStarC_List.rev entry1) in
      (uu___2, (name, metadata, (FStarC_List.rev parameters1), mlty1))
let elim_tydef_or_decl (env : env_t) (td : tydef) : (env_t * tydef)=
  match td with
  | (name, metadata, FStar_Pervasives.Inr arity) ->
      let remove_typars_list =
        FStarC_Util.try_find
          (fun uu___ ->
             match uu___ with
             | FStarC_Extraction_ML_Syntax.RemoveUnusedTypeParameters uu___1
                 -> true
             | uu___1 -> false) metadata in
      (match remove_typars_list with
       | FStar_Pervasives_Native.None -> (env, td)
       | FStar_Pervasives_Native.Some
           (FStarC_Extraction_ML_Syntax.RemoveUnusedTypeParameters (l, r)) ->
           let must_eliminate i = FStarC_List.contains i l in
           let rec aux i =
             if i = arity
             then []
             else
               if must_eliminate i
               then (let uu___1 = aux (i + Prims.int_one) in Omit :: uu___1)
               else
                 (let uu___2 = aux (i + Prims.int_one) in Retain :: uu___2) in
           let entries = aux Prims.int_zero in
           let uu___ = extend_env env name entries in (uu___, td))
  | (name, metadata, FStar_Pervasives.Inl (parameters, mlty)) ->
      let uu___ = elim_tydef env name metadata parameters mlty in
      (match uu___ with
       | (env1, (name1, meta, params, mlty1)) ->
           (env1, (name1, meta, (FStar_Pervasives.Inl (params, mlty1)))))
let elim_tydefs (env : env_t) (tds : tydef Prims.list) :
  (env_t * tydef Prims.list)=
  let uu___ =
    let uu___1 = FStarC_Options.codegen () in
    uu___1 <> (FStar_Pervasives_Native.Some FStarC_Options.FSharp) in
  if uu___
  then (env, tds)
  else
    (let uu___2 =
       FStarC_List.fold_left
         (fun uu___3 td ->
            match uu___3 with
            | (env1, out) ->
                (try
                   (fun uu___4 ->
                      match () with
                      | () ->
                          let uu___5 = elim_tydef_or_decl env1 td in
                          (match uu___5 with
                           | (env2, td1) -> (env2, (td1 :: out)))) ()
                 with | Drop_tydef -> (env1, out))) (env, []) tds in
     match uu___2 with | (env1, tds1) -> (env1, (FStarC_List.rev tds1)))
let elim_one_mltydecl (env : env_t)
  (td : FStarC_Extraction_ML_Syntax.one_mltydecl) :
  (env_t * FStarC_Extraction_ML_Syntax.one_mltydecl)=
  let uu___ = td in
  match uu___ with
  | { FStarC_Extraction_ML_Syntax.tydecl_assumed = uu___1;
      FStarC_Extraction_ML_Syntax.tydecl_name = name;
      FStarC_Extraction_ML_Syntax.tydecl_ignored = uu___2;
      FStarC_Extraction_ML_Syntax.tydecl_parameters = parameters;
      FStarC_Extraction_ML_Syntax.tydecl_meta = meta;
      FStarC_Extraction_ML_Syntax.tydecl_defn = body;_} ->
      let elim_td td1 =
        match td1 with
        | FStarC_Extraction_ML_Syntax.MLTD_Abbrev mlty ->
            let uu___3 = elim_tydef env name meta parameters mlty in
            (match uu___3 with
             | (env1, (name1, uu___4, parameters1, mlty1)) ->
                 (env1, parameters1,
                   (FStarC_Extraction_ML_Syntax.MLTD_Abbrev mlty1)))
        | FStarC_Extraction_ML_Syntax.MLTD_Record fields ->
            let uu___3 =
              let uu___4 =
                FStarC_List.map
                  (fun uu___5 ->
                     match uu___5 with
                     | (name1, ty) ->
                         let uu___6 = elim_mlty env ty in (name1, uu___6))
                  fields in
              FStarC_Extraction_ML_Syntax.MLTD_Record uu___4 in
            (env, parameters, uu___3)
        | FStarC_Extraction_ML_Syntax.MLTD_DType inductive ->
            let uu___3 =
              let uu___4 =
                FStarC_List.map
                  (fun uu___5 ->
                     match uu___5 with
                     | (i, constrs) ->
                         let uu___6 =
                           FStarC_List.map
                             (fun uu___7 ->
                                match uu___7 with
                                | (constr, ty) ->
                                    let uu___8 = elim_mlty env ty in
                                    (constr, uu___8)) constrs in
                         (i, uu___6)) inductive in
              FStarC_Extraction_ML_Syntax.MLTD_DType uu___4 in
            (env, parameters, uu___3) in
      let uu___3 =
        match body with
        | FStar_Pervasives_Native.None -> (env, parameters, body)
        | FStar_Pervasives_Native.Some td1 ->
            let uu___4 = elim_td td1 in
            (match uu___4 with
             | (env1, parameters1, td2) ->
                 (env1, parameters1, (FStar_Pervasives_Native.Some td2))) in
      (match uu___3 with
       | (env1, parameters1, body1) ->
           (env1,
             {
               FStarC_Extraction_ML_Syntax.tydecl_assumed =
                 (td.FStarC_Extraction_ML_Syntax.tydecl_assumed);
               FStarC_Extraction_ML_Syntax.tydecl_name =
                 (td.FStarC_Extraction_ML_Syntax.tydecl_name);
               FStarC_Extraction_ML_Syntax.tydecl_ignored =
                 (td.FStarC_Extraction_ML_Syntax.tydecl_ignored);
               FStarC_Extraction_ML_Syntax.tydecl_parameters = parameters1;
               FStarC_Extraction_ML_Syntax.tydecl_meta =
                 (td.FStarC_Extraction_ML_Syntax.tydecl_meta);
               FStarC_Extraction_ML_Syntax.tydecl_defn = body1
             }))
let elim_modulebody (env : env_t)
  (m : FStarC_Extraction_ML_Syntax.mlmodule1 Prims.list) :
  (env_t * FStarC_Extraction_ML_Syntax.mlmodule1 Prims.list)=
  let elim_module1 env1 m1 =
    match m1.FStarC_Extraction_ML_Syntax.mlmodule1_m with
    | FStarC_Extraction_ML_Syntax.MLM_Ty td ->
        let uu___ = FStarC_Util.fold_map elim_one_mltydecl env1 td in
        (match uu___ with
         | (env2, td1) ->
             (env2,
               {
                 FStarC_Extraction_ML_Syntax.mlmodule1_m =
                   (FStarC_Extraction_ML_Syntax.MLM_Ty td1);
                 FStarC_Extraction_ML_Syntax.mlmodule1_attrs =
                   (m1.FStarC_Extraction_ML_Syntax.mlmodule1_attrs)
               }))
    | FStarC_Extraction_ML_Syntax.MLM_Let lb ->
        let uu___ =
          let uu___1 =
            let uu___2 = elim_letbinding env1 lb in
            FStarC_Extraction_ML_Syntax.MLM_Let uu___2 in
          {
            FStarC_Extraction_ML_Syntax.mlmodule1_m = uu___1;
            FStarC_Extraction_ML_Syntax.mlmodule1_attrs =
              (m1.FStarC_Extraction_ML_Syntax.mlmodule1_attrs)
          } in
        (env1, uu___)
    | FStarC_Extraction_ML_Syntax.MLM_Exn (name, sym_tys) ->
        let uu___ =
          let uu___1 =
            let uu___2 =
              let uu___3 =
                FStarC_List.map
                  (fun uu___4 ->
                     match uu___4 with
                     | (s, t) -> let uu___5 = elim_mlty env1 t in (s, uu___5))
                  sym_tys in
              (name, uu___3) in
            FStarC_Extraction_ML_Syntax.MLM_Exn uu___2 in
          {
            FStarC_Extraction_ML_Syntax.mlmodule1_m = uu___1;
            FStarC_Extraction_ML_Syntax.mlmodule1_attrs =
              (m1.FStarC_Extraction_ML_Syntax.mlmodule1_attrs)
          } in
        (env1, uu___)
    | FStarC_Extraction_ML_Syntax.MLM_Top e ->
        let uu___ =
          let uu___1 =
            let uu___2 = elim_mlexpr env1 e in
            FStarC_Extraction_ML_Syntax.MLM_Top uu___2 in
          {
            FStarC_Extraction_ML_Syntax.mlmodule1_m = uu___1;
            FStarC_Extraction_ML_Syntax.mlmodule1_attrs =
              (m1.FStarC_Extraction_ML_Syntax.mlmodule1_attrs)
          } in
        (env1, uu___)
    | uu___ -> (env1, m1) in
  let uu___ =
    FStarC_List.fold_left
      (fun uu___1 m1 ->
         match uu___1 with
         | (env1, out) ->
             (try
                (fun uu___2 ->
                   match () with
                   | () ->
                       let uu___3 = elim_module1 env1 m1 in
                       (match uu___3 with | (env2, m2) -> (env2, (m2 :: out))))
                  ()
              with | Drop_tydef -> (env1, out))) (env, []) m in
  match uu___ with | (env1, m1) -> (env1, (FStarC_List.rev m1))
let set_current_module (e : env_t) (n : FStarC_Extraction_ML_Syntax.mlpath) :
  env_t=
  let curmod =
    FStarC_List.op_At (FStar_Pervasives_Native.fst n)
      [FStar_Pervasives_Native.snd n] in
  { current_module = curmod; tydef_map = (e.tydef_map) }
let elim_mllib (env : env_t) (m : FStarC_Extraction_ML_Syntax.mlmodule) :
  (env_t * FStarC_Extraction_ML_Syntax.mlmodule)=
  let uu___ =
    let uu___1 = FStarC_Options.codegen () in
    uu___1 <> (FStar_Pervasives_Native.Some FStarC_Options.FSharp) in
  if uu___
  then (env, m)
  else
    (let elim_one_lib env1 lib =
       let uu___2 = lib in
       match uu___2 with
       | (name, sig_mod) ->
           let env2 = set_current_module env1 name in
           let uu___3 =
             match sig_mod with
             | FStar_Pervasives_Native.Some (sig_, mod_) ->
                 let uu___4 = elim_modulebody env2 mod_ in
                 (match uu___4 with
                  | (env3, mod_1) ->
                      ((FStar_Pervasives_Native.Some (sig_, mod_1)), env3))
             | FStar_Pervasives_Native.None ->
                 (FStar_Pervasives_Native.None, env2) in
           (match uu___3 with | (sig_mod1, env3) -> (env3, (name, sig_mod1))) in
     elim_one_lib env m)
let elim_mllibs (l : FStarC_Extraction_ML_Syntax.mlmodule Prims.list) :
  FStarC_Extraction_ML_Syntax.mlmodule Prims.list=
  let uu___ = FStarC_Util.fold_map elim_mllib initial_env l in
  FStar_Pervasives_Native.snd uu___
