open Prims
let dbg_PartialApp : Prims.bool FStarC_Effect.ref=
  FStarC_Debug.get_toggle "PartialApp"
let dbg_SMTEncoding : Prims.bool FStarC_Effect.ref=
  FStarC_Debug.get_toggle "SMTEncoding"
let dbg_SMTEncodingReify : Prims.bool FStarC_Effect.ref=
  FStarC_Debug.get_toggle "SMTEncodingReify"
let mkForall_fuel' (mname : Prims.string) (r : FStarC_Range_Type.t)
  (n : 'uuuuu)
  (uu___ :
    (FStarC_SMTEncoding_Term.pat Prims.list Prims.list *
      FStarC_SMTEncoding_Term.fvs * FStarC_SMTEncoding_Term.term))
  : FStarC_SMTEncoding_Term.term=
  match uu___ with
  | (pats, vars, body) ->
      let fallback uu___1 =
        FStarC_SMTEncoding_Term.mkForall r (pats, vars, body) in
      let uu___1 = FStarC_Options.unthrottle_inductives () in
      if uu___1
      then fallback ()
      else
        (let uu___3 =
           FStarC_SMTEncoding_Env.fresh_fvar mname "f"
             FStarC_SMTEncoding_Term.Fuel_sort in
         match uu___3 with
         | (fsym, fterm) ->
             let add_fuel tms =
               FStarC_List.map
                 (fun p ->
                    match p.FStarC_SMTEncoding_Term.tm with
                    | FStarC_SMTEncoding_Term.App
                        (FStarC_SMTEncoding_Term.Var "HasType", args) ->
                        FStarC_SMTEncoding_Util.mkApp
                          ("HasTypeFuel", (fterm :: args))
                    | uu___4 -> p) tms in
             let pats1 = FStarC_List.map add_fuel pats in
             let body1 =
               match body.FStarC_SMTEncoding_Term.tm with
               | FStarC_SMTEncoding_Term.App
                   (FStarC_SMTEncoding_Term.Imp, guard::body'::[]) ->
                   let guard1 =
                     match guard.FStarC_SMTEncoding_Term.tm with
                     | FStarC_SMTEncoding_Term.App
                         (FStarC_SMTEncoding_Term.And, guards) ->
                         let uu___4 = add_fuel guards in
                         FStarC_SMTEncoding_Util.mk_and_l uu___4
                     | uu___4 ->
                         let uu___5 = add_fuel [guard] in
                         FStarC_List.hd uu___5 in
                   FStarC_SMTEncoding_Util.mkImp (guard1, body')
               | uu___4 -> body in
             let vars1 =
               let uu___4 =
                 FStarC_SMTEncoding_Term.mk_fv
                   (fsym, FStarC_SMTEncoding_Term.Fuel_sort) in
               uu___4 :: vars in
             FStarC_SMTEncoding_Term.mkForall r (pats1, vars1, body1))
let mkForall_fuel (mname : Prims.string) (r : FStarC_Range_Type.t) :
  (FStarC_SMTEncoding_Term.pat Prims.list Prims.list *
    FStarC_SMTEncoding_Term.fvs * FStarC_SMTEncoding_Term.term) ->
    FStarC_SMTEncoding_Term.term=
  mkForall_fuel' mname r Prims.int_one
let head_normal (env : FStarC_SMTEncoding_Env.env_t)
  (t : FStarC_Syntax_Syntax.term) : Prims.bool=
  let t1 = FStarC_Syntax_Util.unmeta t in
  match t1.FStarC_Syntax_Syntax.n with
  | FStarC_Syntax_Syntax.Tm_arrow uu___ -> true
  | FStarC_Syntax_Syntax.Tm_refine uu___ -> true
  | FStarC_Syntax_Syntax.Tm_bvar uu___ -> true
  | FStarC_Syntax_Syntax.Tm_uvar uu___ -> true
  | FStarC_Syntax_Syntax.Tm_abs uu___ -> true
  | FStarC_Syntax_Syntax.Tm_constant uu___ -> true
  | FStarC_Syntax_Syntax.Tm_fvar fv ->
      let uu___ =
        FStarC_TypeChecker_Env.lookup_definition
          [FStarC_TypeChecker_Env.Eager_unfolding_only]
          env.FStarC_SMTEncoding_Env.tcenv fv.FStarC_Syntax_Syntax.fv_name in
      FStar_Pervasives_Native.uu___is_None uu___
  | FStarC_Syntax_Syntax.Tm_app
      {
        FStarC_Syntax_Syntax.hd =
          { FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
            FStarC_Syntax_Syntax.pos = uu___;
            FStarC_Syntax_Syntax.vars = uu___1;
            FStarC_Syntax_Syntax.hash_code = uu___2;_};
        FStarC_Syntax_Syntax.args = uu___3;_}
      ->
      let uu___4 =
        FStarC_TypeChecker_Env.lookup_definition
          [FStarC_TypeChecker_Env.Eager_unfolding_only]
          env.FStarC_SMTEncoding_Env.tcenv fv.FStarC_Syntax_Syntax.fv_name in
      FStar_Pervasives_Native.uu___is_None uu___4
  | uu___ -> false
let head_redex (env : FStarC_SMTEncoding_Env.env_t)
  (t : FStarC_Syntax_Syntax.term) : Prims.bool=
  let uu___ =
    let uu___1 = FStarC_Syntax_Util.un_uinst t in
    uu___1.FStarC_Syntax_Syntax.n in
  match uu___ with
  | FStarC_Syntax_Syntax.Tm_abs
      { FStarC_Syntax_Syntax.bs = uu___1; FStarC_Syntax_Syntax.body = uu___2;
        FStarC_Syntax_Syntax.rc_opt = FStar_Pervasives_Native.Some rc;_}
      ->
      ((FStarC_Ident.lid_equals rc.FStarC_Syntax_Syntax.residual_effect
          FStarC_Parser_Const.effect_Tot_lid)
         ||
         (FStarC_Ident.lid_equals rc.FStarC_Syntax_Syntax.residual_effect
            FStarC_Parser_Const.effect_GTot_lid))
        ||
        (FStarC_List.existsb
           (fun uu___3 ->
              match uu___3 with
              | FStarC_Syntax_Syntax.TOTAL -> true
              | uu___4 -> false) rc.FStarC_Syntax_Syntax.residual_flags)
  | FStarC_Syntax_Syntax.Tm_uinst
      ({ FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
         FStarC_Syntax_Syntax.pos = uu___1;
         FStarC_Syntax_Syntax.vars = uu___2;
         FStarC_Syntax_Syntax.hash_code = uu___3;_},
       uu___4)
      ->
      let uu___5 =
        FStarC_TypeChecker_Env.lookup_definition
          [FStarC_TypeChecker_Env.Eager_unfolding_only]
          env.FStarC_SMTEncoding_Env.tcenv fv.FStarC_Syntax_Syntax.fv_name in
      FStar_Pervasives_Native.uu___is_Some uu___5
  | FStarC_Syntax_Syntax.Tm_fvar fv ->
      let uu___1 =
        FStarC_TypeChecker_Env.lookup_definition
          [FStarC_TypeChecker_Env.Eager_unfolding_only]
          env.FStarC_SMTEncoding_Env.tcenv fv.FStarC_Syntax_Syntax.fv_name in
      FStar_Pervasives_Native.uu___is_Some uu___1
  | uu___1 -> false
let norm_with_steps (steps : FStarC_TypeChecker_Env.steps)
  (env : FStarC_TypeChecker_Env.env) (t : FStarC_Syntax_Syntax.term) :
  FStarC_Syntax_Syntax.term=
  let uu___ =
    let uu___1 =
      let uu___2 = FStarC_TypeChecker_Env.current_module env in
      FStarC_Ident.string_of_lid uu___2 in
    FStar_Pervasives_Native.Some uu___1 in
  FStarC_Profiling.profile
    (fun uu___1 -> FStarC_TypeChecker_Normalize.normalize steps env t) uu___
    "FStarC.SMTEncoding.EncodeTerm.norm_with_steps"
let normalize_refinement (steps : FStarC_TypeChecker_Env.steps)
  (env : FStarC_TypeChecker_Env.env) (t : FStarC_Syntax_Syntax.typ) :
  FStarC_Syntax_Syntax.typ=
  let uu___ =
    let uu___1 =
      let uu___2 = FStarC_TypeChecker_Env.current_module env in
      FStarC_Ident.string_of_lid uu___2 in
    FStar_Pervasives_Native.Some uu___1 in
  FStarC_Profiling.profile
    (fun uu___1 ->
       FStarC_TypeChecker_Normalize.normalize_refinement steps env t) uu___
    "FStarC.SMTEncoding.EncodeTerm.normalize_refinement"
let whnf (env : FStarC_SMTEncoding_Env.env_t) (t : FStarC_Syntax_Syntax.term)
  : FStarC_Syntax_Syntax.term=
  let uu___ = head_normal env t in
  if uu___
  then t
  else
    norm_with_steps
      [FStarC_TypeChecker_Env.Beta;
      FStarC_TypeChecker_Env.Weak;
      FStarC_TypeChecker_Env.HNF;
      FStarC_TypeChecker_Env.Exclude FStarC_TypeChecker_Env.Zeta;
      FStarC_TypeChecker_Env.Eager_unfolding]
      env.FStarC_SMTEncoding_Env.tcenv t
let norm (env : FStarC_SMTEncoding_Env.env_t) (t : FStarC_Syntax_Syntax.term)
  : FStarC_Syntax_Syntax.term=
  norm_with_steps
    [FStarC_TypeChecker_Env.Beta;
    FStarC_TypeChecker_Env.Exclude FStarC_TypeChecker_Env.Zeta;
    FStarC_TypeChecker_Env.Eager_unfolding] env.FStarC_SMTEncoding_Env.tcenv
    t
let maybe_whnf (env : FStarC_SMTEncoding_Env.env_t)
  (t : FStarC_Syntax_Syntax.term) :
  FStarC_Syntax_Syntax.term FStar_Pervasives_Native.option=
  let t' = whnf env t in
  let uu___ = FStarC_Syntax_Util.head_and_args t' in
  match uu___ with
  | (head', uu___1) ->
      let uu___2 = head_redex env head' in
      if uu___2
      then FStar_Pervasives_Native.None
      else FStar_Pervasives_Native.Some t'
let trivial_post (t : FStarC_Syntax_Syntax.term) : FStarC_Syntax_Syntax.term=
  let uu___ = let uu___1 = FStarC_Syntax_Syntax.null_binder t in [uu___1] in
  let uu___1 =
    FStarC_Syntax_Syntax.fvar FStarC_Parser_Const.true_lid
      FStar_Pervasives_Native.None in
  FStarC_Syntax_Util.abs uu___ uu___1 FStar_Pervasives_Native.None
let mk_Apply (e : FStarC_SMTEncoding_Term.term)
  (vars : FStarC_SMTEncoding_Term.fvs) : FStarC_SMTEncoding_Term.term=
  FStarC_List.fold_left
    (fun out var ->
       let uu___ = FStarC_SMTEncoding_Term.fv_sort var in
       match uu___ with
       | FStarC_SMTEncoding_Term.Fuel_sort ->
           let uu___1 = FStarC_SMTEncoding_Util.mkFreeV var in
           FStarC_SMTEncoding_Term.mk_ApplyTF out uu___1
       | s ->
           let uu___1 = FStarC_SMTEncoding_Util.mkFreeV var in
           FStarC_SMTEncoding_Util.mk_ApplyTT out uu___1) e vars
let mk_Apply_args (e : FStarC_SMTEncoding_Term.term)
  (args : FStarC_SMTEncoding_Term.term Prims.list) :
  FStarC_SMTEncoding_Term.term=
  FStarC_List.fold_left FStarC_SMTEncoding_Util.mk_ApplyTT e args
let raise_arity_mismatch (head : Prims.string) (arity : Prims.int)
  (n_args : Prims.int) (rng : FStarC_Range_Type.t) : 'a=
  let uu___ =
    let uu___1 = FStarC_Class_Show.show FStarC_Class_Show.showable_int arity in
    let uu___2 = FStarC_Class_Show.show FStarC_Class_Show.showable_int n_args in
    FStarC_Format.fmt3
      "Head symbol %s expects at least %s arguments; got only %s" head uu___1
      uu___2 in
  FStarC_Errors.raise_error FStarC_Class_HasRange.hasRange_range rng
    FStarC_Errors_Codes.Fatal_SMTEncodingArityMismatch ()
    (Obj.magic FStarC_Errors_Msg.is_error_message_string) (Obj.magic uu___)
let isTotFun_axioms (pos : FStarC_Range_Type.t)
  (head : FStarC_SMTEncoding_Term.term)
  (extra_vars : FStarC_SMTEncoding_Term.fvs)
  (vars : FStarC_SMTEncoding_Term.fvs)
  (guards : FStarC_SMTEncoding_Term.term Prims.list) (is_pure : Prims.bool) :
  FStarC_SMTEncoding_Term.term=
  let maybe_mkForall pat vars1 body =
    match FStarC_List.op_At extra_vars vars1 with
    | [] -> body
    | vs -> FStarC_SMTEncoding_Term.mkForall pos (pat, vs, body) in
  let rec is_tot_fun_axioms ctx ctx_guard head1 vars1 guards1 =
    match (vars1, guards1) with
    | ([], []) -> FStarC_SMTEncoding_Util.mkTrue
    | (uu___::[], uu___1) ->
        if is_pure
        then
          let uu___2 =
            let uu___3 =
              let uu___4 = FStarC_SMTEncoding_Term.mk_IsTotFun head1 in
              (ctx_guard, uu___4) in
            FStarC_SMTEncoding_Util.mkImp uu___3 in
          maybe_mkForall [[head1]] ctx uu___2
        else FStarC_SMTEncoding_Util.mkTrue
    | (x::vars2, g_x::guards2) ->
        let is_tot_fun_head =
          let uu___ =
            let uu___1 =
              let uu___2 = FStarC_SMTEncoding_Term.mk_IsTotFun head1 in
              (ctx_guard, uu___2) in
            FStarC_SMTEncoding_Util.mkImp uu___1 in
          maybe_mkForall [[head1]] ctx uu___ in
        let app = mk_Apply head1 [x] in
        let ctx1 = FStarC_List.op_At ctx [x] in
        let ctx_guard1 = FStarC_SMTEncoding_Util.mkAnd (ctx_guard, g_x) in
        let rest = is_tot_fun_axioms ctx1 ctx_guard1 app vars2 guards2 in
        FStarC_SMTEncoding_Util.mkAnd (is_tot_fun_head, rest)
    | uu___ -> failwith "impossible: isTotFun_axioms" in
  is_tot_fun_axioms [] FStarC_SMTEncoding_Util.mkTrue head vars guards
let maybe_curry_app (rng : FStarC_Range_Type.t)
  (head :
    (FStarC_SMTEncoding_Term.op, FStarC_SMTEncoding_Term.term)
      FStar_Pervasives.either)
  (arity : Prims.int) (args : FStarC_SMTEncoding_Term.term Prims.list) :
  FStarC_SMTEncoding_Term.term=
  let n_args = FStarC_List.length args in
  match head with
  | FStar_Pervasives.Inr head1 -> mk_Apply_args head1 args
  | FStar_Pervasives.Inl head1 ->
      if n_args = arity
      then FStarC_SMTEncoding_Util.mkApp' (head1, args)
      else
        if n_args > arity
        then
          (let uu___1 = FStarC_Util.first_N arity args in
           match uu___1 with
           | (args1, rest) ->
               let head2 = FStarC_SMTEncoding_Util.mkApp' (head1, args1) in
               mk_Apply_args head2 rest)
        else
          (let uu___2 = FStarC_SMTEncoding_Term.op_to_string head1 in
           raise_arity_mismatch uu___2 arity n_args rng)
let maybe_curry_fvb (rng : FStarC_Range_Type.t)
  (fvb : FStarC_SMTEncoding_Env.fvar_binding)
  (args : FStarC_SMTEncoding_Term.term Prims.list) :
  FStarC_SMTEncoding_Term.term=
  if fvb.FStarC_SMTEncoding_Env.fvb_thunked
  then
    let uu___ = FStarC_SMTEncoding_Env.force_thunk fvb in
    mk_Apply_args uu___ args
  else
    maybe_curry_app rng
      (FStar_Pervasives.Inl
         (FStarC_SMTEncoding_Term.Var (fvb.FStarC_SMTEncoding_Env.smt_id)))
      fvb.FStarC_SMTEncoding_Env.smt_arity args
let is_app (uu___ : FStarC_SMTEncoding_Term.op) : Prims.bool=
  match uu___ with
  | FStarC_SMTEncoding_Term.Var "ApplyTT" -> true
  | FStarC_SMTEncoding_Term.Var "ApplyTF" -> true
  | uu___1 -> false
let check_pattern_vars (env : FStarC_SMTEncoding_Env.env_t)
  (vars : FStarC_Syntax_Syntax.binder Prims.list)
  (pats : (FStarC_Syntax_Syntax.term * 'uuuuu) Prims.list) : unit=
  let pats1 =
    FStarC_List.map
      (fun uu___ ->
         match uu___ with
         | (x, uu___1) ->
             norm_with_steps [FStarC_TypeChecker_Env.Beta]
               env.FStarC_SMTEncoding_Env.tcenv x) pats in
  match pats1 with
  | [] -> ()
  | hd::tl ->
      let pat_vars =
        let uu___ = FStarC_Syntax_Free.names hd in
        FStarC_List.fold_left
          (fun uu___2 uu___1 ->
             (fun out x ->
                let uu___1 = FStarC_Syntax_Free.names x in
                Obj.magic
                  (FStarC_Class_Setlike.union ()
                     (Obj.magic
                        (FStarC_FlatSet.setlike_flat_set
                           FStarC_Syntax_Syntax.ord_bv)) (Obj.magic out)
                     (Obj.magic uu___1))) uu___2 uu___1) uu___ tl in
      let uu___ =
        FStarC_Option.find
          (fun uu___1 ->
             match uu___1 with
             | { FStarC_Syntax_Syntax.binder_bv = b;
                 FStarC_Syntax_Syntax.binder_qual = uu___2;
                 FStarC_Syntax_Syntax.binder_positivity = uu___3;
                 FStarC_Syntax_Syntax.binder_attrs = uu___4;_} ->
                 let uu___5 =
                   FStarC_Class_Setlike.mem ()
                     (Obj.magic
                        (FStarC_FlatSet.setlike_flat_set
                           FStarC_Syntax_Syntax.ord_bv)) b
                     (Obj.magic pat_vars) in
                 Prims.op_Negation uu___5) vars in
      (match uu___ with
       | FStar_Pervasives_Native.None -> ()
       | FStar_Pervasives_Native.Some
           { FStarC_Syntax_Syntax.binder_bv = x;
             FStarC_Syntax_Syntax.binder_qual = uu___1;
             FStarC_Syntax_Syntax.binder_positivity = uu___2;
             FStarC_Syntax_Syntax.binder_attrs = uu___3;_}
           ->
           let pos =
             FStarC_List.fold_left
               (fun out t ->
                  FStarC_Range_Ops.union_ranges out
                    t.FStarC_Syntax_Syntax.pos) hd.FStarC_Syntax_Syntax.pos
               tl in
           let uu___4 =
             let uu___5 =
               FStarC_Class_Show.show FStarC_Syntax_Print.showable_bv x in
             FStarC_Format.fmt1
               "SMT pattern misses at least one bound variable: %s" uu___5 in
           FStarC_Errors.log_issue FStarC_Class_HasRange.hasRange_range pos
             FStarC_Errors_Codes.Warning_SMTPatternIllFormed ()
             (Obj.magic FStarC_Errors_Msg.is_error_message_string)
             (Obj.magic uu___4))
type label =
  (FStarC_SMTEncoding_Term.fv * Prims.string * FStarC_Range_Type.t)
type labels = label Prims.list
type pattern =
  {
  pat_vars: (FStarC_Syntax_Syntax.bv * FStarC_SMTEncoding_Term.fv) Prims.list ;
  pat_term:
    unit -> (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t) ;
  guard: FStarC_SMTEncoding_Term.term -> FStarC_SMTEncoding_Term.term ;
  projections:
    FStarC_SMTEncoding_Term.term ->
      (FStarC_Syntax_Syntax.bv * FStarC_SMTEncoding_Term.term) Prims.list
    }
let __proj__Mkpattern__item__pat_vars (projectee : pattern) :
  (FStarC_Syntax_Syntax.bv * FStarC_SMTEncoding_Term.fv) Prims.list=
  match projectee with
  | { pat_vars; pat_term; guard; projections;_} -> pat_vars
let __proj__Mkpattern__item__pat_term (projectee : pattern) :
  unit -> (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  match projectee with
  | { pat_vars; pat_term; guard; projections;_} -> pat_term
let __proj__Mkpattern__item__guard (projectee : pattern) :
  FStarC_SMTEncoding_Term.term -> FStarC_SMTEncoding_Term.term=
  match projectee with | { pat_vars; pat_term; guard; projections;_} -> guard
let __proj__Mkpattern__item__projections (projectee : pattern) :
  FStarC_SMTEncoding_Term.term ->
    (FStarC_Syntax_Syntax.bv * FStarC_SMTEncoding_Term.term) Prims.list=
  match projectee with
  | { pat_vars; pat_term; guard; projections;_} -> projections
let as_function_typ (env : FStarC_SMTEncoding_Env.env_t)
  (t0 : FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax) :
  FStarC_Syntax_Syntax.term=
  let rec aux norm1 t =
    let t1 = FStarC_Syntax_Subst.compress t in
    match t1.FStarC_Syntax_Syntax.n with
    | FStarC_Syntax_Syntax.Tm_arrow uu___ -> t1
    | FStarC_Syntax_Syntax.Tm_refine uu___ ->
        let uu___1 = FStarC_Syntax_Util.unrefine t1 in aux true uu___1
    | uu___ ->
        if norm1
        then let uu___1 = whnf env t1 in aux false uu___1
        else
          (let uu___2 =
             let uu___3 =
               FStarC_Range_Ops.string_of_range t0.FStarC_Syntax_Syntax.pos in
             let uu___4 =
               FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t0 in
             FStarC_Format.fmt2 "(%s) Expected a function typ; got %s" uu___3
               uu___4 in
           failwith uu___2) in
  aux true t0
let rec curried_arrow_formals_comp (k : FStarC_Syntax_Syntax.term) :
  (FStarC_Syntax_Syntax.binders * FStarC_Syntax_Syntax.comp)=
  let k1 = FStarC_Syntax_Subst.compress k in
  match k1.FStarC_Syntax_Syntax.n with
  | FStarC_Syntax_Syntax.Tm_arrow
      { FStarC_Syntax_Syntax.bs1 = bs; FStarC_Syntax_Syntax.comp = c;_} ->
      FStarC_Syntax_Subst.open_comp bs c
  | FStarC_Syntax_Syntax.Tm_refine
      { FStarC_Syntax_Syntax.b = bv; FStarC_Syntax_Syntax.phi = uu___;_} ->
      let uu___1 = curried_arrow_formals_comp bv.FStarC_Syntax_Syntax.sort in
      (match uu___1 with
       | (args, res) ->
           (match args with
            | [] ->
                let uu___2 = FStarC_Syntax_Syntax.mk_Total k1 in ([], uu___2)
            | uu___2 -> (args, res)))
  | uu___ -> let uu___1 = FStarC_Syntax_Syntax.mk_Total k1 in ([], uu___1)
let is_arithmetic_primitive
  (head : FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax)
  (args : 'uuuuu Prims.list) : Prims.bool=
  match ((head.FStarC_Syntax_Syntax.n), args) with
  | (FStarC_Syntax_Syntax.Tm_fvar fv, uu___::uu___1::[]) ->
      ((((((((((((FStarC_Syntax_Syntax.fv_eq_lid fv
                    FStarC_Parser_Const.op_Addition)
                   ||
                   (FStarC_Syntax_Syntax.fv_eq_lid fv
                      FStarC_Parser_Const.op_Subtraction))
                  ||
                  (FStarC_Syntax_Syntax.fv_eq_lid fv
                     FStarC_Parser_Const.op_Multiply))
                 ||
                 (FStarC_Syntax_Syntax.fv_eq_lid fv
                    FStarC_Parser_Const.op_Division))
                ||
                (FStarC_Syntax_Syntax.fv_eq_lid fv
                   FStarC_Parser_Const.op_Modulus))
               ||
               (FStarC_Syntax_Syntax.fv_eq_lid fv
                  FStarC_Parser_Const.real_op_LT))
              ||
              (FStarC_Syntax_Syntax.fv_eq_lid fv
                 FStarC_Parser_Const.real_op_LTE))
             ||
             (FStarC_Syntax_Syntax.fv_eq_lid fv
                FStarC_Parser_Const.real_op_GT))
            ||
            (FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.real_op_GTE))
           ||
           (FStarC_Syntax_Syntax.fv_eq_lid fv
              FStarC_Parser_Const.real_op_Addition))
          ||
          (FStarC_Syntax_Syntax.fv_eq_lid fv
             FStarC_Parser_Const.real_op_Subtraction))
         ||
         (FStarC_Syntax_Syntax.fv_eq_lid fv
            FStarC_Parser_Const.real_op_Multiply))
        ||
        (FStarC_Syntax_Syntax.fv_eq_lid fv
           FStarC_Parser_Const.real_op_Division)
  | (FStarC_Syntax_Syntax.Tm_fvar fv, uu___::[]) ->
      FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.op_Minus
  | uu___ -> false
let isInteger (tm : FStarC_Syntax_Syntax.term') : Prims.bool=
  match tm with
  | FStarC_Syntax_Syntax.Tm_constant (FStarC_Const.Const_int
      (n, FStar_Pervasives_Native.None)) -> true
  | uu___ -> false
let getInteger (tm : FStarC_Syntax_Syntax.term') : Prims.int=
  match tm with
  | FStarC_Syntax_Syntax.Tm_constant (FStarC_Const.Const_int
      (n, FStar_Pervasives_Native.None)) -> FStarC_Util.int_of_string n
  | uu___ -> failwith "Expected an Integer term"
let is_BitVector_primitive
  (head : FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax)
  (args :
    (FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax * 'uuuuu)
      Prims.list)
  : Prims.bool=
  match ((head.FStarC_Syntax_Syntax.n), args) with
  | (FStarC_Syntax_Syntax.Tm_fvar fv, (sz_arg, uu___)::uu___1::uu___2::[]) ->
      (((((((((((((((((((((FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.bv_and_lid)
                            ||
                            (FStarC_Syntax_Syntax.fv_eq_lid fv
                               FStarC_Parser_Const.bv_xor_lid))
                           ||
                           (FStarC_Syntax_Syntax.fv_eq_lid fv
                              FStarC_Parser_Const.bv_or_lid))
                          ||
                          (FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.bv_add_lid))
                         ||
                         (FStarC_Syntax_Syntax.fv_eq_lid fv
                            FStarC_Parser_Const.bv_sub_lid))
                        ||
                        (FStarC_Syntax_Syntax.fv_eq_lid fv
                           FStarC_Parser_Const.bv_shift_left_lid))
                       ||
                       (FStarC_Syntax_Syntax.fv_eq_lid fv
                          FStarC_Parser_Const.bv_shift_right_lid))
                      ||
                      (FStarC_Syntax_Syntax.fv_eq_lid fv
                         FStarC_Parser_Const.bv_udiv_lid))
                     ||
                     (FStarC_Syntax_Syntax.fv_eq_lid fv
                        FStarC_Parser_Const.bv_mod_lid))
                    ||
                    (FStarC_Syntax_Syntax.fv_eq_lid fv
                       FStarC_Parser_Const.bv_mul_lid))
                   ||
                   (FStarC_Syntax_Syntax.fv_eq_lid fv
                      FStarC_Parser_Const.bv_shift_left'_lid))
                  ||
                  (FStarC_Syntax_Syntax.fv_eq_lid fv
                     FStarC_Parser_Const.bv_shift_right'_lid))
                 ||
                 (FStarC_Syntax_Syntax.fv_eq_lid fv
                    FStarC_Parser_Const.bv_rotate_left_lid))
                ||
                (FStarC_Syntax_Syntax.fv_eq_lid fv
                   FStarC_Parser_Const.bv_rotate_right_lid))
               ||
               (FStarC_Syntax_Syntax.fv_eq_lid fv
                  FStarC_Parser_Const.bv_rotate_left'_lid))
              ||
              (FStarC_Syntax_Syntax.fv_eq_lid fv
                 FStarC_Parser_Const.bv_rotate_right'_lid))
             ||
             (FStarC_Syntax_Syntax.fv_eq_lid fv
                FStarC_Parser_Const.bv_udiv_unsafe_lid))
            ||
            (FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.bv_mod_unsafe_lid))
           ||
           (FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.bv_mul'_lid))
          ||
          (FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.bv_ult_lid))
         ||
         (FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.bv_uext_lid))
        && (isInteger sz_arg.FStarC_Syntax_Syntax.n)
  | (FStarC_Syntax_Syntax.Tm_fvar fv, (sz_arg, uu___)::uu___1::[]) ->
      (((FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.nat_to_bv_lid)
          ||
          (FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.bv_not_lid))
         ||
         (FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.bv_to_nat_lid))
        && (isInteger sz_arg.FStarC_Syntax_Syntax.n)
  | uu___ -> false
let encode_univ_name (u : FStarC_Syntax_Syntax.univ_name) :
  (FStarC_SMTEncoding_Term.fv * FStarC_SMTEncoding_Term.term)=
  let u1 =
    let uu___ = FStarC_Ident.string_of_id u in
    FStarC_SMTEncoding_Term.mk_U_name uu___ in
  match u1.FStarC_SMTEncoding_Term.tm with
  | FStarC_SMTEncoding_Term.FreeV fv -> (fv, u1)
  | uu___ -> failwith "Impossible"
let rec encode_universe (u : FStarC_Syntax_Syntax.universe) :
  FStarC_SMTEncoding_Term.term=
  match u with
  | FStarC_Syntax_Syntax.U_bvar uu___ ->
      failwith "Impossible: Locally nameless universes only"
  | FStarC_Syntax_Syntax.U_zero -> FStarC_SMTEncoding_Term.mk_U_zero
  | FStarC_Syntax_Syntax.U_succ u1 ->
      let uu___ = encode_universe u1 in
      FStarC_SMTEncoding_Term.mk_U_succ uu___
  | FStarC_Syntax_Syntax.U_max (u1::us) ->
      let uu___ = encode_universe u1 in
      FStarC_List.fold_right
        (fun u2 out ->
           let uu___1 = encode_universe u2 in
           FStarC_SMTEncoding_Term.mk_U_max out uu___1) us uu___
  | FStarC_Syntax_Syntax.U_name univ_name ->
      let uu___ = FStarC_Ident.string_of_id univ_name in
      FStarC_SMTEncoding_Term.mk_U_name uu___
  | FStarC_Syntax_Syntax.U_unif uv ->
      let uu___ =
        let uu___1 = FStarC_Syntax_Unionfind.univ_uvar_id uv in
        FStarC_SMTEncoding_Util.mkInteger' uu___1 in
      FStarC_SMTEncoding_Term.mk_U_unif uu___
  | FStarC_Syntax_Syntax.U_unknown -> FStarC_SMTEncoding_Term.mk_U_unknown
let rec encode_const (c : FStarC_Const.sconst)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_elt
    Prims.list)=
  FStarC_Errors.with_ctx "While encoding a constant to SMT"
    (fun uu___ ->
       match c with
       | FStarC_Const.Const_unit ->
           (FStarC_SMTEncoding_Term.mk_Term_unit, [])
       | FStarC_Const.Const_bool true ->
           let uu___1 =
             FStarC_SMTEncoding_Term.boxBool FStarC_SMTEncoding_Util.mkTrue in
           (uu___1, [])
       | FStarC_Const.Const_bool false ->
           let uu___1 =
             FStarC_SMTEncoding_Term.boxBool FStarC_SMTEncoding_Util.mkFalse in
           (uu___1, [])
       | FStarC_Const.Const_char c1 ->
           let uu___1 =
             let uu___2 =
               let uu___3 =
                 let uu___4 =
                   let uu___5 =
                     FStarC_SMTEncoding_Util.mkInteger'
                       (FStarC_Util.int_of_char c1) in
                   FStarC_SMTEncoding_Term.boxInt uu___5 in
                 [uu___4] in
               ("FStar.Char.__char_of_int", uu___3) in
             FStarC_SMTEncoding_Util.mkApp uu___2 in
           (uu___1, [])
       | FStarC_Const.Const_int (i, FStar_Pervasives_Native.None) ->
           let uu___1 =
             let uu___2 = FStarC_SMTEncoding_Util.mkInteger i in
             FStarC_SMTEncoding_Term.boxInt uu___2 in
           (uu___1, [])
       | FStarC_Const.Const_int (repr, FStar_Pervasives_Native.Some sw) ->
           let syntax_term =
             FStarC_ToSyntax_ToSyntax.desugar_machine_integer
               (env.FStarC_SMTEncoding_Env.tcenv).FStarC_TypeChecker_Env.dsenv
               repr sw FStarC_Range_Type.dummyRange in
           encode_term syntax_term env
       | FStarC_Const.Const_string (s, uu___1) ->
           let uu___2 =
             let uu___3 = FStarC_SMTEncoding_Util.mk_String_const s in
             FStarC_SMTEncoding_Term.boxString uu___3 in
           (uu___2, [])
       | FStarC_Const.Const_range uu___1 ->
           let uu___2 = FStarC_SMTEncoding_Term.mk_Range_const () in
           (uu___2, [])
       | FStarC_Const.Const_effect ->
           let uu___1 =
             FStarC_SMTEncoding_Term.mk_Term_type
               FStarC_SMTEncoding_Term.mk_U_zero in
           (uu___1, [])
       | FStarC_Const.Const_real r ->
           let uu___1 =
             let uu___2 = FStarC_SMTEncoding_Util.mkReal r in
             FStarC_SMTEncoding_Term.boxReal uu___2 in
           (uu___1, [])
       | c1 ->
           let uu___1 =
             let uu___2 =
               FStarC_Class_Show.show FStarC_Syntax_Print.showable_const c1 in
             FStarC_Format.fmt1 "Unhandled constant: %s" uu___2 in
           failwith uu___1)
and encode_binders
  (fuel_opt : FStarC_SMTEncoding_Term.term FStar_Pervasives_Native.option)
  (bs : FStarC_Syntax_Syntax.binders) (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.fv Prims.list * FStarC_SMTEncoding_Term.term
    Prims.list * FStarC_SMTEncoding_Env.env_t *
    FStarC_SMTEncoding_Term.decls_t * FStarC_Syntax_Syntax.bv Prims.list)=
  (let uu___1 = FStarC_Debug.medium () in
   if uu___1
   then
     let uu___2 =
       FStarC_Class_Show.show
         (FStarC_Class_Show.show_list FStarC_Syntax_Print.showable_binder) bs in
     FStarC_Format.print1 "Encoding binders %s\n" uu___2
   else ());
  (let uu___1 =
     FStarC_List.fold_left
       (fun uu___2 b ->
          match uu___2 with
          | (vars, guards, env1, decls, names) ->
              let uu___3 =
                let x = b.FStarC_Syntax_Syntax.binder_bv in
                let uu___4 = FStarC_SMTEncoding_Env.gen_term_var env1 x in
                match uu___4 with
                | (xxsym, xx, env') ->
                    let uu___5 =
                      let uu___6 = norm env1 x.FStarC_Syntax_Syntax.sort in
                      encode_term_pred fuel_opt uu___6 env1 xx in
                    (match uu___5 with
                     | (guard_x_t, decls') ->
                         let uu___6 =
                           FStarC_SMTEncoding_Term.mk_fv
                             (xxsym, FStarC_SMTEncoding_Term.Term_sort) in
                         (uu___6, guard_x_t, env', decls', x)) in
              (match uu___3 with
               | (v, g, env2, decls', n) ->
                   ((v :: vars), (g :: guards), env2,
                     (FStarC_List.op_At decls decls'), (n :: names))))
       ([], [], env, [], []) bs in
   match uu___1 with
   | (vars, guards, env1, decls, names) ->
       ((FStarC_List.rev vars), (FStarC_List.rev guards), env1, decls,
         (FStarC_List.rev names)))
and encode_term_pred
  (fuel_opt : FStarC_SMTEncoding_Term.term FStar_Pervasives_Native.option)
  (t : FStarC_Syntax_Syntax.typ) (env : FStarC_SMTEncoding_Env.env_t)
  (e : FStarC_SMTEncoding_Term.term) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let uu___ = encode_term t env in
  match uu___ with
  | (t1, decls) ->
      let uu___1 = FStarC_SMTEncoding_Term.mk_HasTypeWithFuel fuel_opt e t1 in
      (uu___1, decls)
and encode_arith_term (env : FStarC_SMTEncoding_Env.env_t)
  (head : FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax)
  (args_e : FStarC_Syntax_Syntax.args) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let uu___ = encode_args args_e env in
  match uu___ with
  | (arg_tms, decls) ->
      let head_fv =
        match head.FStarC_Syntax_Syntax.n with
        | FStarC_Syntax_Syntax.Tm_fvar fv -> fv
        | uu___1 -> failwith "Impossible" in
      let unary unbox arg_tms1 =
        let uu___1 = FStarC_List.hd arg_tms1 in unbox uu___1 in
      let binary unbox arg_tms1 =
        let uu___1 = let uu___2 = FStarC_List.hd arg_tms1 in unbox uu___2 in
        let uu___2 =
          let uu___3 =
            let uu___4 = FStarC_List.tl arg_tms1 in FStarC_List.hd uu___4 in
          unbox uu___3 in
        (uu___1, uu___2) in
      let mk_default uu___1 =
        let uu___2 =
          FStarC_SMTEncoding_Env.lookup_free_var_sym env
            head_fv.FStarC_Syntax_Syntax.fv_name in
        match uu___2 with
        | (fname, fuel_args, arity) ->
            let args = FStarC_List.op_At fuel_args arg_tms in
            maybe_curry_app head.FStarC_Syntax_Syntax.pos fname arity args in
      let mk_l box op mk_args ts =
        let uu___1 = FStarC_Options.smtencoding_l_arith_native () in
        if uu___1
        then let uu___2 = let uu___3 = mk_args ts in op uu___3 in box uu___2
        else mk_default () in
      let mk_nl box unbox nm op ts =
        let uu___1 = FStarC_Options.smtencoding_nl_arith_wrapped () in
        if uu___1
        then
          let uu___2 = binary unbox ts in
          match uu___2 with
          | (t1, t2) ->
              let uu___3 = FStarC_SMTEncoding_Util.mkApp (nm, [t1; t2]) in
              box uu___3
        else
          (let uu___3 = FStarC_Options.smtencoding_nl_arith_native () in
           if uu___3
           then
             let uu___4 = let uu___5 = binary unbox ts in op uu___5 in
             box uu___4
           else mk_default ()) in
      let add box unbox =
        mk_l box FStarC_SMTEncoding_Util.mkAdd (binary unbox) in
      let sub box unbox =
        mk_l box FStarC_SMTEncoding_Util.mkSub (binary unbox) in
      let minus box unbox =
        mk_l box FStarC_SMTEncoding_Util.mkMinus (unary unbox) in
      let mul box unbox nm = mk_nl box unbox nm FStarC_SMTEncoding_Util.mkMul in
      let div box unbox nm = mk_nl box unbox nm FStarC_SMTEncoding_Util.mkDiv in
      let modulus box unbox =
        mk_nl box unbox "_mod" FStarC_SMTEncoding_Util.mkMod in
      let ops =
        [(FStarC_Parser_Const.op_Addition,
           (add FStarC_SMTEncoding_Term.boxInt
              FStarC_SMTEncoding_Term.unboxInt));
        (FStarC_Parser_Const.op_Subtraction,
          (sub FStarC_SMTEncoding_Term.boxInt
             FStarC_SMTEncoding_Term.unboxInt));
        (FStarC_Parser_Const.op_Multiply,
          (mul FStarC_SMTEncoding_Term.boxInt
             FStarC_SMTEncoding_Term.unboxInt "_mul"));
        (FStarC_Parser_Const.op_Division,
          (div FStarC_SMTEncoding_Term.boxInt
             FStarC_SMTEncoding_Term.unboxInt "_div"));
        (FStarC_Parser_Const.op_Modulus,
          (modulus FStarC_SMTEncoding_Term.boxInt
             FStarC_SMTEncoding_Term.unboxInt));
        (FStarC_Parser_Const.op_Minus,
          (minus FStarC_SMTEncoding_Term.boxInt
             FStarC_SMTEncoding_Term.unboxInt));
        (FStarC_Parser_Const.real_op_Addition,
          (add FStarC_SMTEncoding_Term.boxReal
             FStarC_SMTEncoding_Term.unboxReal));
        (FStarC_Parser_Const.real_op_Subtraction,
          (sub FStarC_SMTEncoding_Term.boxReal
             FStarC_SMTEncoding_Term.unboxReal));
        (FStarC_Parser_Const.real_op_Multiply,
          (mul FStarC_SMTEncoding_Term.boxReal
             FStarC_SMTEncoding_Term.unboxReal "_rmul"));
        (FStarC_Parser_Const.real_op_Division,
          (mk_nl FStarC_SMTEncoding_Term.boxReal
             FStarC_SMTEncoding_Term.unboxReal "_rdiv"
             FStarC_SMTEncoding_Util.mkRealDiv));
        (FStarC_Parser_Const.real_op_LT,
          (mk_l FStarC_SMTEncoding_Term.boxBool FStarC_SMTEncoding_Util.mkLT
             (binary FStarC_SMTEncoding_Term.unboxReal)));
        (FStarC_Parser_Const.real_op_LTE,
          (mk_l FStarC_SMTEncoding_Term.boxBool FStarC_SMTEncoding_Util.mkLTE
             (binary FStarC_SMTEncoding_Term.unboxReal)));
        (FStarC_Parser_Const.real_op_GT,
          (mk_l FStarC_SMTEncoding_Term.boxBool FStarC_SMTEncoding_Util.mkGT
             (binary FStarC_SMTEncoding_Term.unboxReal)));
        (FStarC_Parser_Const.real_op_GTE,
          (mk_l FStarC_SMTEncoding_Term.boxBool FStarC_SMTEncoding_Util.mkGTE
             (binary FStarC_SMTEncoding_Term.unboxReal)))] in
      let uu___1 =
        let uu___2 =
          FStarC_List.tryFind
            (fun uu___3 ->
               match uu___3 with
               | (l, uu___4) -> FStarC_Syntax_Syntax.fv_eq_lid head_fv l) ops in
        FStar_Pervasives_Native.__proj__Some__item__v uu___2 in
      (match uu___1 with
       | (uu___2, op) -> let uu___3 = op arg_tms in (uu___3, decls))
and encode_BitVector_term (env : FStarC_SMTEncoding_Env.env_t)
  (head : FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax)
  (args_e :
    (FStarC_Syntax_Syntax.term' FStarC_Syntax_Syntax.syntax *
      FStarC_Syntax_Syntax.arg_qualifier FStar_Pervasives_Native.option)
      Prims.list)
  :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_elt
    Prims.list)=
  let uu___ = FStarC_List.hd args_e in
  match uu___ with
  | (tm_sz, uu___1) ->
      let uu___2 = uu___ in
      let sz = getInteger tm_sz.FStarC_Syntax_Syntax.n in
      let sz_key =
        let uu___3 = FStarC_Class_Show.show FStarC_Class_Show.showable_int sz in
        FStarC_Format.fmt1 "BitVector_%s" uu___3 in
      let sz_decls =
        let uu___3 = FStarC_SMTEncoding_Term.mkBvConstructor sz in
        match uu___3 with
        | (t_decls, constr_name, discriminator_name) ->
            let uu___4 =
              let uu___5 =
                let head1 =
                  FStarC_Syntax_Syntax.lid_as_fv FStarC_Parser_Const.bv_t_lid
                    FStar_Pervasives_Native.None in
                let t =
                  let uu___6 = FStarC_Syntax_Syntax.fv_to_tm head1 in
                  FStarC_Syntax_Util.mk_app uu___6
                    [(tm_sz, FStar_Pervasives_Native.None)] in
                encode_term t env in
              match uu___5 with
              | (bv_t_n, decls) ->
                  let xsym =
                    let uu___6 =
                      let uu___7 =
                        FStarC_SMTEncoding_Env.varops.FStarC_SMTEncoding_Env.fresh
                          env.FStarC_SMTEncoding_Env.current_module_name "x" in
                      (uu___7, FStarC_SMTEncoding_Term.Term_sort) in
                    FStarC_SMTEncoding_Term.mk_fv uu___6 in
                  let x = FStarC_SMTEncoding_Util.mkFreeV xsym in
                  let x_has_type_bv_t_n =
                    FStarC_SMTEncoding_Term.mk_HasType x bv_t_n in
                  let ax =
                    let uu___6 =
                      let uu___7 =
                        let uu___8 =
                          let uu___9 =
                            FStarC_SMTEncoding_Util.mkApp
                              (discriminator_name, [x]) in
                          (x_has_type_bv_t_n, uu___9) in
                        FStarC_SMTEncoding_Util.mkImp uu___8 in
                      ([[x_has_type_bv_t_n]], [xsym], uu___7) in
                    FStarC_SMTEncoding_Term.mkForall
                      head.FStarC_Syntax_Syntax.pos uu___6 in
                  let name = Prims.strcat "typing_inversion_for_" constr_name in
                  let uu___6 =
                    FStarC_SMTEncoding_Util.mkAssume
                      (ax, (FStar_Pervasives_Native.Some name), name) in
                  (decls, uu___6) in
            (match uu___4 with
             | (decls, typing_inversion) ->
                 let uu___5 =
                   FStarC_SMTEncoding_Term.mk_decls "" sz_key
                     (FStarC_List.op_At t_decls [typing_inversion]) [] in
                 FStarC_List.op_At decls uu___5) in
      let uu___3 =
        match ((head.FStarC_Syntax_Syntax.n), args_e) with
        | (FStarC_Syntax_Syntax.Tm_fvar fv,
           uu___4::(sz_arg, uu___5)::uu___6::[]) when
            (FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.bv_uext_lid)
              && (isInteger sz_arg.FStarC_Syntax_Syntax.n)
            ->
            let uu___7 =
              let uu___8 = FStarC_List.tail args_e in FStarC_List.tail uu___8 in
            let uu___8 =
              let uu___9 = getInteger sz_arg.FStarC_Syntax_Syntax.n in
              FStar_Pervasives_Native.Some uu___9 in
            (uu___7, uu___8)
        | (FStarC_Syntax_Syntax.Tm_fvar fv,
           uu___4::(sz_arg, uu___5)::uu___6::[]) when
            FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.bv_uext_lid
            ->
            let uu___7 =
              let uu___8 =
                FStarC_Class_Show.show FStarC_Syntax_Print.showable_term
                  sz_arg in
              FStarC_Format.fmt1 "Not a constant bitvector extend size: %s"
                uu___8 in
            failwith uu___7
        | uu___4 ->
            let uu___5 = FStarC_List.tail args_e in
            (uu___5, FStar_Pervasives_Native.None) in
      (match uu___3 with
       | (arg_tms, ext_sz) ->
           let uu___4 = encode_args arg_tms env in
           (match uu___4 with
            | (arg_tms1, decls) ->
                let head_fv =
                  match head.FStarC_Syntax_Syntax.n with
                  | FStarC_Syntax_Syntax.Tm_fvar fv -> fv
                  | uu___5 -> failwith "Impossible" in
                let unary arg_tms2 =
                  let uu___5 = FStarC_List.hd arg_tms2 in
                  FStarC_SMTEncoding_Term.unboxBitVec sz uu___5 in
                let unary_arith arg_tms2 =
                  let uu___5 = FStarC_List.hd arg_tms2 in
                  FStarC_SMTEncoding_Term.unboxInt uu___5 in
                let binary arg_tms2 =
                  let uu___5 =
                    let uu___6 = FStarC_List.hd arg_tms2 in
                    FStarC_SMTEncoding_Term.unboxBitVec sz uu___6 in
                  let uu___6 =
                    let uu___7 =
                      let uu___8 = FStarC_List.tl arg_tms2 in
                      FStarC_List.hd uu___8 in
                    FStarC_SMTEncoding_Term.unboxBitVec sz uu___7 in
                  (uu___5, uu___6) in
                let binary_arith arg_tms2 =
                  let uu___5 =
                    let uu___6 = FStarC_List.hd arg_tms2 in
                    FStarC_SMTEncoding_Term.unboxBitVec sz uu___6 in
                  let uu___6 =
                    let uu___7 =
                      let uu___8 = FStarC_List.tl arg_tms2 in
                      FStarC_List.hd uu___8 in
                    FStarC_SMTEncoding_Term.unboxInt uu___7 in
                  (uu___5, uu___6) in
                let mk_bv op mk_args resBox ts =
                  let uu___5 = let uu___6 = mk_args ts in op uu___6 in
                  resBox uu___5 in
                let bv_and =
                  mk_bv FStarC_SMTEncoding_Util.mkBvAnd binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_xor =
                  mk_bv FStarC_SMTEncoding_Util.mkBvXor binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_or =
                  mk_bv FStarC_SMTEncoding_Util.mkBvOr binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_add =
                  mk_bv FStarC_SMTEncoding_Util.mkBvAdd binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_sub =
                  mk_bv FStarC_SMTEncoding_Util.mkBvSub binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_shl =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvShl sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_shr =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvShr sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_rol =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvRol sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_ror =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvRor sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_udiv =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvUdiv sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_mod =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvMod sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_mul =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvMul sz) binary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_shl' =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvShl' sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_shr' =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvShr' sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_rol' =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvRol' sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_ror' =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvRor' sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_udiv_unsafe =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvUdivUnsafe sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_mod_unsafe =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvModUnsafe sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_mul' =
                  mk_bv (FStarC_SMTEncoding_Util.mkBvMul' sz) binary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let bv_ult =
                  mk_bv FStarC_SMTEncoding_Util.mkBvUlt binary
                    FStarC_SMTEncoding_Term.boxBool in
                let bv_uext arg_tms2 =
                  let uu___5 =
                    let uu___6 =
                      match ext_sz with
                      | FStar_Pervasives_Native.Some x -> x
                      | FStar_Pervasives_Native.None -> failwith "impossible" in
                    FStarC_SMTEncoding_Util.mkBvUext uu___6 in
                  let uu___6 =
                    let uu___7 =
                      let uu___8 =
                        match ext_sz with
                        | FStar_Pervasives_Native.Some x -> x
                        | FStar_Pervasives_Native.None ->
                            failwith "impossible" in
                      sz + uu___8 in
                    FStarC_SMTEncoding_Term.boxBitVec uu___7 in
                  mk_bv uu___5 unary uu___6 arg_tms2 in
                let bv_not =
                  mk_bv FStarC_SMTEncoding_Util.mkBvNot unary
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let to_int =
                  mk_bv FStarC_SMTEncoding_Util.mkBvToNat unary
                    FStarC_SMTEncoding_Term.boxInt in
                let bv_to =
                  mk_bv (FStarC_SMTEncoding_Util.mkNatToBv sz) unary_arith
                    (FStarC_SMTEncoding_Term.boxBitVec sz) in
                let ops =
                  [(FStarC_Parser_Const.bv_and_lid, bv_and);
                  (FStarC_Parser_Const.bv_xor_lid, bv_xor);
                  (FStarC_Parser_Const.bv_or_lid, bv_or);
                  (FStarC_Parser_Const.bv_add_lid, bv_add);
                  (FStarC_Parser_Const.bv_sub_lid, bv_sub);
                  (FStarC_Parser_Const.bv_shift_left_lid, bv_shl);
                  (FStarC_Parser_Const.bv_shift_right_lid, bv_shr);
                  (FStarC_Parser_Const.bv_rotate_left_lid, bv_rol);
                  (FStarC_Parser_Const.bv_rotate_right_lid, bv_ror);
                  (FStarC_Parser_Const.bv_udiv_lid, bv_udiv);
                  (FStarC_Parser_Const.bv_mod_lid, bv_mod);
                  (FStarC_Parser_Const.bv_mul_lid, bv_mul);
                  (FStarC_Parser_Const.bv_shift_left'_lid, bv_shl');
                  (FStarC_Parser_Const.bv_shift_right'_lid, bv_shr');
                  (FStarC_Parser_Const.bv_rotate_left'_lid, bv_rol');
                  (FStarC_Parser_Const.bv_rotate_right'_lid, bv_ror');
                  (FStarC_Parser_Const.bv_udiv_unsafe_lid, bv_udiv_unsafe);
                  (FStarC_Parser_Const.bv_mod_unsafe_lid, bv_mod_unsafe);
                  (FStarC_Parser_Const.bv_mul'_lid, bv_mul');
                  (FStarC_Parser_Const.bv_ult_lid, bv_ult);
                  (FStarC_Parser_Const.bv_not_lid, bv_not);
                  (FStarC_Parser_Const.bv_uext_lid, bv_uext);
                  (FStarC_Parser_Const.bv_to_nat_lid, to_int);
                  (FStarC_Parser_Const.nat_to_bv_lid, bv_to)] in
                let uu___5 =
                  let uu___6 =
                    FStarC_List.tryFind
                      (fun uu___7 ->
                         match uu___7 with
                         | (l, uu___8) ->
                             FStarC_Syntax_Syntax.fv_eq_lid head_fv l) ops in
                  FStar_Pervasives_Native.__proj__Some__item__v uu___6 in
                (match uu___5 with
                 | (uu___6, op) ->
                     let uu___7 = op arg_tms1 in
                     (uu___7, (FStarC_List.op_At sz_decls decls)))))
and encode_deeply_embedded_quantifier (t : FStarC_Syntax_Syntax.term)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let env1 =
    {
      FStarC_SMTEncoding_Env.bvar_bindings =
        (env.FStarC_SMTEncoding_Env.bvar_bindings);
      FStarC_SMTEncoding_Env.fvar_bindings =
        (env.FStarC_SMTEncoding_Env.fvar_bindings);
      FStarC_SMTEncoding_Env.depth = (env.FStarC_SMTEncoding_Env.depth);
      FStarC_SMTEncoding_Env.tcenv = (env.FStarC_SMTEncoding_Env.tcenv);
      FStarC_SMTEncoding_Env.warn = (env.FStarC_SMTEncoding_Env.warn);
      FStarC_SMTEncoding_Env.nolabels = (env.FStarC_SMTEncoding_Env.nolabels);
      FStarC_SMTEncoding_Env.use_zfuel_name =
        (env.FStarC_SMTEncoding_Env.use_zfuel_name);
      FStarC_SMTEncoding_Env.encode_non_total_function_typ =
        (env.FStarC_SMTEncoding_Env.encode_non_total_function_typ);
      FStarC_SMTEncoding_Env.current_module_name =
        (env.FStarC_SMTEncoding_Env.current_module_name);
      FStarC_SMTEncoding_Env.encoding_quantifier = true;
      FStarC_SMTEncoding_Env.global_cache =
        (env.FStarC_SMTEncoding_Env.global_cache)
    } in
  let uu___ = encode_term t env1 in
  match uu___ with
  | (tm, decls) ->
      let vars = FStarC_SMTEncoding_Term.free_variables tm in
      let valid_tm = FStarC_SMTEncoding_Term.mk_Valid tm in
      let key =
        FStarC_SMTEncoding_Term.mkForall t.FStarC_Syntax_Syntax.pos
          ([], vars, valid_tm) in
      let tkey_hash = FStarC_SMTEncoding_Term.hash_of_term key in
      (match tm.FStarC_SMTEncoding_Term.tm with
       | FStarC_SMTEncoding_Term.App
           (uu___1,
            {
              FStarC_SMTEncoding_Term.tm = FStarC_SMTEncoding_Term.FreeV
                uu___2;
              FStarC_SMTEncoding_Term.freevars = uu___3;
              FStarC_SMTEncoding_Term.rng = uu___4;_}::{
                                                         FStarC_SMTEncoding_Term.tm
                                                           =
                                                           FStarC_SMTEncoding_Term.FreeV
                                                           uu___5;
                                                         FStarC_SMTEncoding_Term.freevars
                                                           = uu___6;
                                                         FStarC_SMTEncoding_Term.rng
                                                           = uu___7;_}::[])
           ->
           (FStarC_Errors.log_issue
              (FStarC_Syntax_Syntax.has_range_syntax ()) t
              FStarC_Errors_Codes.Warning_QuantifierWithoutPattern ()
              (Obj.magic FStarC_Errors_Msg.is_error_message_string)
              (Obj.magic
                 "Not encoding deeply embedded, unguarded quantifier to SMT");
            (tm, decls))
       | uu___1 ->
           let uu___2 = encode_formula t env1 in
           (match uu___2 with
            | (phi, decls') ->
                let interp =
                  match vars with
                  | [] ->
                      let uu___3 =
                        let uu___4 = FStarC_SMTEncoding_Term.mk_Valid tm in
                        (uu___4, phi) in
                      FStarC_SMTEncoding_Util.mkIff uu___3
                  | uu___3 ->
                      let uu___4 =
                        let uu___5 =
                          let uu___6 =
                            let uu___7 = FStarC_SMTEncoding_Term.mk_Valid tm in
                            (uu___7, phi) in
                          FStarC_SMTEncoding_Util.mkIff uu___6 in
                        ([[valid_tm]], vars, uu___5) in
                      FStarC_SMTEncoding_Term.mkForall
                        t.FStarC_Syntax_Syntax.pos uu___4 in
                let ax =
                  let uu___3 =
                    let uu___4 =
                      let uu___5 = FStarC_Util.digest_of_string tkey_hash in
                      Prims.strcat "l_quant_interp_" uu___5 in
                    (interp,
                      (FStar_Pervasives_Native.Some
                         "Interpretation of deeply embedded quantifier"),
                      uu___4) in
                  FStarC_SMTEncoding_Util.mkAssume uu___3 in
                let uu___3 =
                  let uu___4 =
                    let uu___5 =
                      FStarC_SMTEncoding_Term.mk_decls "" tkey_hash [ax]
                        (FStarC_List.op_At decls decls') in
                    FStarC_List.op_At decls' uu___5 in
                  FStarC_List.op_At decls uu___4 in
                (tm, uu___3)))
and encode_term (t : FStarC_Syntax_Syntax.typ)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  FStarC_Defensive.def_check_scoped FStarC_TypeChecker_Env.hasBinders_env
    FStarC_Class_Binders.hasNames_term FStarC_Syntax_Print.pretty_term
    t.FStarC_Syntax_Syntax.pos "encode_term" env.FStarC_SMTEncoding_Env.tcenv
    t;
  (let t1 = FStarC_Syntax_Subst.compress t in
   let t0 = t1 in
   (let uu___2 = FStarC_Effect.op_Bang dbg_SMTEncoding in
    if uu___2
    then
      let uu___3 =
        FStarC_Class_Tagged.tag_of FStarC_Syntax_Syntax.tagged_term t1 in
      let uu___4 =
        FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t1 in
      FStarC_Format.print2 "(%s)   %s\n" uu___3 uu___4
    else ());
   (match t1.FStarC_Syntax_Syntax.n with
    | FStarC_Syntax_Syntax.Tm_delayed uu___2 ->
        let uu___3 =
          let uu___4 =
            FStarC_Range_Ops.string_of_range t1.FStarC_Syntax_Syntax.pos in
          let uu___5 =
            FStarC_Class_Tagged.tag_of FStarC_Syntax_Syntax.tagged_term t1 in
          let uu___6 =
            FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t1 in
          FStarC_Format.fmt3 "(%s) Impossible: %s\n%s\n" uu___4 uu___5 uu___6 in
        failwith uu___3
    | FStarC_Syntax_Syntax.Tm_unknown ->
        let uu___2 =
          let uu___3 =
            FStarC_Range_Ops.string_of_range t1.FStarC_Syntax_Syntax.pos in
          let uu___4 =
            FStarC_Class_Tagged.tag_of FStarC_Syntax_Syntax.tagged_term t1 in
          let uu___5 =
            FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t1 in
          FStarC_Format.fmt3 "(%s) Impossible: %s\n%s\n" uu___3 uu___4 uu___5 in
        failwith uu___2
    | FStarC_Syntax_Syntax.Tm_lazy i ->
        let e = FStarC_Syntax_Util.unfold_lazy i in
        ((let uu___3 = FStarC_Effect.op_Bang dbg_SMTEncoding in
          if uu___3
          then
            let uu___4 =
              FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t1 in
            let uu___5 =
              FStarC_Class_Show.show FStarC_Syntax_Print.showable_term e in
            FStarC_Format.print2 ">> Unfolded (%s) ~> (%s)\n" uu___4 uu___5
          else ());
         encode_term e env)
    | FStarC_Syntax_Syntax.Tm_bvar x ->
        let uu___2 =
          let uu___3 =
            FStarC_Class_Show.show FStarC_Syntax_Print.showable_bv x in
          FStarC_Format.fmt1 "Impossible: locally nameless; got %s" uu___3 in
        failwith uu___2
    | FStarC_Syntax_Syntax.Tm_ascribed
        { FStarC_Syntax_Syntax.tm = t2;
          FStarC_Syntax_Syntax.asc = (k, uu___2, uu___3);
          FStarC_Syntax_Syntax.eff_opt = uu___4;_}
        ->
        let uu___5 =
          match k with
          | FStar_Pervasives.Inl t3 -> FStarC_Syntax_Util.is_unit t3
          | uu___6 -> false in
        if uu___5
        then (FStarC_SMTEncoding_Term.mk_Term_unit, [])
        else encode_term t2 env
    | FStarC_Syntax_Syntax.Tm_quoted (qt, uu___2) ->
        let tv =
          let uu___3 =
            let uu___4 = FStarC_Reflection_V2_Builtins.inspect_ln qt in
            FStarC_Syntax_Embeddings_Base.embed
              FStarC_Reflection_V2_Embeddings.e_term_view uu___4 in
          uu___3 t1.FStarC_Syntax_Syntax.pos FStar_Pervasives_Native.None
            FStarC_Syntax_Embeddings_Base.id_norm_cb in
        ((let uu___4 = FStarC_Effect.op_Bang dbg_SMTEncoding in
          if uu___4
          then
            let uu___5 =
              FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t0 in
            let uu___6 =
              FStarC_Class_Show.show FStarC_Syntax_Print.showable_term tv in
            FStarC_Format.print2 ">> Inspected (%s) ~> (%s)\n" uu___5 uu___6
          else ());
         (let t2 =
            let uu___4 =
              let uu___5 = FStarC_Syntax_Syntax.as_arg tv in [uu___5] in
            FStarC_Syntax_Util.mk_app
              (FStarC_Reflection_V2_Constants.refl_constant_term
                 FStarC_Reflection_V2_Constants.fstar_refl_pack_ln) uu___4 in
          encode_term t2 env))
    | FStarC_Syntax_Syntax.Tm_meta
        { FStarC_Syntax_Syntax.tm2 = t2;
          FStarC_Syntax_Syntax.meta = FStarC_Syntax_Syntax.Meta_pattern
            uu___2;_}
        ->
        encode_term t2
          {
            FStarC_SMTEncoding_Env.bvar_bindings =
              (env.FStarC_SMTEncoding_Env.bvar_bindings);
            FStarC_SMTEncoding_Env.fvar_bindings =
              (env.FStarC_SMTEncoding_Env.fvar_bindings);
            FStarC_SMTEncoding_Env.depth = (env.FStarC_SMTEncoding_Env.depth);
            FStarC_SMTEncoding_Env.tcenv = (env.FStarC_SMTEncoding_Env.tcenv);
            FStarC_SMTEncoding_Env.warn = (env.FStarC_SMTEncoding_Env.warn);
            FStarC_SMTEncoding_Env.nolabels =
              (env.FStarC_SMTEncoding_Env.nolabels);
            FStarC_SMTEncoding_Env.use_zfuel_name =
              (env.FStarC_SMTEncoding_Env.use_zfuel_name);
            FStarC_SMTEncoding_Env.encode_non_total_function_typ =
              (env.FStarC_SMTEncoding_Env.encode_non_total_function_typ);
            FStarC_SMTEncoding_Env.current_module_name =
              (env.FStarC_SMTEncoding_Env.current_module_name);
            FStarC_SMTEncoding_Env.encoding_quantifier = false;
            FStarC_SMTEncoding_Env.global_cache =
              (env.FStarC_SMTEncoding_Env.global_cache)
          }
    | FStarC_Syntax_Syntax.Tm_meta
        { FStarC_Syntax_Syntax.tm2 = t2;
          FStarC_Syntax_Syntax.meta = uu___2;_}
        -> encode_term t2 env
    | FStarC_Syntax_Syntax.Tm_name x ->
        let t2 = FStarC_SMTEncoding_Env.lookup_term_var env x in (t2, [])
    | FStarC_Syntax_Syntax.Tm_type u ->
        let uu___2 =
          let uu___3 = encode_universe u in
          FStarC_SMTEncoding_Term.mk_Term_type uu___3 in
        (uu___2, [])
    | FStarC_Syntax_Syntax.Tm_uinst
        ({ FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
           FStarC_Syntax_Syntax.pos = uu___2;
           FStarC_Syntax_Syntax.vars = uu___3;
           FStarC_Syntax_Syntax.hash_code = uu___4;_},
         uu___5)
        when FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.lex_t_lid
        -> (FStarC_SMTEncoding_Util.mk_lex_t, [])
    | FStarC_Syntax_Syntax.Tm_uinst
        ({ FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
           FStarC_Syntax_Syntax.pos = uu___2;
           FStarC_Syntax_Syntax.vars = uu___3;
           FStarC_Syntax_Syntax.hash_code = uu___4;_},
         uu___5)
        when FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.lextop_lid
        -> (FStarC_SMTEncoding_Util.mk_LexTop, [])
    | FStarC_Syntax_Syntax.Tm_fvar v ->
        let us =
          match t1.FStarC_Syntax_Syntax.n with
          | FStarC_Syntax_Syntax.Tm_fvar uu___2 -> []
          | FStarC_Syntax_Syntax.Tm_uinst (uu___2, us1) -> us1 in
        let encode_freev uu___2 =
          let us1 = FStarC_List.map encode_universe us in
          let fvb =
            FStarC_SMTEncoding_Env.lookup_free_var_name env
              v.FStarC_Syntax_Syntax.fv_name in
          let tok =
            FStarC_SMTEncoding_Env.lookup_free_var env
              v.FStarC_Syntax_Syntax.fv_name in
          let uu___3 =
            match ((tok.FStarC_SMTEncoding_Term.tm), us1) with
            | (FStarC_SMTEncoding_Term.FreeV uu___4, uu___5::uu___6) ->
                failwith
                  "Impossible: Universe applications on nullary symbol"
            | (FStarC_SMTEncoding_Term.App
               (FStarC_SMTEncoding_Term.Var "ApplyTF",
                {
                  FStarC_SMTEncoding_Term.tm = FStarC_SMTEncoding_Term.FreeV
                    (FStarC_SMTEncoding_Term.FV (tok1, uu___4, uu___5));
                  FStarC_SMTEncoding_Term.freevars = uu___6;
                  FStarC_SMTEncoding_Term.rng = uu___7;_}::fuel::[]),
               us2) ->
                let uu___8 =
                  let uu___9 =
                    let uu___10 =
                      let uu___11 = FStarC_SMTEncoding_Util.mkApp (tok1, us2) in
                      [uu___11; fuel] in
                    ("ApplyTF", uu___10) in
                  FStarC_SMTEncoding_Util.mkApp uu___9 in
                (true, uu___8)
            | (FStarC_SMTEncoding_Term.App
               (FStarC_SMTEncoding_Term.Var "ApplyTF",
                {
                  FStarC_SMTEncoding_Term.tm = FStarC_SMTEncoding_Term.App
                    (FStarC_SMTEncoding_Term.Var tok1, []);
                  FStarC_SMTEncoding_Term.freevars = uu___4;
                  FStarC_SMTEncoding_Term.rng = uu___5;_}::fuel::[]),
               us2) ->
                let uu___6 =
                  let uu___7 =
                    let uu___8 =
                      let uu___9 = FStarC_SMTEncoding_Util.mkApp (tok1, us2) in
                      [uu___9; fuel] in
                    ("ApplyTF", uu___8) in
                  FStarC_SMTEncoding_Util.mkApp uu___7 in
                (true, uu___6)
            | (FStarC_SMTEncoding_Term.App (op, uu___4::uu___5),
               uu___6::uu___7) ->
                let uu___8 =
                  let uu___9 =
                    FStarC_Class_Show.show
                      FStarC_SMTEncoding_Term.showable_smt_term tok in
                  FStarC_Format.fmt1
                    "Impossible: Universe applications cannot be curried: head is %s"
                    uu___9 in
                failwith uu___8
            | (FStarC_SMTEncoding_Term.FreeV uu___4, []) -> (true, tok)
            | (FStarC_SMTEncoding_Term.App (op, []), us2) ->
                (true,
                  {
                    FStarC_SMTEncoding_Term.tm =
                      (FStarC_SMTEncoding_Term.App (op, us2));
                    FStarC_SMTEncoding_Term.freevars =
                      (tok.FStarC_SMTEncoding_Term.freevars);
                    FStarC_SMTEncoding_Term.rng =
                      (tok.FStarC_SMTEncoding_Term.rng)
                  })
            | (FStarC_SMTEncoding_Term.App (op, ts), []) -> (false, tok) in
          match uu___3 with
          | (is_nullary, tok1) ->
              let tkey_hash = FStarC_SMTEncoding_Term.hash_of_term tok1 in
              let uu___4 =
                if
                  (fvb.FStarC_SMTEncoding_Env.smt_arity > Prims.int_zero) &&
                    is_nullary
                then
                  let uu___5 = FStarC_SMTEncoding_Env.kick_partial_app fvb in
                  match uu___5 with
                  | FStar_Pervasives_Native.None -> ([], "")
                  | FStar_Pervasives_Native.Some kpa ->
                      let sym_name =
                        let uu___6 = FStarC_Util.digest_of_string tkey_hash in
                        Prims.strcat "@kick_partial_app_" uu___6 in
                      let uu___6 =
                        let uu___7 =
                          FStarC_SMTEncoding_Util.mkAssume
                            (kpa,
                              (FStar_Pervasives_Native.Some
                                 "kick_partial_app"), sym_name) in
                        [uu___7] in
                      (uu___6, sym_name)
                else ([], "") in
              (match uu___4 with
               | (aux_decls, sym_name) ->
                   let uu___5 =
                     if aux_decls = []
                     then FStarC_SMTEncoding_Term.mk_decls_trivial []
                     else
                       FStarC_SMTEncoding_Term.mk_decls sym_name tkey_hash
                         aux_decls [] in
                   (tok1, uu___5)) in
        let uu___2 = head_redex env t1 in
        if uu___2
        then
          let uu___3 = maybe_whnf env t1 in
          (match uu___3 with
           | FStar_Pervasives_Native.None -> encode_freev ()
           | FStar_Pervasives_Native.Some t2 -> encode_term t2 env)
        else encode_freev ()
    | FStarC_Syntax_Syntax.Tm_uinst
        ({ FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar v;
           FStarC_Syntax_Syntax.pos = uu___2;
           FStarC_Syntax_Syntax.vars = uu___3;
           FStarC_Syntax_Syntax.hash_code = uu___4;_},
         uu___5)
        ->
        let us =
          match t1.FStarC_Syntax_Syntax.n with
          | FStarC_Syntax_Syntax.Tm_fvar uu___6 -> []
          | FStarC_Syntax_Syntax.Tm_uinst (uu___6, us1) -> us1 in
        let encode_freev uu___6 =
          let us1 = FStarC_List.map encode_universe us in
          let fvb =
            FStarC_SMTEncoding_Env.lookup_free_var_name env
              v.FStarC_Syntax_Syntax.fv_name in
          let tok =
            FStarC_SMTEncoding_Env.lookup_free_var env
              v.FStarC_Syntax_Syntax.fv_name in
          let uu___7 =
            match ((tok.FStarC_SMTEncoding_Term.tm), us1) with
            | (FStarC_SMTEncoding_Term.FreeV uu___8, uu___9::uu___10) ->
                failwith
                  "Impossible: Universe applications on nullary symbol"
            | (FStarC_SMTEncoding_Term.App
               (FStarC_SMTEncoding_Term.Var "ApplyTF",
                {
                  FStarC_SMTEncoding_Term.tm = FStarC_SMTEncoding_Term.FreeV
                    (FStarC_SMTEncoding_Term.FV (tok1, uu___8, uu___9));
                  FStarC_SMTEncoding_Term.freevars = uu___10;
                  FStarC_SMTEncoding_Term.rng = uu___11;_}::fuel::[]),
               us2) ->
                let uu___12 =
                  let uu___13 =
                    let uu___14 =
                      let uu___15 = FStarC_SMTEncoding_Util.mkApp (tok1, us2) in
                      [uu___15; fuel] in
                    ("ApplyTF", uu___14) in
                  FStarC_SMTEncoding_Util.mkApp uu___13 in
                (true, uu___12)
            | (FStarC_SMTEncoding_Term.App
               (FStarC_SMTEncoding_Term.Var "ApplyTF",
                {
                  FStarC_SMTEncoding_Term.tm = FStarC_SMTEncoding_Term.App
                    (FStarC_SMTEncoding_Term.Var tok1, []);
                  FStarC_SMTEncoding_Term.freevars = uu___8;
                  FStarC_SMTEncoding_Term.rng = uu___9;_}::fuel::[]),
               us2) ->
                let uu___10 =
                  let uu___11 =
                    let uu___12 =
                      let uu___13 = FStarC_SMTEncoding_Util.mkApp (tok1, us2) in
                      [uu___13; fuel] in
                    ("ApplyTF", uu___12) in
                  FStarC_SMTEncoding_Util.mkApp uu___11 in
                (true, uu___10)
            | (FStarC_SMTEncoding_Term.App (op, uu___8::uu___9),
               uu___10::uu___11) ->
                let uu___12 =
                  let uu___13 =
                    FStarC_Class_Show.show
                      FStarC_SMTEncoding_Term.showable_smt_term tok in
                  FStarC_Format.fmt1
                    "Impossible: Universe applications cannot be curried: head is %s"
                    uu___13 in
                failwith uu___12
            | (FStarC_SMTEncoding_Term.FreeV uu___8, []) -> (true, tok)
            | (FStarC_SMTEncoding_Term.App (op, []), us2) ->
                (true,
                  {
                    FStarC_SMTEncoding_Term.tm =
                      (FStarC_SMTEncoding_Term.App (op, us2));
                    FStarC_SMTEncoding_Term.freevars =
                      (tok.FStarC_SMTEncoding_Term.freevars);
                    FStarC_SMTEncoding_Term.rng =
                      (tok.FStarC_SMTEncoding_Term.rng)
                  })
            | (FStarC_SMTEncoding_Term.App (op, ts), []) -> (false, tok) in
          match uu___7 with
          | (is_nullary, tok1) ->
              let tkey_hash = FStarC_SMTEncoding_Term.hash_of_term tok1 in
              let uu___8 =
                if
                  (fvb.FStarC_SMTEncoding_Env.smt_arity > Prims.int_zero) &&
                    is_nullary
                then
                  let uu___9 = FStarC_SMTEncoding_Env.kick_partial_app fvb in
                  match uu___9 with
                  | FStar_Pervasives_Native.None -> ([], "")
                  | FStar_Pervasives_Native.Some kpa ->
                      let sym_name =
                        let uu___10 = FStarC_Util.digest_of_string tkey_hash in
                        Prims.strcat "@kick_partial_app_" uu___10 in
                      let uu___10 =
                        let uu___11 =
                          FStarC_SMTEncoding_Util.mkAssume
                            (kpa,
                              (FStar_Pervasives_Native.Some
                                 "kick_partial_app"), sym_name) in
                        [uu___11] in
                      (uu___10, sym_name)
                else ([], "") in
              (match uu___8 with
               | (aux_decls, sym_name) ->
                   let uu___9 =
                     if aux_decls = []
                     then FStarC_SMTEncoding_Term.mk_decls_trivial []
                     else
                       FStarC_SMTEncoding_Term.mk_decls sym_name tkey_hash
                         aux_decls [] in
                   (tok1, uu___9)) in
        let uu___6 = head_redex env t1 in
        if uu___6
        then
          let uu___7 = maybe_whnf env t1 in
          (match uu___7 with
           | FStar_Pervasives_Native.None -> encode_freev ()
           | FStar_Pervasives_Native.Some t2 -> encode_term t2 env)
        else encode_freev ()
    | FStarC_Syntax_Syntax.Tm_constant c -> encode_const c env
    | FStarC_Syntax_Syntax.Tm_arrow
        { FStarC_Syntax_Syntax.bs1 = binders;
          FStarC_Syntax_Syntax.comp = c;_}
        ->
        let module_name = env.FStarC_SMTEncoding_Env.current_module_name in
        let uu___2 = FStarC_Syntax_Subst.open_comp binders c in
        (match uu___2 with
         | (binders1, res) ->
             let uu___3 =
               (env.FStarC_SMTEncoding_Env.encode_non_total_function_typ &&
                  (FStarC_Syntax_Util.is_pure_or_ghost_comp res))
                 || (FStarC_Syntax_Util.is_tot_or_gtot_comp res) in
             if uu___3
             then
               let t0_univ =
                 (env.FStarC_SMTEncoding_Env.tcenv).FStarC_TypeChecker_Env.universe_of
                   env.FStarC_SMTEncoding_Env.tcenv t0 in
               let uu___4 =
                 encode_binders FStar_Pervasives_Native.None binders1 env in
               (match uu___4 with
                | (vars, guards_l, env', decls, bvs) ->
                    let fsym =
                      let uu___5 =
                        let uu___6 =
                          FStarC_SMTEncoding_Env.varops.FStarC_SMTEncoding_Env.fresh
                            module_name "f" in
                        (uu___6, FStarC_SMTEncoding_Term.Term_sort) in
                      FStarC_SMTEncoding_Term.mk_fv uu___5 in
                    let f = FStarC_SMTEncoding_Util.mkFreeV fsym in
                    let app = mk_Apply f vars in
                    let tcenv_bs =
                      let uu___5 = env'.FStarC_SMTEncoding_Env.tcenv in
                      {
                        FStarC_TypeChecker_Env.solver =
                          (uu___5.FStarC_TypeChecker_Env.solver);
                        FStarC_TypeChecker_Env.range =
                          (uu___5.FStarC_TypeChecker_Env.range);
                        FStarC_TypeChecker_Env.curmodule =
                          (uu___5.FStarC_TypeChecker_Env.curmodule);
                        FStarC_TypeChecker_Env.gamma =
                          (uu___5.FStarC_TypeChecker_Env.gamma);
                        FStarC_TypeChecker_Env.gamma_sig =
                          (uu___5.FStarC_TypeChecker_Env.gamma_sig);
                        FStarC_TypeChecker_Env.gamma_cache =
                          (uu___5.FStarC_TypeChecker_Env.gamma_cache);
                        FStarC_TypeChecker_Env.modules =
                          (uu___5.FStarC_TypeChecker_Env.modules);
                        FStarC_TypeChecker_Env.expected_typ =
                          (uu___5.FStarC_TypeChecker_Env.expected_typ);
                        FStarC_TypeChecker_Env.sigtab =
                          (uu___5.FStarC_TypeChecker_Env.sigtab);
                        FStarC_TypeChecker_Env.attrtab =
                          (uu___5.FStarC_TypeChecker_Env.attrtab);
                        FStarC_TypeChecker_Env.instantiate_imp =
                          (uu___5.FStarC_TypeChecker_Env.instantiate_imp);
                        FStarC_TypeChecker_Env.effects =
                          (uu___5.FStarC_TypeChecker_Env.effects);
                        FStarC_TypeChecker_Env.generalize =
                          (uu___5.FStarC_TypeChecker_Env.generalize);
                        FStarC_TypeChecker_Env.letrecs =
                          (uu___5.FStarC_TypeChecker_Env.letrecs);
                        FStarC_TypeChecker_Env.top_level =
                          (uu___5.FStarC_TypeChecker_Env.top_level);
                        FStarC_TypeChecker_Env.check_uvars =
                          (uu___5.FStarC_TypeChecker_Env.check_uvars);
                        FStarC_TypeChecker_Env.use_eq_strict =
                          (uu___5.FStarC_TypeChecker_Env.use_eq_strict);
                        FStarC_TypeChecker_Env.is_iface =
                          (uu___5.FStarC_TypeChecker_Env.is_iface);
                        FStarC_TypeChecker_Env.admit = true;
                        FStarC_TypeChecker_Env.phase1 =
                          (uu___5.FStarC_TypeChecker_Env.phase1);
                        FStarC_TypeChecker_Env.failhard =
                          (uu___5.FStarC_TypeChecker_Env.failhard);
                        FStarC_TypeChecker_Env.flychecking =
                          (uu___5.FStarC_TypeChecker_Env.flychecking);
                        FStarC_TypeChecker_Env.uvar_subtyping =
                          (uu___5.FStarC_TypeChecker_Env.uvar_subtyping);
                        FStarC_TypeChecker_Env.intactics =
                          (uu___5.FStarC_TypeChecker_Env.intactics);
                        FStarC_TypeChecker_Env.nocoerce =
                          (uu___5.FStarC_TypeChecker_Env.nocoerce);
                        FStarC_TypeChecker_Env.tc_term =
                          (uu___5.FStarC_TypeChecker_Env.tc_term);
                        FStarC_TypeChecker_Env.typeof_tot_or_gtot_term =
                          (uu___5.FStarC_TypeChecker_Env.typeof_tot_or_gtot_term);
                        FStarC_TypeChecker_Env.universe_of =
                          (uu___5.FStarC_TypeChecker_Env.universe_of);
                        FStarC_TypeChecker_Env.typeof_well_typed_tot_or_gtot_term
                          =
                          (uu___5.FStarC_TypeChecker_Env.typeof_well_typed_tot_or_gtot_term);
                        FStarC_TypeChecker_Env.teq_nosmt_force =
                          (uu___5.FStarC_TypeChecker_Env.teq_nosmt_force);
                        FStarC_TypeChecker_Env.subtype_nosmt_force =
                          (uu___5.FStarC_TypeChecker_Env.subtype_nosmt_force);
                        FStarC_TypeChecker_Env.qtbl_name_and_index =
                          (uu___5.FStarC_TypeChecker_Env.qtbl_name_and_index);
                        FStarC_TypeChecker_Env.normalized_eff_names =
                          (uu___5.FStarC_TypeChecker_Env.normalized_eff_names);
                        FStarC_TypeChecker_Env.fv_delta_depths =
                          (uu___5.FStarC_TypeChecker_Env.fv_delta_depths);
                        FStarC_TypeChecker_Env.proof_ns =
                          (uu___5.FStarC_TypeChecker_Env.proof_ns);
                        FStarC_TypeChecker_Env.synth_hook =
                          (uu___5.FStarC_TypeChecker_Env.synth_hook);
                        FStarC_TypeChecker_Env.try_solve_implicits_hook =
                          (uu___5.FStarC_TypeChecker_Env.try_solve_implicits_hook);
                        FStarC_TypeChecker_Env.splice =
                          (uu___5.FStarC_TypeChecker_Env.splice);
                        FStarC_TypeChecker_Env.mpreprocess =
                          (uu___5.FStarC_TypeChecker_Env.mpreprocess);
                        FStarC_TypeChecker_Env.postprocess =
                          (uu___5.FStarC_TypeChecker_Env.postprocess);
                        FStarC_TypeChecker_Env.identifier_info =
                          (uu___5.FStarC_TypeChecker_Env.identifier_info);
                        FStarC_TypeChecker_Env.tc_hooks =
                          (uu___5.FStarC_TypeChecker_Env.tc_hooks);
                        FStarC_TypeChecker_Env.dsenv =
                          (uu___5.FStarC_TypeChecker_Env.dsenv);
                        FStarC_TypeChecker_Env.nbe =
                          (uu___5.FStarC_TypeChecker_Env.nbe);
                        FStarC_TypeChecker_Env.strict_args_tab =
                          (uu___5.FStarC_TypeChecker_Env.strict_args_tab);
                        FStarC_TypeChecker_Env.erasable_types_tab =
                          (uu___5.FStarC_TypeChecker_Env.erasable_types_tab);
                        FStarC_TypeChecker_Env.enable_defer_to_tac =
                          (uu___5.FStarC_TypeChecker_Env.enable_defer_to_tac);
                        FStarC_TypeChecker_Env.unif_allow_ref_guards =
                          (uu___5.FStarC_TypeChecker_Env.unif_allow_ref_guards);
                        FStarC_TypeChecker_Env.erase_erasable_args =
                          (uu___5.FStarC_TypeChecker_Env.erase_erasable_args);
                        FStarC_TypeChecker_Env.core_check =
                          (uu___5.FStarC_TypeChecker_Env.core_check);
                        FStarC_TypeChecker_Env.missing_decl =
                          (uu___5.FStarC_TypeChecker_Env.missing_decl)
                      } in
                    let uu___5 =
                      FStarC_TypeChecker_Util.pure_or_ghost_pre_and_post
                        tcenv_bs res in
                    (match uu___5 with
                     | (pre_opt, res_t) ->
                         let uu___6 =
                           encode_term_pred FStar_Pervasives_Native.None
                             res_t env' app in
                         (match uu___6 with
                          | (res_pred, decls') ->
                              let uu___7 =
                                match pre_opt with
                                | FStar_Pervasives_Native.None ->
                                    let uu___8 =
                                      FStarC_SMTEncoding_Util.mk_and_l
                                        guards_l in
                                    (uu___8, [])
                                | FStar_Pervasives_Native.Some pre ->
                                    let uu___8 = encode_formula pre env' in
                                    (match uu___8 with
                                     | (guard, decls0) ->
                                         let uu___9 =
                                           FStarC_SMTEncoding_Util.mk_and_l
                                             (guard :: guards_l) in
                                         (uu___9, decls0)) in
                              (match uu___7 with
                               | (guards, guard_decls) ->
                                   let is_pure =
                                     let uu___8 =
                                       FStarC_TypeChecker_Normalize.maybe_ghost_to_pure
                                         env.FStarC_SMTEncoding_Env.tcenv res in
                                     FStarC_Syntax_Util.is_pure_comp uu___8 in
                                   let t_interp =
                                     let uu___8 =
                                       let uu___9 =
                                         FStarC_SMTEncoding_Util.mkImp
                                           (guards, res_pred) in
                                       ([[app]], vars, uu___9) in
                                     FStarC_SMTEncoding_Term.mkForall
                                       t1.FStarC_Syntax_Syntax.pos uu___8 in
                                   let t_interp1 =
                                     let tot_fun_axioms =
                                       isTotFun_axioms
                                         t1.FStarC_Syntax_Syntax.pos f []
                                         vars guards_l is_pure in
                                     FStarC_SMTEncoding_Util.mkAnd
                                       (t_interp, tot_fun_axioms) in
                                   let tkey_body =
                                     let rec add_bv_sorts bvs1 acc =
                                       match bvs1 with
                                       | bv::bvs2 ->
                                           let uu___8 =
                                             let uu___9 =
                                               let uu___10 =
                                                 let uu___11 =
                                                   let uu___12 =
                                                     (env'.FStarC_SMTEncoding_Env.tcenv).FStarC_TypeChecker_Env.universe_of
                                                       env'.FStarC_SMTEncoding_Env.tcenv
                                                       bv.FStarC_Syntax_Syntax.sort in
                                                   encode_universe uu___12 in
                                                 FStarC_SMTEncoding_Term.mk_Term_type
                                                   uu___11 in
                                               (acc, uu___10) in
                                             FStarC_SMTEncoding_Util.mkAnd
                                               uu___9 in
                                           add_bv_sorts bvs2 uu___8
                                       | uu___8 -> acc in
                                     let tkey_body1 = t_interp1 in
                                     let tkey_body2 =
                                       add_bv_sorts bvs t_interp1 in
                                     let tkey_body3 =
                                       let uu___8 =
                                         let uu___9 =
                                           let uu___10 =
                                             encode_universe t0_univ in
                                           FStarC_SMTEncoding_Term.mk_Term_type
                                             uu___10 in
                                         (tkey_body2, uu___9) in
                                       FStarC_SMTEncoding_Util.mkAnd uu___8 in
                                     tkey_body3 in
                                   let cvars =
                                     let cvars1 =
                                       let uu___8 =
                                         FStarC_SMTEncoding_Term.free_variables
                                           tkey_body in
                                       FStarC_List.filter
                                         (fun x ->
                                            let uu___9 =
                                              FStarC_SMTEncoding_Term.fv_name
                                                x in
                                            let uu___10 =
                                              FStarC_SMTEncoding_Term.fv_name
                                                fsym in
                                            uu___9 <> uu___10) uu___8 in
                                     FStarC_Util.remove_dups
                                       FStarC_SMTEncoding_Term.fv_eq cvars1 in
                                   let tkey =
                                     FStarC_SMTEncoding_Term.mkForall
                                       t1.FStarC_Syntax_Syntax.pos
                                       ([], (fsym :: cvars), t_interp1) in
                                   let prefix =
                                     if is_pure
                                     then "Tm_arrow_"
                                     else "Tm_ghost_arrow_" in
                                   let tkey_hash =
                                     let uu___8 =
                                       FStarC_SMTEncoding_Term.hash_of_term
                                         tkey in
                                     Prims.strcat prefix uu___8 in
                                   let tsym =
                                     let uu___8 =
                                       FStarC_Util.digest_of_string tkey_hash in
                                     Prims.strcat prefix uu___8 in
                                   let cvar_sorts =
                                     FStarC_List.map
                                       FStarC_SMTEncoding_Term.fv_sort cvars in
                                   let caption =
                                     let uu___8 =
                                       FStarC_Options.log_queries () in
                                     if uu___8
                                     then
                                       let uu___9 =
                                         let uu___10 =
                                           FStarC_TypeChecker_Normalize.term_to_string
                                             env.FStarC_SMTEncoding_Env.tcenv
                                             t0 in
                                         FStarC_Util.replace_char uu___10 10
                                           32 in
                                       FStar_Pervasives_Native.Some uu___9
                                     else FStar_Pervasives_Native.None in
                                   let tdecl =
                                     FStarC_SMTEncoding_Term.DeclFun
                                       (tsym, cvar_sorts,
                                         FStarC_SMTEncoding_Term.Term_sort,
                                         caption) in
                                   let t2 =
                                     let uu___8 =
                                       let uu___9 =
                                         FStarC_List.map
                                           FStarC_SMTEncoding_Util.mkFreeV
                                           cvars in
                                       (tsym, uu___9) in
                                     FStarC_SMTEncoding_Util.mkApp uu___8 in
                                   let t_has_kind =
                                     let u = encode_universe t0_univ in
                                     let uu___8 =
                                       FStarC_SMTEncoding_Term.mk_Term_type u in
                                     FStarC_SMTEncoding_Term.mk_HasType t2
                                       uu___8 in
                                   let k_assumption =
                                     let a_name =
                                       Prims.strcat "kinding_" tsym in
                                     let uu___8 =
                                       let uu___9 =
                                         FStarC_SMTEncoding_Term.mkForall
                                           t0.FStarC_Syntax_Syntax.pos
                                           ([[t_has_kind]], cvars,
                                             t_has_kind) in
                                       (uu___9,
                                         (FStar_Pervasives_Native.Some a_name),
                                         a_name) in
                                     FStarC_SMTEncoding_Util.mkAssume uu___8 in
                                   let f_has_t =
                                     FStarC_SMTEncoding_Term.mk_HasType f t2 in
                                   let f_has_t_z =
                                     FStarC_SMTEncoding_Term.mk_HasTypeZ f t2 in
                                   let pre_typing =
                                     let a_name =
                                       Prims.strcat "pre_typing_" tsym in
                                     let uu___8 =
                                       let uu___9 =
                                         let uu___10 =
                                           let uu___11 =
                                             let uu___12 =
                                               let uu___13 =
                                                 let uu___14 =
                                                   FStarC_SMTEncoding_Term.mk_PreType
                                                     f in
                                                 FStarC_SMTEncoding_Term.mk_tester
                                                   "Tm_arrow" uu___14 in
                                               (f_has_t, uu___13) in
                                             FStarC_SMTEncoding_Util.mkImp
                                               uu___12 in
                                           ([[f_has_t]], (fsym :: cvars),
                                             uu___11) in
                                         let uu___11 =
                                           mkForall_fuel module_name
                                             t0.FStarC_Syntax_Syntax.pos in
                                         uu___11 uu___10 in
                                       (uu___9,
                                         (FStar_Pervasives_Native.Some
                                            "pre-typing for functions"),
                                         (Prims.strcat module_name
                                            (Prims.strcat "_" a_name))) in
                                     FStarC_SMTEncoding_Util.mkAssume uu___8 in
                                   let t_interp2 =
                                     let a_name =
                                       Prims.strcat "interpretation_" tsym in
                                     let uu___8 =
                                       let uu___9 =
                                         let uu___10 =
                                           let uu___11 =
                                             FStarC_SMTEncoding_Util.mkIff
                                               (f_has_t_z, t_interp1) in
                                           ([[f_has_t_z]], (fsym :: cvars),
                                             uu___11) in
                                         FStarC_SMTEncoding_Term.mkForall
                                           t0.FStarC_Syntax_Syntax.pos
                                           uu___10 in
                                       (uu___9,
                                         (FStar_Pervasives_Native.Some a_name),
                                         (Prims.strcat module_name
                                            (Prims.strcat "_" a_name))) in
                                     FStarC_SMTEncoding_Util.mkAssume uu___8 in
                                   let t_decls =
                                     [tdecl;
                                     k_assumption;
                                     pre_typing;
                                     t_interp2] in
                                   let uu___8 =
                                     let uu___9 =
                                       let uu___10 =
                                         let uu___11 =
                                           FStarC_SMTEncoding_Term.mk_decls
                                             tsym tkey_hash t_decls
                                             (FStarC_List.op_At decls
                                                (FStarC_List.op_At decls'
                                                   guard_decls)) in
                                         FStarC_List.op_At guard_decls
                                           uu___11 in
                                       FStarC_List.op_At decls' uu___10 in
                                     FStarC_List.op_At decls uu___9 in
                                   (t2, uu___8)))))
             else
               (let tkey_hash =
                  let uu___5 =
                    encode_binders FStar_Pervasives_Native.None binders1 env in
                  match uu___5 with
                  | (vars, guards_l, env_bs, uu___6, uu___7) ->
                      let c1 =
                        let uu___8 =
                          let uu___9 =
                            FStarC_TypeChecker_Env.push_binders
                              env.FStarC_SMTEncoding_Env.tcenv binders1 in
                          FStarC_TypeChecker_Env.unfold_effect_abbrev uu___9
                            res in
                        FStarC_Syntax_Syntax.mk_Comp uu___8 in
                      let uu___8 =
                        let uu___9 = FStarC_Syntax_Util.comp_result c1 in
                        encode_term uu___9 env_bs in
                      (match uu___8 with
                       | (ct, uu___9) ->
                           let uu___10 =
                             let uu___11 =
                               FStarC_Syntax_Util.comp_effect_args c1 in
                             encode_args uu___11 env_bs in
                           (match uu___10 with
                            | (effect_args, uu___11) ->
                                let tkey =
                                  let uu___12 =
                                    let uu___13 =
                                      FStarC_SMTEncoding_Util.mk_and_l
                                        (FStarC_List.op_At guards_l
                                           (FStarC_List.op_At [ct]
                                              effect_args)) in
                                    ([], vars, uu___13) in
                                  FStarC_SMTEncoding_Term.mkForall
                                    t1.FStarC_Syntax_Syntax.pos uu___12 in
                                let tkey_hash1 =
                                  let uu___12 =
                                    let uu___13 =
                                      FStarC_SMTEncoding_Term.hash_of_term
                                        tkey in
                                    let uu___14 =
                                      let uu___15 =
                                        let uu___16 =
                                          FStarC_Syntax_Util.comp_effect_name
                                            c1 in
                                        FStarC_Ident.string_of_lid uu___16 in
                                      Prims.strcat "@Effect=" uu___15 in
                                    Prims.strcat uu___13 uu___14 in
                                  Prims.strcat "Non_total_Tm_arrow" uu___12 in
                                FStarC_Util.digest_of_string tkey_hash1)) in
                let tsym = Prims.strcat "Non_total_Tm_arrow_" tkey_hash in
                let env0 = env in
                let uu___5 =
                  let fvs =
                    let uu___6 = FStarC_Syntax_Free.names t0 in
                    FStarC_Class_Setlike.elems ()
                      (Obj.magic
                         (FStarC_FlatSet.setlike_flat_set
                            FStarC_Syntax_Syntax.ord_bv)) (Obj.magic uu___6) in
                  let getfreeV t2 =
                    match t2.FStarC_SMTEncoding_Term.tm with
                    | FStarC_SMTEncoding_Term.FreeV fv -> fv
                    | uu___6 ->
                        failwith
                          "Impossible: getfreeV: gen_term_var should always returns a FreeV" in
                  let uu___6 =
                    FStarC_List.fold_left
                      (fun uu___7 bv ->
                         match uu___7 with
                         | (env1, decls, vars, tms, guards) ->
                             let uu___8 =
                               FStarC_TypeChecker_Env.lookup_bv
                                 env1.FStarC_SMTEncoding_Env.tcenv bv in
                             (match uu___8 with
                              | (sort, uu___9) ->
                                  let uu___10 =
                                    FStarC_SMTEncoding_Env.gen_term_var env1
                                      bv in
                                  (match uu___10 with
                                   | (sym, smt_tm, env2) ->
                                       let fv = getfreeV smt_tm in
                                       let uu___11 =
                                         let uu___12 = norm env2 sort in
                                         encode_term_pred
                                           FStar_Pervasives_Native.None
                                           uu___12 env2 smt_tm in
                                       (match uu___11 with
                                        | (guard, decls') ->
                                            (env2,
                                              (FStarC_List.op_At decls' decls),
                                              (fv :: vars), (smt_tm :: tms),
                                              (guard :: guards))))))
                      (env, [], [], [], []) fvs in
                  (fvs, uu___6) in
                match uu___5 with
                | (fstar_fvs, (env1, fv_decls, fv_vars, fv_tms, fv_guards))
                    ->
                    let fv_decls1 = FStarC_List.rev fv_decls in
                    let fv_vars1 = FStarC_List.rev fv_vars in
                    let fv_tms1 = FStarC_List.rev fv_tms in
                    let fv_guards1 = FStarC_List.rev fv_guards in
                    let arg_sorts =
                      FStarC_List.map
                        (fun uu___6 -> FStarC_SMTEncoding_Term.Term_sort)
                        fv_tms1 in
                    let tdecl =
                      FStarC_SMTEncoding_Term.DeclFun
                        (tsym, arg_sorts, FStarC_SMTEncoding_Term.Term_sort,
                          FStar_Pervasives_Native.None) in
                    let tapp = FStarC_SMTEncoding_Util.mkApp (tsym, fv_tms1) in
                    let t_kinding =
                      let a_name =
                        Prims.strcat "non_total_function_typing_" tsym in
                      let axiom =
                        let uu___6 =
                          let uu___7 =
                            let uu___8 =
                              let uu___9 =
                                let uu___10 =
                                  FStarC_SMTEncoding_Term.mk_Term_type
                                    FStarC_SMTEncoding_Term.mk_U_unknown in
                                FStarC_SMTEncoding_Term.mk_HasType tapp
                                  uu___10 in
                              [uu___9] in
                            [uu___8] in
                          let uu___8 =
                            let uu___9 =
                              let uu___10 =
                                FStarC_SMTEncoding_Util.mk_and_l fv_guards1 in
                              let uu___11 =
                                let uu___12 =
                                  FStarC_SMTEncoding_Term.mk_Term_type
                                    FStarC_SMTEncoding_Term.mk_U_unknown in
                                FStarC_SMTEncoding_Term.mk_HasType tapp
                                  uu___12 in
                              (uu___10, uu___11) in
                            FStarC_SMTEncoding_Util.mkImp uu___9 in
                          (uu___7, fv_vars1, uu___8) in
                        FStarC_SMTEncoding_Term.mkForall
                          t0.FStarC_Syntax_Syntax.pos uu___6 in
                      let svars =
                        FStarC_SMTEncoding_Term.free_variables axiom in
                      let axiom1 =
                        FStarC_SMTEncoding_Term.mkForall
                          t0.FStarC_Syntax_Syntax.pos ([], svars, axiom) in
                      FStarC_SMTEncoding_Util.mkAssume
                        (axiom1,
                          (FStar_Pervasives_Native.Some
                             "Typing for non-total arrows"), a_name) in
                    let tapp_concrete =
                      let uu___6 =
                        let uu___7 =
                          FStarC_List.map
                            (FStarC_SMTEncoding_Env.lookup_term_var env0)
                            fstar_fvs in
                        (tsym, uu___7) in
                      FStarC_SMTEncoding_Util.mkApp uu___6 in
                    let uu___6 =
                      let uu___7 =
                        FStarC_SMTEncoding_Term.mk_decls tsym tkey_hash
                          [tdecl; t_kinding] [] in
                      FStarC_List.op_At fv_decls1 uu___7 in
                    (tapp_concrete, uu___6)))
    | FStarC_Syntax_Syntax.Tm_refine uu___2 ->
        let uu___3 =
          let steps =
            [FStarC_TypeChecker_Env.Weak; FStarC_TypeChecker_Env.HNF] in
          let uu___4 =
            normalize_refinement steps env.FStarC_SMTEncoding_Env.tcenv t0 in
          match uu___4 with
          | {
              FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_refine
                { FStarC_Syntax_Syntax.b = x; FStarC_Syntax_Syntax.phi = f;_};
              FStarC_Syntax_Syntax.pos = uu___5;
              FStarC_Syntax_Syntax.vars = uu___6;
              FStarC_Syntax_Syntax.hash_code = uu___7;_} ->
              let uu___8 =
                let uu___9 =
                  let uu___10 = FStarC_Syntax_Syntax.mk_binder x in [uu___10] in
                FStarC_Syntax_Subst.open_term uu___9 f in
              (match uu___8 with
               | (b, f1) ->
                   let uu___9 =
                     let uu___10 = FStarC_List.hd b in
                     uu___10.FStarC_Syntax_Syntax.binder_bv in
                   let uu___10 =
                     (env.FStarC_SMTEncoding_Env.tcenv).FStarC_TypeChecker_Env.universe_of
                       env.FStarC_SMTEncoding_Env.tcenv t0 in
                   (uu___9, f1, uu___10))
          | uu___5 -> failwith "impossible" in
        (match uu___3 with
         | (x, f, t0_univ) ->
             let uu___4 = encode_term x.FStarC_Syntax_Syntax.sort env in
             (match uu___4 with
              | (base_t, decls) ->
                  let uu___5 = FStarC_SMTEncoding_Env.gen_term_var env x in
                  (match uu___5 with
                   | (x1, xtm, env') ->
                       let uu___6 = encode_formula f env' in
                       (match uu___6 with
                        | (refinement, decls') ->
                            let universe = encode_universe t0_univ in
                            let uu___7 =
                              FStarC_SMTEncoding_Env.fresh_fvar
                                env.FStarC_SMTEncoding_Env.current_module_name
                                "f" FStarC_SMTEncoding_Term.Fuel_sort in
                            (match uu___7 with
                             | (fsym, fterm) ->
                                 let tm_has_type_with_fuel =
                                   FStarC_SMTEncoding_Term.mk_HasTypeWithFuel
                                     (FStar_Pervasives_Native.Some fterm) xtm
                                     base_t in
                                 let encoding =
                                   FStarC_SMTEncoding_Util.mkAnd
                                     (tm_has_type_with_fuel, refinement) in
                                 let cvars =
                                   let uu___8 =
                                     let uu___9 =
                                       FStarC_SMTEncoding_Term.free_variables
                                         refinement in
                                     let uu___10 =
                                       FStarC_SMTEncoding_Term.free_variables
                                         tm_has_type_with_fuel in
                                     FStarC_List.op_At uu___9 uu___10 in
                                   FStarC_Util.remove_dups
                                     FStarC_SMTEncoding_Term.fv_eq uu___8 in
                                 let cvars1 =
                                   FStarC_List.filter
                                     (fun y ->
                                        (let uu___8 =
                                           FStarC_SMTEncoding_Term.fv_name y in
                                         uu___8 <> x1) &&
                                          (let uu___8 =
                                             FStarC_SMTEncoding_Term.fv_name
                                               y in
                                           uu___8 <> fsym)) cvars in
                                 let cvars2 =
                                   let univ_vars =
                                     let uu___8 =
                                       let uu___9 =
                                         let uu___10 =
                                           FStarC_Syntax_Free.univnames t1 in
                                         let uu___11 =
                                           let uu___12 =
                                             FStarC_Syntax_Util.type_with_u
                                               t0_univ in
                                           FStarC_Syntax_Free.univnames
                                             uu___12 in
                                         Obj.magic
                                           (FStarC_Class_Setlike.union ()
                                              (Obj.magic
                                                 (FStarC_FlatSet.setlike_flat_set
                                                    FStarC_Syntax_Syntax.ord_ident))
                                              (Obj.magic uu___10)
                                              (Obj.magic uu___11)) in
                                       FStarC_Class_Setlike.elems ()
                                         (Obj.magic
                                            (FStarC_FlatSet.setlike_flat_set
                                               FStarC_Syntax_Syntax.ord_ident))
                                         (Obj.magic uu___9) in
                                     FStarC_List.map encode_univ_name uu___8 in
                                   let cvars3 =
                                     let uu___8 =
                                       FStarC_List.map
                                         FStar_Pervasives_Native.fst
                                         univ_vars in
                                     FStarC_List.op_At uu___8 cvars1 in
                                   FStarC_Util.remove_dups
                                     FStarC_SMTEncoding_Term.fv_eq cvars3 in
                                 let xfv =
                                   FStarC_SMTEncoding_Term.mk_fv
                                     (x1, FStarC_SMTEncoding_Term.Term_sort) in
                                 let ffv =
                                   FStarC_SMTEncoding_Term.mk_fv
                                     (fsym,
                                       FStarC_SMTEncoding_Term.Fuel_sort) in
                                 let tkey =
                                   FStarC_SMTEncoding_Term.mkForall
                                     t0.FStarC_Syntax_Syntax.pos
                                     ([], (ffv :: xfv :: cvars2), encoding) in
                                 let tkey_hash =
                                   FStarC_SMTEncoding_Term.hash_of_term tkey in
                                 ((let uu___9 =
                                     FStarC_Effect.op_Bang dbg_SMTEncoding in
                                   if uu___9
                                   then
                                     let uu___10 =
                                       FStarC_Class_Show.show
                                         FStarC_Syntax_Print.showable_term f in
                                     let uu___11 =
                                       FStarC_Util.digest_of_string tkey_hash in
                                     FStarC_Format.print3
                                       "Encoding Tm_refine %s with tkey_hash %s and digest %s\n"
                                       uu___10 tkey_hash uu___11
                                   else ());
                                  (let tsym =
                                     let uu___9 =
                                       FStarC_Util.digest_of_string tkey_hash in
                                     Prims.strcat "Tm_refine_" uu___9 in
                                   let cvar_sorts =
                                     FStarC_List.map
                                       FStarC_SMTEncoding_Term.fv_sort cvars2 in
                                   let tdecl =
                                     FStarC_SMTEncoding_Term.DeclFun
                                       (tsym, cvar_sorts,
                                         FStarC_SMTEncoding_Term.Term_sort,
                                         FStar_Pervasives_Native.None) in
                                   let t2 =
                                     let uu___9 =
                                       let uu___10 =
                                         FStarC_List.map
                                           FStarC_SMTEncoding_Util.mkFreeV
                                           cvars2 in
                                       (tsym, uu___10) in
                                     FStarC_SMTEncoding_Util.mkApp uu___9 in
                                   let x_has_base_t =
                                     FStarC_SMTEncoding_Term.mk_HasType xtm
                                       base_t in
                                   let x_has_t =
                                     FStarC_SMTEncoding_Term.mk_HasTypeWithFuel
                                       (FStar_Pervasives_Native.Some fterm)
                                       xtm t2 in
                                   let t_has_kind =
                                     let uu___9 =
                                       FStarC_SMTEncoding_Term.mk_Term_type
                                         universe in
                                     FStarC_SMTEncoding_Term.mk_HasType t2
                                       uu___9 in
                                   let t_haseq_base =
                                     FStarC_SMTEncoding_Term.mk_haseq
                                       universe base_t in
                                   let t_haseq_ref =
                                     FStarC_SMTEncoding_Term.mk_haseq
                                       universe t2 in
                                   let t_haseq =
                                     let uu___9 =
                                       let uu___10 =
                                         let uu___11 =
                                           let uu___12 =
                                             FStarC_SMTEncoding_Util.mkIff
                                               (t_haseq_ref, t_haseq_base) in
                                           ([[t_haseq_ref]], cvars2, uu___12) in
                                         FStarC_SMTEncoding_Term.mkForall
                                           t0.FStarC_Syntax_Syntax.pos
                                           uu___11 in
                                       (uu___10,
                                         (FStar_Pervasives_Native.Some
                                            (Prims.strcat "haseq for " tsym)),
                                         (Prims.strcat "haseq" tsym)) in
                                     FStarC_SMTEncoding_Util.mkAssume uu___9 in
                                   let t_kinding =
                                     let uu___9 =
                                       let uu___10 =
                                         FStarC_SMTEncoding_Term.mkForall
                                           t0.FStarC_Syntax_Syntax.pos
                                           ([[t_has_kind]], cvars2,
                                             t_has_kind) in
                                       (uu___10,
                                         (FStar_Pervasives_Native.Some
                                            "refinement kinding"),
                                         (Prims.strcat "refinement_kinding_"
                                            tsym)) in
                                     FStarC_SMTEncoding_Util.mkAssume uu___9 in
                                   let t_interp =
                                     let uu___9 =
                                       let uu___10 =
                                         let uu___11 =
                                           let uu___12 =
                                             FStarC_SMTEncoding_Util.mkIff
                                               (x_has_t, encoding) in
                                           ([[x_has_t]], (ffv :: xfv ::
                                             cvars2), uu___12) in
                                         FStarC_SMTEncoding_Term.mkForall
                                           t0.FStarC_Syntax_Syntax.pos
                                           uu___11 in
                                       (uu___10,
                                         (FStar_Pervasives_Native.Some
                                            "refinement_interpretation"),
                                         (Prims.strcat
                                            "refinement_interpretation_" tsym)) in
                                     FStarC_SMTEncoding_Util.mkAssume uu___9 in
                                   let t_decls =
                                     [tdecl; t_kinding; t_interp; t_haseq] in
                                   let uu___9 =
                                     let uu___10 =
                                       let uu___11 =
                                         FStarC_SMTEncoding_Term.mk_decls
                                           tsym tkey_hash t_decls
                                           (FStarC_List.op_At decls decls') in
                                       FStarC_List.op_At decls' uu___11 in
                                     FStarC_List.op_At decls uu___10 in
                                   (t2, uu___9))))))))
    | FStarC_Syntax_Syntax.Tm_uvar (uv, uu___2) ->
        let ttm =
          let uu___3 =
            FStarC_Syntax_Unionfind.uvar_id
              uv.FStarC_Syntax_Syntax.ctx_uvar_head in
          FStarC_SMTEncoding_Term.mk_Term_uvar uu___3
            FStarC_Range_Type.dummyRange in
        let uu___3 =
          let uu___4 = FStarC_Syntax_Util.ctx_uvar_typ uv in
          encode_term_pred FStar_Pervasives_Native.None uu___4 env ttm in
        (match uu___3 with
         | (t_has_k, decls) ->
             let d =
               let uu___4 =
                 let uu___5 =
                   let uu___6 =
                     let uu___7 =
                       let uu___8 =
                         FStarC_Syntax_Unionfind.uvar_id
                           uv.FStarC_Syntax_Syntax.ctx_uvar_head in
                       FStarC_Class_Show.show FStarC_Class_Show.showable_int
                         uu___8 in
                     FStarC_Format.fmt1 "uvar_typing_%s" uu___7 in
                   FStarC_SMTEncoding_Env.varops.FStarC_SMTEncoding_Env.mk_unique
                     uu___6 in
                 (t_has_k, (FStar_Pervasives_Native.Some "Uvar typing"),
                   uu___5) in
               FStarC_SMTEncoding_Util.mkAssume uu___4 in
             let uu___4 =
               let uu___5 = FStarC_SMTEncoding_Term.mk_decls_trivial [d] in
               FStarC_List.op_At decls uu___5 in
             (ttm, uu___4))
    | FStarC_Syntax_Syntax.Tm_app uu___2 ->
        let uu___3 = FStarC_Syntax_Util.head_and_args t0 in
        (match uu___3 with
         | (head, args_e) ->
             let uu___4 =
               let uu___5 = head_redex env head in
               if uu___5
               then
                 let uu___6 = maybe_whnf env t0 in
                 match uu___6 with
                 | FStar_Pervasives_Native.None -> (head, args_e)
                 | FStar_Pervasives_Native.Some t2 ->
                     FStarC_Syntax_Util.head_and_args t2
               else (head, args_e) in
             (match uu___4 with
              | (head1, args_e1) ->
                  let uu___5 =
                    let uu___6 =
                      let uu___7 = FStarC_Syntax_Subst.compress head1 in
                      uu___7.FStarC_Syntax_Syntax.n in
                    (uu___6, args_e1) in
                  if is_arithmetic_primitive head1 args_e1
                  then encode_arith_term env head1 args_e1
                  else
                    if is_BitVector_primitive head1 args_e1
                    then encode_BitVector_term env head1 args_e1
                    else
                      (match uu___5 with
                       | (FStarC_Syntax_Syntax.Tm_fvar fv, (arg, uu___6)::[])
                           when
                           ((FStarC_Syntax_Syntax.fv_eq_lid fv
                               FStarC_Parser_Const.squash_lid)
                              ||
                              (FStarC_Syntax_Syntax.fv_eq_lid fv
                                 FStarC_Parser_Const.auto_squash_lid))
                             &&
                             (let uu___7 =
                                FStarC_Syntax_Formula.destruct_typ_as_formula
                                  arg in
                              FStar_Pervasives_Native.uu___is_Some uu___7)
                           ->
                           let dummy =
                             FStarC_Syntax_Syntax.new_bv
                               FStar_Pervasives_Native.None
                               FStarC_Syntax_Syntax.t_unit in
                           let t2 = FStarC_Syntax_Util.refine dummy arg in
                           encode_term t2 env
                       | (FStarC_Syntax_Syntax.Tm_uinst
                          ({
                             FStarC_Syntax_Syntax.n =
                               FStarC_Syntax_Syntax.Tm_fvar fv;
                             FStarC_Syntax_Syntax.pos = uu___6;
                             FStarC_Syntax_Syntax.vars = uu___7;
                             FStarC_Syntax_Syntax.hash_code = uu___8;_},
                           uu___9),
                          (arg, uu___10)::[]) when
                           ((FStarC_Syntax_Syntax.fv_eq_lid fv
                               FStarC_Parser_Const.squash_lid)
                              ||
                              (FStarC_Syntax_Syntax.fv_eq_lid fv
                                 FStarC_Parser_Const.auto_squash_lid))
                             &&
                             (let uu___11 =
                                FStarC_Syntax_Formula.destruct_typ_as_formula
                                  arg in
                              FStar_Pervasives_Native.uu___is_Some uu___11)
                           ->
                           let dummy =
                             FStarC_Syntax_Syntax.new_bv
                               FStar_Pervasives_Native.None
                               FStarC_Syntax_Syntax.t_unit in
                           let t2 = FStarC_Syntax_Util.refine dummy arg in
                           encode_term t2 env
                       | (FStarC_Syntax_Syntax.Tm_fvar fv, uu___6) when
                           (Prims.op_Negation
                              env.FStarC_SMTEncoding_Env.encoding_quantifier)
                             &&
                             ((FStarC_Syntax_Syntax.fv_eq_lid fv
                                 FStarC_Parser_Const.forall_lid)
                                ||
                                (FStarC_Syntax_Syntax.fv_eq_lid fv
                                   FStarC_Parser_Const.exists_lid))
                           -> encode_deeply_embedded_quantifier t0 env
                       | (FStarC_Syntax_Syntax.Tm_uinst
                          ({
                             FStarC_Syntax_Syntax.n =
                               FStarC_Syntax_Syntax.Tm_fvar fv;
                             FStarC_Syntax_Syntax.pos = uu___6;
                             FStarC_Syntax_Syntax.vars = uu___7;
                             FStarC_Syntax_Syntax.hash_code = uu___8;_},
                           uu___9),
                          uu___10) when
                           (Prims.op_Negation
                              env.FStarC_SMTEncoding_Env.encoding_quantifier)
                             &&
                             ((FStarC_Syntax_Syntax.fv_eq_lid fv
                                 FStarC_Parser_Const.forall_lid)
                                ||
                                (FStarC_Syntax_Syntax.fv_eq_lid fv
                                   FStarC_Parser_Const.exists_lid))
                           -> encode_deeply_embedded_quantifier t0 env
                       | (FStarC_Syntax_Syntax.Tm_uinst
                          ({
                             FStarC_Syntax_Syntax.n =
                               FStarC_Syntax_Syntax.Tm_fvar fv;
                             FStarC_Syntax_Syntax.pos = uu___6;
                             FStarC_Syntax_Syntax.vars = uu___7;
                             FStarC_Syntax_Syntax.hash_code = uu___8;_},
                           uu___9),
                          (v0, uu___10)::(v1, uu___11)::(v2, uu___12)::[])
                           when
                           FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.lexcons_lid
                           ->
                           let uu___13 = encode_term v0 env in
                           (match uu___13 with
                            | (v01, decls0) ->
                                let uu___14 = encode_term v1 env in
                                (match uu___14 with
                                 | (v11, decls1) ->
                                     let uu___15 = encode_term v2 env in
                                     (match uu___15 with
                                      | (v21, decls2) ->
                                          let uu___16 =
                                            FStarC_SMTEncoding_Util.mk_LexCons
                                              v01 v11 v21 in
                                          (uu___16,
                                            (FStarC_List.op_At decls0
                                               (FStarC_List.op_At decls1
                                                  decls2))))))
                       | (FStarC_Syntax_Syntax.Tm_fvar fv,
                          (v0, uu___6)::(v1, uu___7)::(v2, uu___8)::[]) when
                           FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.lexcons_lid
                           ->
                           let uu___9 = encode_term v0 env in
                           (match uu___9 with
                            | (v01, decls0) ->
                                let uu___10 = encode_term v1 env in
                                (match uu___10 with
                                 | (v11, decls1) ->
                                     let uu___11 = encode_term v2 env in
                                     (match uu___11 with
                                      | (v21, decls2) ->
                                          let uu___12 =
                                            FStarC_SMTEncoding_Util.mk_LexCons
                                              v01 v11 v21 in
                                          (uu___12,
                                            (FStarC_List.op_At decls0
                                               (FStarC_List.op_At decls1
                                                  decls2))))))
                       | (FStarC_Syntax_Syntax.Tm_constant
                          (FStarC_Const.Const_range_of), (arg, uu___6)::[])
                           ->
                           encode_const
                             (FStarC_Const.Const_range
                                (arg.FStarC_Syntax_Syntax.pos)) env
                       | (FStarC_Syntax_Syntax.Tm_constant
                          (FStarC_Const.Const_set_range_of),
                          (arg, uu___6)::(rng, uu___7)::[]) ->
                           encode_term arg env
                       | (FStarC_Syntax_Syntax.Tm_constant
                          (FStarC_Const.Const_reify lopt), uu___6) ->
                           let fallback uu___7 =
                             let f =
                               FStarC_SMTEncoding_Env.varops.FStarC_SMTEncoding_Env.fresh
                                 env.FStarC_SMTEncoding_Env.current_module_name
                                 "Tm_reify" in
                             let decl =
                               FStarC_SMTEncoding_Term.DeclFun
                                 (f, [], FStarC_SMTEncoding_Term.Term_sort,
                                   (FStar_Pervasives_Native.Some
                                      "Imprecise reify")) in
                             let uu___8 =
                               let uu___9 =
                                 FStarC_SMTEncoding_Term.mk_fv
                                   (f, FStarC_SMTEncoding_Term.Term_sort) in
                               FStarC_SMTEncoding_Util.mkFreeV uu___9 in
                             let uu___9 =
                               FStarC_SMTEncoding_Term.mk_decls_trivial
                                 [decl] in
                             (uu___8, uu___9) in
                           (match lopt with
                            | FStar_Pervasives_Native.None -> fallback ()
                            | FStar_Pervasives_Native.Some l when
                                let uu___7 =
                                  FStarC_TypeChecker_Env.norm_eff_name
                                    env.FStarC_SMTEncoding_Env.tcenv l in
                                FStarC_TypeChecker_Env.is_layered_effect
                                  env.FStarC_SMTEncoding_Env.tcenv uu___7
                                -> fallback ()
                            | uu___7 ->
                                let e0 =
                                  let uu___8 =
                                    let uu___9 =
                                      let uu___10 = FStarC_List.hd args_e1 in
                                      FStar_Pervasives_Native.fst uu___10 in
                                    FStarC_Syntax_Util.mk_reify uu___9 lopt in
                                  FStarC_TypeChecker_Util.norm_reify
                                    env.FStarC_SMTEncoding_Env.tcenv []
                                    uu___8 in
                                ((let uu___9 =
                                    FStarC_Effect.op_Bang
                                      dbg_SMTEncodingReify in
                                  if uu___9
                                  then
                                    let uu___10 =
                                      FStarC_Class_Show.show
                                        FStarC_Syntax_Print.showable_term e0 in
                                    FStarC_Format.print1
                                      "Result of normalization %s\n" uu___10
                                  else ());
                                 (let e =
                                    let uu___9 =
                                      FStarC_TypeChecker_Util.remove_reify e0 in
                                    let uu___10 = FStarC_List.tl args_e1 in
                                    FStarC_Syntax_Syntax.mk_Tm_app uu___9
                                      uu___10 t0.FStarC_Syntax_Syntax.pos in
                                  encode_term e env)))
                       | (FStarC_Syntax_Syntax.Tm_constant
                          (FStarC_Const.Const_reflect uu___6),
                          (arg, uu___7)::[]) -> encode_term arg env
                       | (FStarC_Syntax_Syntax.Tm_fvar fv,
                          uu___6::(phi, uu___7)::[]) when
                           FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.by_tactic_lid
                           -> encode_term phi env
                       | (FStarC_Syntax_Syntax.Tm_uinst
                          ({
                             FStarC_Syntax_Syntax.n =
                               FStarC_Syntax_Syntax.Tm_fvar fv;
                             FStarC_Syntax_Syntax.pos = uu___6;
                             FStarC_Syntax_Syntax.vars = uu___7;
                             FStarC_Syntax_Syntax.hash_code = uu___8;_},
                           uu___9),
                          uu___10::(phi, uu___11)::[]) when
                           FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.by_tactic_lid
                           -> encode_term phi env
                       | (FStarC_Syntax_Syntax.Tm_fvar fv,
                          uu___6::uu___7::(phi, uu___8)::[]) when
                           FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.rewrite_by_tactic_lid
                           -> encode_term phi env
                       | (FStarC_Syntax_Syntax.Tm_uinst
                          ({
                             FStarC_Syntax_Syntax.n =
                               FStarC_Syntax_Syntax.Tm_fvar fv;
                             FStarC_Syntax_Syntax.pos = uu___6;
                             FStarC_Syntax_Syntax.vars = uu___7;
                             FStarC_Syntax_Syntax.hash_code = uu___8;_},
                           uu___9),
                          uu___10::uu___11::(phi, uu___12)::[]) when
                           FStarC_Syntax_Syntax.fv_eq_lid fv
                             FStarC_Parser_Const.rewrite_by_tactic_lid
                           -> encode_term phi env
                       | uu___6 ->
                           let uu___7 = encode_args args_e1 env in
                           (match uu___7 with
                            | (args, decls) ->
                                let encode_partial_app ht_opt =
                                  let uu___8 = encode_term head1 env in
                                  match uu___8 with
                                  | (smt_head, decls') ->
                                      let app_tm =
                                        mk_Apply_args smt_head args in
                                      (app_tm,
                                        (FStarC_List.op_At decls decls')) in
                                let encode_full_app fv univs =
                                  let uu___8 =
                                    FStarC_SMTEncoding_Env.lookup_free_var_sym
                                      env fv in
                                  match uu___8 with
                                  | (fname, fuel_args, arity) ->
                                      let tm =
                                        maybe_curry_app
                                          t0.FStarC_Syntax_Syntax.pos fname
                                          (arity + (FStarC_List.length univs))
                                          (FStarC_List.op_At fuel_args
                                             (FStarC_List.op_At univs args)) in
                                      (tm, decls) in
                                let head2 =
                                  FStarC_Syntax_Subst.compress head1 in
                                let head_type =
                                  match head2.FStarC_Syntax_Syntax.n with
                                  | FStarC_Syntax_Syntax.Tm_uinst
                                      ({
                                         FStarC_Syntax_Syntax.n =
                                           FStarC_Syntax_Syntax.Tm_name x;
                                         FStarC_Syntax_Syntax.pos = uu___8;
                                         FStarC_Syntax_Syntax.vars = uu___9;
                                         FStarC_Syntax_Syntax.hash_code =
                                           uu___10;_},
                                       uu___11)
                                      ->
                                      FStar_Pervasives_Native.Some
                                        (x.FStarC_Syntax_Syntax.sort)
                                  | FStarC_Syntax_Syntax.Tm_name x ->
                                      FStar_Pervasives_Native.Some
                                        (x.FStarC_Syntax_Syntax.sort)
                                  | FStarC_Syntax_Syntax.Tm_uinst
                                      ({
                                         FStarC_Syntax_Syntax.n =
                                           FStarC_Syntax_Syntax.Tm_fvar fv;
                                         FStarC_Syntax_Syntax.pos = uu___8;
                                         FStarC_Syntax_Syntax.vars = uu___9;
                                         FStarC_Syntax_Syntax.hash_code =
                                           uu___10;_},
                                       uu___11)
                                      ->
                                      let uu___12 =
                                        let uu___13 =
                                          let uu___14 =
                                            FStarC_TypeChecker_Env.lookup_lid
                                              env.FStarC_SMTEncoding_Env.tcenv
                                              fv.FStarC_Syntax_Syntax.fv_name in
                                          FStar_Pervasives_Native.fst uu___14 in
                                        FStar_Pervasives_Native.snd uu___13 in
                                      FStar_Pervasives_Native.Some uu___12
                                  | FStarC_Syntax_Syntax.Tm_fvar fv ->
                                      let uu___8 =
                                        let uu___9 =
                                          let uu___10 =
                                            FStarC_TypeChecker_Env.lookup_lid
                                              env.FStarC_SMTEncoding_Env.tcenv
                                              fv.FStarC_Syntax_Syntax.fv_name in
                                          FStar_Pervasives_Native.fst uu___10 in
                                        FStar_Pervasives_Native.snd uu___9 in
                                      FStar_Pervasives_Native.Some uu___8
                                  | FStarC_Syntax_Syntax.Tm_ascribed
                                      { FStarC_Syntax_Syntax.tm = uu___8;
                                        FStarC_Syntax_Syntax.asc =
                                          (FStar_Pervasives.Inl t2, uu___9,
                                           uu___10);
                                        FStarC_Syntax_Syntax.eff_opt =
                                          uu___11;_}
                                      -> FStar_Pervasives_Native.Some t2
                                  | FStarC_Syntax_Syntax.Tm_ascribed
                                      { FStarC_Syntax_Syntax.tm = uu___8;
                                        FStarC_Syntax_Syntax.asc =
                                          (FStar_Pervasives.Inr c, uu___9,
                                           uu___10);
                                        FStarC_Syntax_Syntax.eff_opt =
                                          uu___11;_}
                                      ->
                                      let uu___12 =
                                        FStarC_Syntax_Util.comp_result c in
                                      FStar_Pervasives_Native.Some uu___12
                                  | uu___8 -> FStar_Pervasives_Native.None in
                                (match head_type with
                                 | FStar_Pervasives_Native.None ->
                                     encode_partial_app
                                       FStar_Pervasives_Native.None
                                 | FStar_Pervasives_Native.Some head_type1 ->
                                     let uu___8 =
                                       let head_type2 =
                                         let uu___9 =
                                           normalize_refinement
                                             [FStarC_TypeChecker_Env.Weak;
                                             FStarC_TypeChecker_Env.HNF]
                                             env.FStarC_SMTEncoding_Env.tcenv
                                             head_type1 in
                                         FStarC_Syntax_Util.unrefine uu___9 in
                                       let uu___9 =
                                         curried_arrow_formals_comp
                                           head_type2 in
                                       match uu___9 with
                                       | (formals, c) ->
                                           if
                                             (FStarC_List.length formals) <
                                               (FStarC_List.length args)
                                           then
                                             let head_type3 =
                                               let uu___10 =
                                                 normalize_refinement
                                                   [FStarC_TypeChecker_Env.Weak;
                                                   FStarC_TypeChecker_Env.HNF;
                                                   FStarC_TypeChecker_Env.UnfoldUntil
                                                     FStarC_Syntax_Syntax.delta_constant]
                                                   env.FStarC_SMTEncoding_Env.tcenv
                                                   head_type2 in
                                               FStarC_Syntax_Util.unrefine
                                                 uu___10 in
                                             let uu___10 =
                                               curried_arrow_formals_comp
                                                 head_type3 in
                                             (match uu___10 with
                                              | (formals1, c1) ->
                                                  (head_type3, formals1, c1))
                                           else (head_type2, formals, c) in
                                     (match uu___8 with
                                      | (head_type2, formals, c) ->
                                          ((let uu___10 =
                                              FStarC_Effect.op_Bang
                                                dbg_PartialApp in
                                            if uu___10
                                            then
                                              let uu___11 =
                                                FStarC_Class_Show.show
                                                  FStarC_Syntax_Print.showable_term
                                                  head_type2 in
                                              let uu___12 =
                                                FStarC_Class_Show.show
                                                  (FStarC_Class_Show.show_list
                                                     FStarC_Syntax_Print.showable_binder)
                                                  formals in
                                              let uu___13 =
                                                FStarC_Class_Show.show
                                                  (FStarC_Class_Show.show_list
                                                     (FStarC_Class_Show.show_tuple2
                                                        FStarC_Syntax_Print.showable_term
                                                        FStarC_Syntax_Print.showable_aqual))
                                                  args_e1 in
                                              FStarC_Format.print3
                                                "Encoding partial application, head_type = %s, formals = %s, args = %s\n"
                                                uu___11 uu___12 uu___13
                                            else ());
                                           (match head2.FStarC_Syntax_Syntax.n
                                            with
                                            | FStarC_Syntax_Syntax.Tm_uinst
                                                ({
                                                   FStarC_Syntax_Syntax.n =
                                                     FStarC_Syntax_Syntax.Tm_fvar
                                                     fv;
                                                   FStarC_Syntax_Syntax.pos =
                                                     uu___10;
                                                   FStarC_Syntax_Syntax.vars
                                                     = uu___11;
                                                   FStarC_Syntax_Syntax.hash_code
                                                     = uu___12;_},
                                                 us)
                                                when
                                                (FStarC_List.length formals)
                                                  = (FStarC_List.length args)
                                                ->
                                                let uu___13 =
                                                  FStarC_List.map
                                                    encode_universe us in
                                                encode_full_app
                                                  fv.FStarC_Syntax_Syntax.fv_name
                                                  uu___13
                                            | FStarC_Syntax_Syntax.Tm_fvar fv
                                                when
                                                (FStarC_List.length formals)
                                                  = (FStarC_List.length args)
                                                ->
                                                encode_full_app
                                                  fv.FStarC_Syntax_Syntax.fv_name
                                                  []
                                            | uu___10 ->
                                                if
                                                  (FStarC_List.length formals)
                                                    >
                                                    (FStarC_List.length args)
                                                then
                                                  encode_partial_app
                                                    (FStar_Pervasives_Native.Some
                                                       (head_type2, formals,
                                                         c))
                                                else
                                                  encode_partial_app
                                                    FStar_Pervasives_Native.None))))))))
    | FStarC_Syntax_Syntax.Tm_abs
        { FStarC_Syntax_Syntax.bs = bs; FStarC_Syntax_Syntax.body = body;
          FStarC_Syntax_Syntax.rc_opt = lopt;_}
        ->
        let uu___2 = FStarC_Syntax_Subst.open_term' bs body in
        (match uu___2 with
         | (bs1, body1, opening) ->
             let fallback uu___3 =
               let uu___4 =
                 let fvs =
                   let uu___5 = FStarC_Syntax_Free.names t0 in
                   FStarC_Class_Setlike.elems ()
                     (Obj.magic
                        (FStarC_FlatSet.setlike_flat_set
                           FStarC_Syntax_Syntax.ord_bv)) (Obj.magic uu___5) in
                 let tms =
                   FStarC_List.map
                     (FStarC_SMTEncoding_Env.lookup_term_var env) fvs in
                 let uu___5 =
                   FStarC_List.map
                     (fun uu___6 -> FStarC_SMTEncoding_Term.Term_sort) fvs in
                 (uu___5, tms) in
               match uu___4 with
               | (arg_sorts, arg_terms) ->
                   let f =
                     FStarC_SMTEncoding_Env.varops.FStarC_SMTEncoding_Env.fresh
                       env.FStarC_SMTEncoding_Env.current_module_name
                       "Tm_abs" in
                   let decl =
                     FStarC_SMTEncoding_Term.DeclFun
                       (f, arg_sorts, FStarC_SMTEncoding_Term.Term_sort,
                         (FStar_Pervasives_Native.Some
                            "Imprecise function encoding")) in
                   let fv =
                     let uu___5 =
                       FStarC_SMTEncoding_Term.mk_fv
                         (f, FStarC_SMTEncoding_Term.Term_sort) in
                     FStarC_SMTEncoding_Util.mkFreeV uu___5 in
                   let fapp = FStarC_SMTEncoding_Util.mkApp (f, arg_terms) in
                   let uu___5 =
                     FStarC_SMTEncoding_Term.mk_decls_trivial [decl] in
                   (fapp, uu___5) in
             let is_impure rc =
               let uu___3 =
                 FStarC_TypeChecker_Util.is_pure_or_ghost_effect
                   env.FStarC_SMTEncoding_Env.tcenv
                   rc.FStarC_Syntax_Syntax.residual_effect in
               Prims.op_Negation uu___3 in
             let codomain_eff rc =
               let res_typ =
                 match rc.FStarC_Syntax_Syntax.residual_typ with
                 | FStar_Pervasives_Native.None ->
                     let uu___3 =
                       let uu___4 =
                         FStarC_TypeChecker_Env.get_range
                           env.FStarC_SMTEncoding_Env.tcenv in
                       FStarC_TypeChecker_Util.new_implicit_var
                         "SMTEncoding codomain" uu___4
                         env.FStarC_SMTEncoding_Env.tcenv
                         FStarC_Syntax_Util.ktype0 false in
                     (match uu___3 with | (t2, uu___4, uu___5) -> t2)
                 | FStar_Pervasives_Native.Some t2 -> t2 in
               let uu___3 =
                 FStarC_Ident.lid_equals
                   rc.FStarC_Syntax_Syntax.residual_effect
                   FStarC_Parser_Const.effect_Tot_lid in
               if uu___3
               then
                 let uu___4 = FStarC_Syntax_Syntax.mk_Total res_typ in
                 FStar_Pervasives_Native.Some uu___4
               else
                 (let uu___5 =
                    FStarC_Ident.lid_equals
                      rc.FStarC_Syntax_Syntax.residual_effect
                      FStarC_Parser_Const.effect_GTot_lid in
                  if uu___5
                  then
                    let uu___6 = FStarC_Syntax_Syntax.mk_GTotal res_typ in
                    FStar_Pervasives_Native.Some uu___6
                  else FStar_Pervasives_Native.None) in
             (match lopt with
              | FStar_Pervasives_Native.None ->
                  ((let uu___4 =
                      let uu___5 =
                        let uu___6 =
                          FStarC_Errors_Msg.text
                            "Losing precision when encoding a function literal:" in
                        let uu___7 =
                          FStarC_Class_PP.pp FStarC_Syntax_Print.pretty_term
                            t0 in
                        FStar_Pprint.prefix (Prims.of_int (2)) Prims.int_one
                          uu___6 uu___7 in
                      let uu___6 =
                        let uu___7 =
                          FStarC_Errors_Msg.text
                            "Unannotated abstraction in the compiler?" in
                        [uu___7] in
                      uu___5 :: uu___6 in
                    FStarC_Errors.log_issue
                      (FStarC_Syntax_Syntax.has_range_syntax ()) t0
                      FStarC_Errors_Codes.Warning_FunctionLiteralPrecisionLoss
                      ()
                      (Obj.magic FStarC_Errors_Msg.is_error_message_list_doc)
                      (Obj.magic uu___4));
                   fallback ())
              | FStar_Pervasives_Native.Some rc ->
                  let uu___3 =
                    (is_impure rc) &&
                      (let uu___4 =
                         FStarC_SMTEncoding_Util.is_smt_reifiable_rc
                           env.FStarC_SMTEncoding_Env.tcenv rc in
                       Prims.op_Negation uu___4) in
                  if uu___3
                  then fallback ()
                  else
                    (let uu___5 =
                       encode_binders FStar_Pervasives_Native.None bs1 env in
                     match uu___5 with
                     | (vars, guards, envbody, decls, uu___6) ->
                         let body2 =
                           let uu___7 =
                             FStarC_SMTEncoding_Util.is_smt_reifiable_rc
                               env.FStarC_SMTEncoding_Env.tcenv rc in
                           if uu___7
                           then
                             let uu___8 =
                               FStarC_Syntax_Util.mk_reify body1
                                 (FStar_Pervasives_Native.Some
                                    (rc.FStarC_Syntax_Syntax.residual_effect)) in
                             FStarC_TypeChecker_Util.norm_reify
                               env.FStarC_SMTEncoding_Env.tcenv [] uu___8
                           else body1 in
                         let uu___7 = encode_term body2 envbody in
                         (match uu___7 with
                          | (body3, decls') ->
                              let is_pure =
                                FStarC_Syntax_Util.is_pure_effect
                                  rc.FStarC_Syntax_Syntax.residual_effect in
                              let uu___8 =
                                let uu___9 = codomain_eff rc in
                                match uu___9 with
                                | FStar_Pervasives_Native.None ->
                                    (FStar_Pervasives_Native.None, [])
                                | FStar_Pervasives_Native.Some c ->
                                    let tfun = FStarC_Syntax_Util.arrow bs1 c in
                                    let uu___10 = encode_term tfun env in
                                    (match uu___10 with
                                     | (t2, decls1) ->
                                         ((FStar_Pervasives_Native.Some t2),
                                           decls1)) in
                              (match uu___8 with
                               | (arrow_t_opt, decls'') ->
                                   let key_body =
                                     let uu___9 =
                                       let uu___10 =
                                         let uu___11 =
                                           let uu___12 =
                                             FStarC_SMTEncoding_Util.mk_and_l
                                               guards in
                                           (uu___12, body3) in
                                         FStarC_SMTEncoding_Util.mkImp
                                           uu___11 in
                                       ([], vars, uu___10) in
                                     FStarC_SMTEncoding_Term.mkForall
                                       t0.FStarC_Syntax_Syntax.pos uu___9 in
                                   let cvars =
                                     FStarC_SMTEncoding_Term.free_variables
                                       key_body in
                                   let uu___9 =
                                     match arrow_t_opt with
                                     | FStar_Pervasives_Native.None ->
                                         (cvars, key_body)
                                     | FStar_Pervasives_Native.Some t2 ->
                                         let uu___10 =
                                           let uu___11 =
                                             let uu___12 =
                                               FStarC_SMTEncoding_Term.free_variables
                                                 t2 in
                                             FStarC_List.op_At uu___12 cvars in
                                           FStarC_Util.remove_dups
                                             FStarC_SMTEncoding_Term.fv_eq
                                             uu___11 in
                                         let uu___11 =
                                           FStarC_SMTEncoding_Util.mkAnd
                                             (key_body, t2) in
                                         (uu___10, uu___11) in
                                   (match uu___9 with
                                    | (cvars1, key_body1) ->
                                        let tkey =
                                          FStarC_SMTEncoding_Term.mkForall
                                            t0.FStarC_Syntax_Syntax.pos
                                            ([], cvars1, key_body1) in
                                        let tkey_hash =
                                          FStarC_SMTEncoding_Term.hash_of_term
                                            tkey in
                                        ((let uu___11 =
                                            FStarC_Effect.op_Bang
                                              dbg_PartialApp in
                                          if uu___11
                                          then
                                            let uu___12 =
                                              let uu___13 =
                                                FStarC_List.map
                                                  FStarC_SMTEncoding_Term.fv_name
                                                  vars in
                                              FStarC_String.concat ", "
                                                uu___13 in
                                            let uu___13 =
                                              FStarC_SMTEncoding_Term.print_smt_term
                                                body3 in
                                            FStarC_Format.print2
                                              "Checking eta expansion of\n\tvars={%s}\n\tbody=%s\n"
                                              uu___12 uu___13
                                          else ());
                                         (let cvar_sorts =
                                            FStarC_List.map
                                              FStarC_SMTEncoding_Term.fv_sort
                                              cvars1 in
                                          let fsym =
                                            let uu___11 =
                                              FStarC_Util.digest_of_string
                                                tkey_hash in
                                            Prims.strcat "Tm_abs_" uu___11 in
                                          let fdecl =
                                            FStarC_SMTEncoding_Term.DeclFun
                                              (fsym, cvar_sorts,
                                                FStarC_SMTEncoding_Term.Term_sort,
                                                FStar_Pervasives_Native.None) in
                                          let f =
                                            let uu___11 =
                                              let uu___12 =
                                                FStarC_List.map
                                                  FStarC_SMTEncoding_Util.mkFreeV
                                                  cvars1 in
                                              (fsym, uu___12) in
                                            FStarC_SMTEncoding_Util.mkApp
                                              uu___11 in
                                          let app = mk_Apply f vars in
                                          let typing_f =
                                            match arrow_t_opt with
                                            | FStar_Pervasives_Native.None ->
                                                let tot_fun_ax =
                                                  let ax =
                                                    let uu___11 =
                                                      FStarC_List.map
                                                        (fun uu___12 ->
                                                           FStarC_SMTEncoding_Util.mkTrue)
                                                        vars in
                                                    isTotFun_axioms
                                                      t0.FStarC_Syntax_Syntax.pos
                                                      f [] vars uu___11
                                                      is_pure in
                                                  match cvars1 with
                                                  | [] -> ax
                                                  | uu___11 ->
                                                      FStarC_SMTEncoding_Term.mkForall
                                                        t0.FStarC_Syntax_Syntax.pos
                                                        ([[f]], cvars1, ax) in
                                                let a_name =
                                                  Prims.strcat "tot_fun_"
                                                    fsym in
                                                let uu___11 =
                                                  FStarC_SMTEncoding_Util.mkAssume
                                                    (tot_fun_ax,
                                                      (FStar_Pervasives_Native.Some
                                                         a_name), a_name) in
                                                [uu___11]
                                            | FStar_Pervasives_Native.Some t2
                                                ->
                                                let f_has_t =
                                                  FStarC_SMTEncoding_Term.mk_HasTypeWithFuel
                                                    FStar_Pervasives_Native.None
                                                    f t2 in
                                                let a_name =
                                                  Prims.strcat "typing_" fsym in
                                                let uu___11 =
                                                  let uu___12 =
                                                    let uu___13 =
                                                      FStarC_SMTEncoding_Term.mkForall
                                                        t0.FStarC_Syntax_Syntax.pos
                                                        ([[f]], cvars1,
                                                          f_has_t) in
                                                    (uu___13,
                                                      (FStar_Pervasives_Native.Some
                                                         a_name), a_name) in
                                                  FStarC_SMTEncoding_Util.mkAssume
                                                    uu___12 in
                                                [uu___11] in
                                          let interp_f =
                                            let a_name =
                                              Prims.strcat "interpretation_"
                                                fsym in
                                            let uu___11 =
                                              let uu___12 =
                                                let uu___13 =
                                                  let uu___14 =
                                                    FStarC_SMTEncoding_Util.mkEq
                                                      (app, body3) in
                                                  ([[app]],
                                                    (FStarC_List.op_At vars
                                                       cvars1), uu___14) in
                                                FStarC_SMTEncoding_Term.mkForall
                                                  t0.FStarC_Syntax_Syntax.pos
                                                  uu___13 in
                                              (uu___12,
                                                (FStar_Pervasives_Native.Some
                                                   a_name), a_name) in
                                            FStarC_SMTEncoding_Util.mkAssume
                                              uu___11 in
                                          let f_decls =
                                            FStarC_List.op_At (fdecl ::
                                              typing_f) [interp_f] in
                                          let uu___11 =
                                            let uu___12 =
                                              let uu___13 =
                                                let uu___14 =
                                                  FStarC_SMTEncoding_Term.mk_decls
                                                    fsym tkey_hash f_decls
                                                    (FStarC_List.op_At decls
                                                       (FStarC_List.op_At
                                                          decls' decls'')) in
                                                FStarC_List.op_At decls''
                                                  uu___14 in
                                              FStarC_List.op_At decls'
                                                uu___13 in
                                            FStarC_List.op_At decls uu___12 in
                                          (f, uu___11)))))))))
    | FStarC_Syntax_Syntax.Tm_let
        {
          FStarC_Syntax_Syntax.lbs =
            (uu___2,
             { FStarC_Syntax_Syntax.lbname = FStar_Pervasives.Inr uu___3;
               FStarC_Syntax_Syntax.lbunivs = uu___4;
               FStarC_Syntax_Syntax.lbtyp = uu___5;
               FStarC_Syntax_Syntax.lbeff = uu___6;
               FStarC_Syntax_Syntax.lbdef = uu___7;
               FStarC_Syntax_Syntax.lbattrs = uu___8;
               FStarC_Syntax_Syntax.lbpos = uu___9;_}::uu___10);
          FStarC_Syntax_Syntax.body1 = uu___11;_}
        -> failwith "Impossible: already handled by encoding of Sig_let"
    | FStarC_Syntax_Syntax.Tm_let
        {
          FStarC_Syntax_Syntax.lbs =
            (false,
             { FStarC_Syntax_Syntax.lbname = FStar_Pervasives.Inl x;
               FStarC_Syntax_Syntax.lbunivs = uu___2;
               FStarC_Syntax_Syntax.lbtyp = t11;
               FStarC_Syntax_Syntax.lbeff = uu___3;
               FStarC_Syntax_Syntax.lbdef = e1;
               FStarC_Syntax_Syntax.lbattrs = uu___4;
               FStarC_Syntax_Syntax.lbpos = uu___5;_}::[]);
          FStarC_Syntax_Syntax.body1 = e2;_}
        -> encode_let x t11 e1 e2 env encode_term
    | FStarC_Syntax_Syntax.Tm_let
        { FStarC_Syntax_Syntax.lbs = (false, uu___2::uu___3);
          FStarC_Syntax_Syntax.body1 = uu___4;_}
        -> failwith "Impossible: non-recursive let with multiple bindings"
    | FStarC_Syntax_Syntax.Tm_let
        { FStarC_Syntax_Syntax.lbs = (true, lbs);
          FStarC_Syntax_Syntax.body1 = uu___2;_}
        ->
        let f =
          FStarC_SMTEncoding_Env.varops.FStarC_SMTEncoding_Env.fresh
            env.FStarC_SMTEncoding_Env.current_module_name "inner_let_rec" in
        let decl =
          FStarC_SMTEncoding_Term.DeclFun
            (f, [], FStarC_SMTEncoding_Term.Term_sort,
              (FStar_Pervasives_Native.Some "Inner let rec")) in
        let uu___3 =
          let uu___4 =
            FStarC_SMTEncoding_Term.mk_fv
              (f, FStarC_SMTEncoding_Term.Term_sort) in
          FStarC_SMTEncoding_Util.mkFreeV uu___4 in
        let uu___4 = FStarC_SMTEncoding_Term.mk_decls_trivial [decl] in
        (uu___3, uu___4)
    | FStarC_Syntax_Syntax.Tm_let uu___2 ->
        failwith "Impossible: all cases handled above (encode_term)."
    | FStarC_Syntax_Syntax.Tm_match
        { FStarC_Syntax_Syntax.scrutinee = e;
          FStarC_Syntax_Syntax.ret_opt = uu___2;
          FStarC_Syntax_Syntax.brs = pats;
          FStarC_Syntax_Syntax.rc_opt1 = uu___3;_}
        ->
        encode_match e pats FStarC_SMTEncoding_Term.mk_Term_unit env
          encode_term))
and encode_let (x : FStarC_Syntax_Syntax.bv) (t1 : FStarC_Syntax_Syntax.typ)
  (e1 : FStarC_Syntax_Syntax.term) (e2 : FStarC_Syntax_Syntax.term)
  (env : FStarC_SMTEncoding_Env.env_t)
  (encode_body :
    FStarC_Syntax_Syntax.term ->
      FStarC_SMTEncoding_Env.env_t ->
        (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t))
  : (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let uu___ =
    let uu___1 =
      FStarC_Syntax_Util.ascribe e1
        ((FStar_Pervasives.Inl t1), FStar_Pervasives_Native.None, false) in
    encode_term uu___1 env in
  match uu___ with
  | (ee1, decls1) ->
      let uu___1 =
        let uu___2 =
          let uu___3 = FStarC_Syntax_Syntax.mk_binder x in [uu___3] in
        FStarC_Syntax_Subst.open_term uu___2 e2 in
      (match uu___1 with
       | (xs, e21) ->
           let x1 =
             let uu___2 = FStarC_List.hd xs in
             uu___2.FStarC_Syntax_Syntax.binder_bv in
           let env' = FStarC_SMTEncoding_Env.push_term_var env x1 ee1 in
           let uu___2 = encode_body e21 env' in
           (match uu___2 with
            | (ee2, decls2) -> (ee2, (FStarC_List.op_At decls1 decls2))))
and encode_match (e : FStarC_Syntax_Syntax.term)
  (pats : FStarC_Syntax_Syntax.branch Prims.list)
  (default_case : FStarC_SMTEncoding_Term.term)
  (env : FStarC_SMTEncoding_Env.env_t)
  (encode_br :
    FStarC_Syntax_Syntax.term ->
      FStarC_SMTEncoding_Env.env_t ->
        (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t))
  : (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let uu___ =
    let uu___1 =
      let uu___2 =
        FStarC_Syntax_Syntax.mk FStarC_Syntax_Syntax.Tm_unknown
          FStarC_Range_Type.dummyRange in
      FStarC_Syntax_Syntax.null_bv uu___2 in
    FStarC_SMTEncoding_Env.gen_term_var env uu___1 in
  match uu___ with
  | (scrsym, scr', env1) ->
      let uu___1 = encode_term e env1 in
      (match uu___1 with
       | (scr, decls) ->
           let uu___2 =
             let encode_branch b uu___3 =
               match uu___3 with
               | (else_case, decls1) ->
                   let uu___4 = FStarC_Syntax_Subst.open_branch b in
                   (match uu___4 with
                    | (p, w, br) ->
                        let uu___5 = encode_pat env1 p in
                        (match uu___5 with
                         | (env0, pattern1) ->
                             let guard = pattern1.guard scr' in
                             let projections = pattern1.projections scr' in
                             let env2 =
                               FStarC_List.fold_left
                                 (fun env3 uu___6 ->
                                    match uu___6 with
                                    | (x, t) ->
                                        FStarC_SMTEncoding_Env.push_term_var
                                          env3 x t) env1 projections in
                             let uu___6 =
                               match w with
                               | FStar_Pervasives_Native.None -> (guard, [])
                               | FStar_Pervasives_Native.Some w1 ->
                                   let uu___7 = encode_term w1 env2 in
                                   (match uu___7 with
                                    | (w2, decls2) ->
                                        let uu___8 =
                                          let uu___9 =
                                            let uu___10 =
                                              let uu___11 =
                                                let uu___12 =
                                                  FStarC_SMTEncoding_Term.boxBool
                                                    FStarC_SMTEncoding_Util.mkTrue in
                                                (w2, uu___12) in
                                              FStarC_SMTEncoding_Util.mkEq
                                                uu___11 in
                                            (guard, uu___10) in
                                          FStarC_SMTEncoding_Util.mkAnd
                                            uu___9 in
                                        (uu___8, decls2)) in
                             (match uu___6 with
                              | (guard1, decls2) ->
                                  let uu___7 = encode_br br env2 in
                                  (match uu___7 with
                                   | (br1, decls3) ->
                                       let uu___8 =
                                         FStarC_SMTEncoding_Util.mkITE
                                           (guard1, br1, else_case) in
                                       (uu___8,
                                         (FStarC_List.op_At decls1
                                            (FStarC_List.op_At decls2 decls3))))))) in
             FStarC_List.fold_right encode_branch pats (default_case, decls) in
           (match uu___2 with
            | (match_tm, decls1) ->
                let uu___3 =
                  let uu___4 =
                    let uu___5 =
                      let uu___6 =
                        let uu___7 =
                          FStarC_SMTEncoding_Term.mk_fv
                            (scrsym, FStarC_SMTEncoding_Term.Term_sort) in
                        (uu___7, scr) in
                      [uu___6] in
                    (uu___5, match_tm) in
                  FStarC_SMTEncoding_Term.mkLet' uu___4
                    FStarC_Range_Type.dummyRange in
                (uu___3, decls1)))
and encode_pat (env : FStarC_SMTEncoding_Env.env_t)
  (pat : FStarC_Syntax_Syntax.pat) :
  (FStarC_SMTEncoding_Env.env_t * pattern)=
  (let uu___1 = FStarC_Debug.medium () in
   if uu___1
   then
     let uu___2 = FStarC_Class_Show.show FStarC_Syntax_Print.showable_pat pat in
     FStarC_Format.print1 "Encoding pattern %s\n" uu___2
   else ());
  (let uu___1 = FStarC_TypeChecker_Util.decorated_pattern_as_term pat in
   match uu___1 with
   | (vars, pat_term) ->
       let uu___2 =
         FStarC_List.fold_left
           (fun uu___3 v ->
              match uu___3 with
              | (env1, vars1) ->
                  let uu___4 = FStarC_SMTEncoding_Env.gen_term_var env1 v in
                  (match uu___4 with
                   | (xx, uu___5, env2) ->
                       let uu___6 =
                         let uu___7 =
                           let uu___8 =
                             FStarC_SMTEncoding_Term.mk_fv
                               (xx, FStarC_SMTEncoding_Term.Term_sort) in
                           (v, uu___8) in
                         uu___7 :: vars1 in
                       (env2, uu___6))) (env, []) vars in
       (match uu___2 with
        | (env1, vars1) ->
            let rec mk_guard pat1 scrutinee =
              match pat1.FStarC_Syntax_Syntax.v with
              | FStarC_Syntax_Syntax.Pat_var uu___3 ->
                  FStarC_SMTEncoding_Util.mkTrue
              | FStarC_Syntax_Syntax.Pat_dot_term uu___3 ->
                  FStarC_SMTEncoding_Util.mkTrue
              | FStarC_Syntax_Syntax.Pat_constant c ->
                  let uu___3 = encode_const c env1 in
                  (match uu___3 with
                   | (tm, decls) ->
                       ((match decls with
                         | uu___5::uu___6 ->
                             failwith
                               "Unexpected encoding of constant pattern"
                         | uu___5 -> ());
                        FStarC_SMTEncoding_Util.mkEq (scrutinee, tm)))
              | FStarC_Syntax_Syntax.Pat_cons (f, uu___3, args) ->
                  let is_f =
                    let tc_name =
                      FStarC_TypeChecker_Env.typ_of_datacon
                        env1.FStarC_SMTEncoding_Env.tcenv
                        f.FStarC_Syntax_Syntax.fv_name in
                    let uu___4 =
                      FStarC_TypeChecker_Env.datacons_of_typ
                        env1.FStarC_SMTEncoding_Env.tcenv tc_name in
                    match uu___4 with
                    | (uu___5, uu___6::[]) -> FStarC_SMTEncoding_Util.mkTrue
                    | uu___5 ->
                        FStarC_SMTEncoding_Env.mk_data_tester env1
                          f.FStarC_Syntax_Syntax.fv_name scrutinee in
                  let sub_term_guards =
                    FStarC_List.mapi
                      (fun i uu___4 ->
                         match uu___4 with
                         | (arg, uu___5) ->
                             let proj =
                               FStarC_SMTEncoding_Env.primitive_projector_by_pos
                                 env1.FStarC_SMTEncoding_Env.tcenv
                                 f.FStarC_Syntax_Syntax.fv_name i in
                             let uu___6 =
                               FStarC_SMTEncoding_Util.mkApp
                                 (proj, [scrutinee]) in
                             mk_guard arg uu___6) args in
                  FStarC_SMTEncoding_Util.mk_and_l (is_f :: sub_term_guards) in
            let rec mk_projections pat1 scrutinee =
              match pat1.FStarC_Syntax_Syntax.v with
              | FStarC_Syntax_Syntax.Pat_dot_term uu___3 -> []
              | FStarC_Syntax_Syntax.Pat_var x -> [(x, scrutinee)]
              | FStarC_Syntax_Syntax.Pat_constant uu___3 -> []
              | FStarC_Syntax_Syntax.Pat_cons (f, uu___3, args) ->
                  let uu___4 =
                    FStarC_List.mapi
                      (fun i uu___5 ->
                         match uu___5 with
                         | (arg, uu___6) ->
                             let proj =
                               FStarC_SMTEncoding_Env.primitive_projector_by_pos
                                 env1.FStarC_SMTEncoding_Env.tcenv
                                 f.FStarC_Syntax_Syntax.fv_name i in
                             let uu___7 =
                               FStarC_SMTEncoding_Util.mkApp
                                 (proj, [scrutinee]) in
                             mk_projections arg uu___7) args in
                  FStarC_List.flatten uu___4 in
            let pat_term1 uu___3 = encode_term pat_term env1 in
            let pattern1 =
              {
                pat_vars = vars1;
                pat_term = pat_term1;
                guard = (mk_guard pat);
                projections = (mk_projections pat)
              } in
            (env1, pattern1)))
and encode_args (l : FStarC_Syntax_Syntax.args)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term Prims.list * FStarC_SMTEncoding_Term.decls_t)=
  let uu___ =
    FStarC_List.fold_left
      (fun uu___1 uu___2 ->
         match (uu___1, uu___2) with
         | ((tms, decls), (t, uu___3)) ->
             let uu___4 = encode_term t env in
             (match uu___4 with
              | (t1, decls') ->
                  ((t1 :: tms), (FStarC_List.op_At decls decls')))) ([], [])
      l in
  match uu___ with | (l1, decls) -> ((FStarC_List.rev l1), decls)
and encode_smt_patterns
  (pats_l : FStarC_Syntax_Syntax.arg Prims.list Prims.list)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term Prims.list Prims.list *
    FStarC_SMTEncoding_Term.decls_t)=
  let env1 =
    {
      FStarC_SMTEncoding_Env.bvar_bindings =
        (env.FStarC_SMTEncoding_Env.bvar_bindings);
      FStarC_SMTEncoding_Env.fvar_bindings =
        (env.FStarC_SMTEncoding_Env.fvar_bindings);
      FStarC_SMTEncoding_Env.depth = (env.FStarC_SMTEncoding_Env.depth);
      FStarC_SMTEncoding_Env.tcenv = (env.FStarC_SMTEncoding_Env.tcenv);
      FStarC_SMTEncoding_Env.warn = (env.FStarC_SMTEncoding_Env.warn);
      FStarC_SMTEncoding_Env.nolabels = (env.FStarC_SMTEncoding_Env.nolabels);
      FStarC_SMTEncoding_Env.use_zfuel_name = true;
      FStarC_SMTEncoding_Env.encode_non_total_function_typ =
        (env.FStarC_SMTEncoding_Env.encode_non_total_function_typ);
      FStarC_SMTEncoding_Env.current_module_name =
        (env.FStarC_SMTEncoding_Env.current_module_name);
      FStarC_SMTEncoding_Env.encoding_quantifier =
        (env.FStarC_SMTEncoding_Env.encoding_quantifier);
      FStarC_SMTEncoding_Env.global_cache =
        (env.FStarC_SMTEncoding_Env.global_cache)
    } in
  let encode_smt_pattern t =
    let uu___ = FStarC_Syntax_Util.head_and_args t in
    match uu___ with
    | (head, args) ->
        let head1 = FStarC_Syntax_Util.un_uinst head in
        (match ((head1.FStarC_Syntax_Syntax.n), args) with
         | (FStarC_Syntax_Syntax.Tm_fvar fv,
            uu___1::(x, uu___2)::(t1, uu___3)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.has_type_lid
             ->
             let uu___4 = encode_term x env1 in
             (match uu___4 with
              | (x1, decls) ->
                  let uu___5 = encode_term t1 env1 in
                  (match uu___5 with
                   | (t2, decls') ->
                       let uu___6 = FStarC_SMTEncoding_Term.mk_HasType x1 t2 in
                       (uu___6, (FStarC_List.op_At decls decls'))))
         | uu___1 -> encode_term t env1) in
  FStarC_List.fold_right
    (fun pats uu___ ->
       match uu___ with
       | (pats_l1, decls) ->
           let uu___1 =
             FStarC_List.fold_right
               (fun uu___2 uu___3 ->
                  match (uu___2, uu___3) with
                  | ((p, uu___4), (pats1, decls1)) ->
                      let uu___5 = encode_smt_pattern p in
                      (match uu___5 with
                       | (t, d) ->
                           let uu___6 =
                             FStarC_SMTEncoding_Term.check_pattern_ok t in
                           (match uu___6 with
                            | FStar_Pervasives_Native.None ->
                                ((t :: pats1), (FStarC_List.op_At d decls1))
                            | FStar_Pervasives_Native.Some illegal_subterm ->
                                ((let uu___8 =
                                    let uu___9 =
                                      FStarC_Class_Show.show
                                        FStarC_Syntax_Print.showable_term p in
                                    let uu___10 =
                                      FStarC_Class_Show.show
                                        FStarC_SMTEncoding_Term.showable_smt_term
                                        illegal_subterm in
                                    FStarC_Format.fmt2
                                      "Pattern %s contains illegal sub-term (%s); dropping it"
                                      uu___9 uu___10 in
                                  FStarC_Errors.log_issue
                                    (FStarC_Syntax_Syntax.has_range_syntax ())
                                    p
                                    FStarC_Errors_Codes.Warning_SMTPatternIllFormed
                                    ()
                                    (Obj.magic
                                       FStarC_Errors_Msg.is_error_message_string)
                                    (Obj.magic uu___8));
                                 (pats1, (FStarC_List.op_At d decls1))))))
               pats ([], decls) in
           (match uu___1 with
            | (pats1, decls1) -> ((pats1 :: pats_l1), decls1))) pats_l
    ([], [])
and encode_formula (phi : FStarC_Syntax_Syntax.typ)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let debug phi1 =
    let uu___ = FStarC_Effect.op_Bang dbg_SMTEncoding in
    if uu___
    then
      let uu___1 =
        FStarC_Class_Tagged.tag_of FStarC_Syntax_Syntax.tagged_term phi1 in
      let uu___2 =
        FStarC_Class_Show.show FStarC_Syntax_Print.showable_term phi1 in
      FStarC_Format.print2 "Formula (%s)  %s\n" uu___1 uu___2
    else () in
  let enc f r l =
    let uu___ =
      FStarC_Util.fold_map
        (fun decls x ->
           let uu___1 = encode_term (FStar_Pervasives_Native.fst x) env in
           match uu___1 with
           | (t, decls') -> ((FStarC_List.op_At decls decls'), t)) [] l in
    match uu___ with
    | (decls, args) ->
        let uu___1 =
          let uu___2 = f args in
          {
            FStarC_SMTEncoding_Term.tm = (uu___2.FStarC_SMTEncoding_Term.tm);
            FStarC_SMTEncoding_Term.freevars =
              (uu___2.FStarC_SMTEncoding_Term.freevars);
            FStarC_SMTEncoding_Term.rng = r
          } in
        (uu___1, decls) in
  let const_op f r uu___ = let uu___1 = f r in (uu___1, []) in
  let un_op f l = let uu___ = FStarC_List.hd l in f uu___ in
  let bin_op f uu___ =
    match uu___ with
    | t1::t2::[] -> f (t1, t2)
    | uu___1 -> failwith "Impossible" in
  let enc_prop_c f r l =
    let uu___ =
      FStarC_Util.fold_map
        (fun decls uu___1 ->
           match uu___1 with
           | (t, uu___2) ->
               let uu___3 = encode_formula t env in
               (match uu___3 with
                | (phi1, decls') -> ((FStarC_List.op_At decls decls'), phi1)))
        [] l in
    match uu___ with
    | (decls, phis) ->
        let uu___1 =
          let uu___2 = f phis in
          {
            FStarC_SMTEncoding_Term.tm = (uu___2.FStarC_SMTEncoding_Term.tm);
            FStarC_SMTEncoding_Term.freevars =
              (uu___2.FStarC_SMTEncoding_Term.freevars);
            FStarC_SMTEncoding_Term.rng = r
          } in
        (uu___1, decls) in
  let eq_op r args =
    let rf =
      FStarC_List.filter
        (fun uu___ ->
           match uu___ with
           | (a, q) ->
               (match q with
                | FStar_Pervasives_Native.Some
                    { FStarC_Syntax_Syntax.aqual_implicit = true;
                      FStarC_Syntax_Syntax.aqual_attributes = uu___1;_}
                    -> false
                | uu___1 -> true)) args in
    if (FStarC_List.length rf) <> (Prims.of_int (2))
    then
      let uu___ =
        let uu___1 =
          FStarC_Class_Show.show FStarC_Class_Show.showable_nat
            (FStarC_List.length rf) in
        FStarC_Format.fmt1
          "eq_op: got %s non-implicit arguments instead of 2?" uu___1 in
      failwith uu___
    else
      (let uu___1 = enc (bin_op FStarC_SMTEncoding_Util.mkEq) in uu___1 r rf) in
  let mk_imp r uu___ =
    match uu___ with
    | (lhs, uu___1)::(rhs, uu___2)::[] ->
        let uu___3 = encode_formula rhs env in
        (match uu___3 with
         | (l1, decls1) ->
             (match l1.FStarC_SMTEncoding_Term.tm with
              | FStarC_SMTEncoding_Term.App
                  (FStarC_SMTEncoding_Term.TrueOp, uu___4) -> (l1, decls1)
              | uu___4 ->
                  let uu___5 = encode_formula lhs env in
                  (match uu___5 with
                   | (l2, decls2) ->
                       let uu___6 = FStarC_SMTEncoding_Term.mkImp (l2, l1) r in
                       (uu___6, (FStarC_List.op_At decls1 decls2)))))
    | uu___1 -> failwith "impossible" in
  let mk_ite r uu___ =
    match uu___ with
    | (guard, uu___1)::(_then, uu___2)::(_else, uu___3)::[] ->
        let uu___4 = encode_formula guard env in
        (match uu___4 with
         | (g, decls1) ->
             let uu___5 = encode_formula _then env in
             (match uu___5 with
              | (t, decls2) ->
                  let uu___6 = encode_formula _else env in
                  (match uu___6 with
                   | (e, decls3) ->
                       let res = FStarC_SMTEncoding_Term.mkITE (g, t, e) r in
                       (res,
                         (FStarC_List.op_At decls1
                            (FStarC_List.op_At decls2 decls3))))))
    | uu___1 -> failwith "impossible" in
  let unboxInt_l f l =
    let uu___ = FStarC_List.map FStarC_SMTEncoding_Term.unboxInt l in f uu___ in
  let connectives =
    let uu___ =
      let uu___1 = enc_prop_c (bin_op FStarC_SMTEncoding_Util.mkAnd) in
      (FStarC_Parser_Const.and_lid, uu___1) in
    let uu___1 =
      let uu___2 =
        let uu___3 = enc_prop_c (bin_op FStarC_SMTEncoding_Util.mkOr) in
        (FStarC_Parser_Const.or_lid, uu___3) in
      let uu___3 =
        let uu___4 =
          let uu___5 =
            let uu___6 = enc_prop_c (bin_op FStarC_SMTEncoding_Util.mkIff) in
            (FStarC_Parser_Const.iff_lid, uu___6) in
          let uu___6 =
            let uu___7 =
              let uu___8 =
                let uu___9 = enc_prop_c (un_op FStarC_SMTEncoding_Util.mkNot) in
                (FStarC_Parser_Const.not_lid, uu___9) in
              [uu___8;
              (FStarC_Parser_Const.eq2_lid, eq_op);
              (FStarC_Parser_Const.c_eq2_lid, eq_op);
              (FStarC_Parser_Const.true_lid,
                (const_op FStarC_SMTEncoding_Term.mkTrue));
              (FStarC_Parser_Const.false_lid,
                (const_op FStarC_SMTEncoding_Term.mkFalse))] in
            (FStarC_Parser_Const.ite_lid, mk_ite) :: uu___7 in
          uu___5 :: uu___6 in
        (FStarC_Parser_Const.imp_lid, mk_imp) :: uu___4 in
      uu___2 :: uu___3 in
    uu___ :: uu___1 in
  let rec fallback phi1 =
    match phi1.FStarC_Syntax_Syntax.n with
    | FStarC_Syntax_Syntax.Tm_meta
        { FStarC_Syntax_Syntax.tm2 = phi';
          FStarC_Syntax_Syntax.meta = FStarC_Syntax_Syntax.Meta_labeled
            (msg, r, b);_}
        ->
        let uu___ = encode_formula phi' env in
        (match uu___ with
         | (phi2, decls) ->
             let uu___1 =
               FStarC_SMTEncoding_Term.mk
                 (FStarC_SMTEncoding_Term.Labeled (phi2, msg, r)) r in
             (uu___1, decls))
    | FStarC_Syntax_Syntax.Tm_meta uu___ ->
        let uu___1 = FStarC_Syntax_Util.unmeta phi1 in
        encode_formula uu___1 env
    | FStarC_Syntax_Syntax.Tm_match
        { FStarC_Syntax_Syntax.scrutinee = e;
          FStarC_Syntax_Syntax.ret_opt = uu___;
          FStarC_Syntax_Syntax.brs = pats;
          FStarC_Syntax_Syntax.rc_opt1 = uu___1;_}
        ->
        let uu___2 =
          encode_match e pats FStarC_SMTEncoding_Term.mkUnreachable env
            encode_formula in
        (match uu___2 with | (t, decls) -> (t, decls))
    | FStarC_Syntax_Syntax.Tm_let
        {
          FStarC_Syntax_Syntax.lbs =
            (false,
             { FStarC_Syntax_Syntax.lbname = FStar_Pervasives.Inl x;
               FStarC_Syntax_Syntax.lbunivs = uu___;
               FStarC_Syntax_Syntax.lbtyp = t1;
               FStarC_Syntax_Syntax.lbeff = uu___1;
               FStarC_Syntax_Syntax.lbdef = e1;
               FStarC_Syntax_Syntax.lbattrs = uu___2;
               FStarC_Syntax_Syntax.lbpos = uu___3;_}::[]);
          FStarC_Syntax_Syntax.body1 = e2;_}
        ->
        let uu___4 = encode_let x t1 e1 e2 env encode_formula in
        (match uu___4 with | (t, decls) -> (t, decls))
    | FStarC_Syntax_Syntax.Tm_app
        { FStarC_Syntax_Syntax.hd = head; FStarC_Syntax_Syntax.args = args;_}
        ->
        let uu___ =
          let uu___1 =
            let uu___2 = FStarC_Syntax_Util.un_uinst head in
            uu___2.FStarC_Syntax_Syntax.n in
          (uu___1, args) in
        (match uu___ with
         | (FStarC_Syntax_Syntax.Tm_fvar fv,
            uu___1::(x, uu___2)::(t, uu___3)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.has_type_lid
             ->
             let uu___4 = encode_term x env in
             (match uu___4 with
              | (x1, decls) ->
                  let uu___5 = encode_term t env in
                  (match uu___5 with
                   | (t1, decls') ->
                       let uu___6 = FStarC_SMTEncoding_Term.mk_HasType x1 t1 in
                       (uu___6, (FStarC_List.op_At decls decls'))))
         | (FStarC_Syntax_Syntax.Tm_fvar fv, uu___1::(phi2, uu___2)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.by_tactic_lid
             -> encode_formula phi2 env
         | (FStarC_Syntax_Syntax.Tm_uinst
            ({ FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
               FStarC_Syntax_Syntax.pos = uu___1;
               FStarC_Syntax_Syntax.vars = uu___2;
               FStarC_Syntax_Syntax.hash_code = uu___3;_},
             uu___4),
            uu___5::(phi2, uu___6)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.by_tactic_lid
             -> encode_formula phi2 env
         | (FStarC_Syntax_Syntax.Tm_fvar fv,
            uu___1::uu___2::(phi2, uu___3)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.rewrite_by_tactic_lid
             -> encode_formula phi2 env
         | (FStarC_Syntax_Syntax.Tm_uinst
            ({ FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
               FStarC_Syntax_Syntax.pos = uu___1;
               FStarC_Syntax_Syntax.vars = uu___2;
               FStarC_Syntax_Syntax.hash_code = uu___3;_},
             uu___4),
            uu___5::uu___6::(phi2, uu___7)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.rewrite_by_tactic_lid
             -> encode_formula phi2 env
         | (FStarC_Syntax_Syntax.Tm_fvar fv,
            (r, uu___1)::(msg, uu___2)::(phi2, uu___3)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv
               FStarC_Parser_Const.labeled_lid
             ->
             let uu___4 =
               let uu___5 =
                 FStarC_Syntax_Embeddings_Base.try_unembed
                   FStarC_Syntax_Embeddings.e_range r
                   FStarC_Syntax_Embeddings_Base.id_norm_cb in
               let uu___6 =
                 FStarC_Syntax_Embeddings_Base.try_unembed
                   FStarC_Syntax_Embeddings.e_string msg
                   FStarC_Syntax_Embeddings_Base.id_norm_cb in
               (uu___5, uu___6) in
             (match uu___4 with
              | (FStar_Pervasives_Native.Some r1,
                 FStar_Pervasives_Native.Some s) ->
                  let phi3 =
                    let uu___5 =
                      let uu___6 =
                        let uu___7 =
                          let uu___8 =
                            let uu___9 = FStarC_Errors_Msg.mkmsg s in
                            (uu___9, r1, false) in
                          FStarC_Syntax_Syntax.Meta_labeled uu___8 in
                        {
                          FStarC_Syntax_Syntax.tm2 = phi2;
                          FStarC_Syntax_Syntax.meta = uu___7
                        } in
                      FStarC_Syntax_Syntax.Tm_meta uu___6 in
                    FStarC_Syntax_Syntax.mk uu___5 r1 in
                  fallback phi3
              | (FStar_Pervasives_Native.None, FStar_Pervasives_Native.Some
                 s) ->
                  let phi3 =
                    let uu___5 =
                      let uu___6 =
                        let uu___7 =
                          let uu___8 =
                            let uu___9 = FStarC_Errors_Msg.mkmsg s in
                            (uu___9, (phi2.FStarC_Syntax_Syntax.pos), false) in
                          FStarC_Syntax_Syntax.Meta_labeled uu___8 in
                        {
                          FStarC_Syntax_Syntax.tm2 = phi2;
                          FStarC_Syntax_Syntax.meta = uu___7
                        } in
                      FStarC_Syntax_Syntax.Tm_meta uu___6 in
                    FStarC_Syntax_Syntax.mk uu___5
                      phi2.FStarC_Syntax_Syntax.pos in
                  fallback phi3
              | uu___5 -> fallback phi2)
         | (FStarC_Syntax_Syntax.Tm_fvar fv, (t, uu___1)::[]) when
             (FStarC_Syntax_Syntax.fv_eq_lid fv
                FStarC_Parser_Const.squash_lid)
               ||
               (FStarC_Syntax_Syntax.fv_eq_lid fv
                  FStarC_Parser_Const.auto_squash_lid)
             -> encode_formula t env
         | uu___1 ->
             let encode_valid uu___2 =
               debug phi1;
               (let uu___4 = encode_term phi1 env in
                match uu___4 with
                | (tt, decls) ->
                    let tt1 =
                      let uu___5 =
                        let uu___6 =
                          FStarC_Range_Type.use_range
                            tt.FStarC_SMTEncoding_Term.rng in
                        let uu___7 =
                          FStarC_Range_Type.use_range
                            phi1.FStarC_Syntax_Syntax.pos in
                        FStarC_Range_Ops.rng_included uu___6 uu___7 in
                      if uu___5
                      then tt
                      else
                        {
                          FStarC_SMTEncoding_Term.tm =
                            (tt.FStarC_SMTEncoding_Term.tm);
                          FStarC_SMTEncoding_Term.freevars =
                            (tt.FStarC_SMTEncoding_Term.freevars);
                          FStarC_SMTEncoding_Term.rng =
                            (phi1.FStarC_Syntax_Syntax.pos)
                        } in
                    let uu___5 = FStarC_SMTEncoding_Term.mk_Valid tt1 in
                    (uu___5, decls)) in
             let uu___2 = head_redex env head in
             if uu___2
             then
               let uu___3 = maybe_whnf env head in
               (match uu___3 with
                | FStar_Pervasives_Native.None -> encode_valid ()
                | FStar_Pervasives_Native.Some phi2 ->
                    encode_formula phi2 env)
             else encode_valid ())
    | uu___ ->
        let uu___1 = encode_term phi1 env in
        (match uu___1 with
         | (tt, decls) ->
             let tt1 =
               let uu___2 =
                 let uu___3 =
                   FStarC_Range_Type.use_range tt.FStarC_SMTEncoding_Term.rng in
                 let uu___4 =
                   FStarC_Range_Type.use_range phi1.FStarC_Syntax_Syntax.pos in
                 FStarC_Range_Ops.rng_included uu___3 uu___4 in
               if uu___2
               then tt
               else
                 {
                   FStarC_SMTEncoding_Term.tm =
                     (tt.FStarC_SMTEncoding_Term.tm);
                   FStarC_SMTEncoding_Term.freevars =
                     (tt.FStarC_SMTEncoding_Term.freevars);
                   FStarC_SMTEncoding_Term.rng =
                     (phi1.FStarC_Syntax_Syntax.pos)
                 } in
             let uu___2 = FStarC_SMTEncoding_Term.mk_Valid tt1 in
             (uu___2, decls)) in
  let encode_q_body env1 bs ps body =
    let uu___ = encode_binders FStar_Pervasives_Native.None bs env1 in
    match uu___ with
    | (vars, guards, env2, decls, uu___1) ->
        let uu___2 = encode_smt_patterns ps env2 in
        (match uu___2 with
         | (pats, decls') ->
             let uu___3 = encode_formula body env2 in
             (match uu___3 with
              | (body1, decls'') ->
                  let guards1 =
                    match pats with
                    | ({
                         FStarC_SMTEncoding_Term.tm =
                           FStarC_SMTEncoding_Term.App
                           (FStarC_SMTEncoding_Term.Var gf, p::[]);
                         FStarC_SMTEncoding_Term.freevars = uu___4;
                         FStarC_SMTEncoding_Term.rng = uu___5;_}::[])::[]
                        when
                        let uu___6 =
                          FStarC_Ident.string_of_lid
                            FStarC_Parser_Const.guard_free in
                        uu___6 = gf -> []
                    | uu___4 -> guards in
                  let uu___4 = FStarC_SMTEncoding_Util.mk_and_l guards1 in
                  (vars, pats, uu___4, body1,
                    (FStarC_List.op_At decls
                       (FStarC_List.op_At decls' decls''))))) in
  debug phi;
  (let phi1 = FStarC_Syntax_Util.unascribe phi in
   let uu___1 = FStarC_Syntax_Formula.destruct_typ_as_formula phi1 in
   match uu___1 with
   | FStar_Pervasives_Native.None -> fallback phi1
   | FStar_Pervasives_Native.Some (FStarC_Syntax_Formula.BaseConn (op, arms))
       ->
       let uu___2 =
         FStarC_List.tryFind
           (fun uu___3 ->
              match uu___3 with | (l, uu___4) -> FStarC_Ident.lid_equals op l)
           connectives in
       (match uu___2 with
        | FStar_Pervasives_Native.None -> fallback phi1
        | FStar_Pervasives_Native.Some (uu___3, f) ->
            f phi1.FStarC_Syntax_Syntax.pos arms)
   | FStar_Pervasives_Native.Some (FStarC_Syntax_Formula.QAll
       (vars, pats, body)) ->
       (FStarC_List.iter (check_pattern_vars env vars) pats;
        (let uu___3 = encode_q_body env vars pats body in
         match uu___3 with
         | (vars1, pats1, guard, body1, decls) ->
             let tm =
               let uu___4 =
                 let uu___5 = FStarC_SMTEncoding_Util.mkImp (guard, body1) in
                 (pats1, vars1, uu___5) in
               FStarC_SMTEncoding_Term.mkForall phi1.FStarC_Syntax_Syntax.pos
                 uu___4 in
             (tm, decls)))
   | FStar_Pervasives_Native.Some (FStarC_Syntax_Formula.QEx
       (vars, pats, body)) ->
       (FStarC_List.iter (check_pattern_vars env vars) pats;
        (let uu___3 = encode_q_body env vars pats body in
         match uu___3 with
         | (vars1, pats1, guard, body1, decls) ->
             let uu___4 =
               let uu___5 =
                 let uu___6 = FStarC_SMTEncoding_Util.mkAnd (guard, body1) in
                 (pats1, vars1, uu___6) in
               FStarC_SMTEncoding_Term.mkExists phi1.FStarC_Syntax_Syntax.pos
                 uu___5 in
             (uu___4, decls))))
let encode_function_type_as_formula (t : FStarC_Syntax_Syntax.typ)
  (env : FStarC_SMTEncoding_Env.env_t) :
  (FStarC_SMTEncoding_Term.term * FStarC_SMTEncoding_Term.decls_t)=
  let universe_of_binders binders =
    FStarC_List.map (fun uu___ -> FStarC_Syntax_Syntax.U_zero) binders in
  let quant = FStarC_Syntax_Util.smt_lemma_as_forall t universe_of_binders in
  let env1 =
    {
      FStarC_SMTEncoding_Env.bvar_bindings =
        (env.FStarC_SMTEncoding_Env.bvar_bindings);
      FStarC_SMTEncoding_Env.fvar_bindings =
        (env.FStarC_SMTEncoding_Env.fvar_bindings);
      FStarC_SMTEncoding_Env.depth = (env.FStarC_SMTEncoding_Env.depth);
      FStarC_SMTEncoding_Env.tcenv = (env.FStarC_SMTEncoding_Env.tcenv);
      FStarC_SMTEncoding_Env.warn = (env.FStarC_SMTEncoding_Env.warn);
      FStarC_SMTEncoding_Env.nolabels = (env.FStarC_SMTEncoding_Env.nolabels);
      FStarC_SMTEncoding_Env.use_zfuel_name = true;
      FStarC_SMTEncoding_Env.encode_non_total_function_typ =
        (env.FStarC_SMTEncoding_Env.encode_non_total_function_typ);
      FStarC_SMTEncoding_Env.current_module_name =
        (env.FStarC_SMTEncoding_Env.current_module_name);
      FStarC_SMTEncoding_Env.encoding_quantifier =
        (env.FStarC_SMTEncoding_Env.encoding_quantifier);
      FStarC_SMTEncoding_Env.global_cache =
        (env.FStarC_SMTEncoding_Env.global_cache)
    } in
  encode_formula quant env1
