open Prims
let dbg_Tac : Prims.bool FStarC_Effect.ref= FStarC_Debug.get_toggle "Tac"
let dbg_SpinoffAll : Prims.bool FStarC_Effect.ref=
  FStarC_Debug.get_toggle "SpinoffAll"
let run_tactic_on_typ (rng_tac : FStarC_Range_Type.t)
  (rng_goal : FStarC_Range_Type.t) (tactic : FStarC_Syntax_Syntax.term)
  (env : FStarC_TypeChecker_Env.env) (typ : FStarC_Syntax_Syntax.term) :
  (FStarC_Tactics_Types.goal Prims.list * FStarC_Syntax_Syntax.term)=
  let rng =
    let uu___ = FStarC_Range_Type.use_range rng_tac in
    let uu___1 = FStarC_Range_Type.use_range rng_goal in
    FStarC_Range_Type.range_of_rng uu___ uu___1 in
  let uu___ = FStarC_Tactics_V2_Basic.proofstate_of_goal_ty rng env typ in
  match uu___ with
  | (ps, w) ->
      let tactic_already_typed = false in
      let uu___1 =
        FStarC_Tactics_Interpreter.run_tactic_on_ps rng_tac rng_goal false
          FStarC_Syntax_Embeddings.e_unit () FStarC_Syntax_Embeddings.e_unit
          tactic tactic_already_typed ps in
      (match uu___1 with | (gs, _res) -> (gs, w))
let run_tactic_on_all_implicits (rng_tac : FStarC_Range_Type.t)
  (rng_goal : FStarC_Range_Type.t) (tactic : FStarC_Syntax_Syntax.term)
  (env : FStarC_TypeChecker_Env.env)
  (imps : FStarC_TypeChecker_Env.implicits) :
  FStarC_Tactics_Types.goal Prims.list=
  let uu___ =
    FStarC_Tactics_V2_Basic.proofstate_of_all_implicits rng_goal env imps in
  match uu___ with
  | (ps, uu___1) ->
      let tactic_already_typed = false in
      let uu___2 =
        let uu___3 = FStarC_TypeChecker_Env.get_range env in
        FStarC_Tactics_Interpreter.run_tactic_on_ps uu___3 rng_goal true
          FStarC_Syntax_Embeddings.e_unit () FStarC_Syntax_Embeddings.e_unit
          tactic tactic_already_typed ps in
      (match uu___2 with | (goals, ()) -> goals)
type pol =
  | StrictlyPositive 
  | Pos 
  | Neg 
  | Both 
let uu___is_StrictlyPositive (projectee : pol) : Prims.bool=
  match projectee with | StrictlyPositive -> true | uu___ -> false
let uu___is_Pos (projectee : pol) : Prims.bool=
  match projectee with | Pos -> true | uu___ -> false
let uu___is_Neg (projectee : pol) : Prims.bool=
  match projectee with | Neg -> true | uu___ -> false
let uu___is_Both (projectee : pol) : Prims.bool=
  match projectee with | Both -> true | uu___ -> false
type 'a tres_m =
  | Unchanged of 'a 
  | Simplified of ('a * FStarC_Tactics_Types.goal Prims.list) 
  | Dual of ('a * 'a * FStarC_Tactics_Types.goal Prims.list) 
let uu___is_Unchanged (projectee : 'a tres_m) : Prims.bool=
  match projectee with | Unchanged _0 -> true | uu___ -> false
let __proj__Unchanged__item___0 (projectee : 'a tres_m) : 'a=
  match projectee with | Unchanged _0 -> _0
let uu___is_Simplified (projectee : 'a tres_m) : Prims.bool=
  match projectee with | Simplified _0 -> true | uu___ -> false
let __proj__Simplified__item___0 (projectee : 'a tres_m) :
  ('a * FStarC_Tactics_Types.goal Prims.list)=
  match projectee with | Simplified _0 -> _0
let uu___is_Dual (projectee : 'a tres_m) : Prims.bool=
  match projectee with | Dual _0 -> true | uu___ -> false
let __proj__Dual__item___0 (projectee : 'a tres_m) :
  ('a * 'a * FStarC_Tactics_Types.goal Prims.list)=
  match projectee with | Dual _0 -> _0
type tres = FStarC_Syntax_Syntax.term tres_m
let tpure (x : 'uuuuu) : 'uuuuu tres_m= Unchanged x
let flip (p : pol) : pol=
  match p with
  | StrictlyPositive -> Neg
  | Pos -> Neg
  | Neg -> Pos
  | Both -> Both
let getprop (e : FStarC_TypeChecker_Env.env) (t : FStarC_Syntax_Syntax.term)
  : FStarC_Syntax_Syntax.term FStar_Pervasives_Native.option=
  let tn =
    FStarC_TypeChecker_Normalize.normalize
      [FStarC_TypeChecker_Env.Weak;
      FStarC_TypeChecker_Env.HNF;
      FStarC_TypeChecker_Env.UnfoldUntil FStarC_Syntax_Syntax.delta_constant]
      e t in
  FStarC_Syntax_Util.un_squash tn
let by_tactic_interp (pol1 : pol) (e : FStarC_TypeChecker_Env.env)
  (t : FStarC_Syntax_Syntax.term) : tres=
  let uu___ = FStarC_Syntax_Util.head_and_args t in
  match uu___ with
  | (hd, args) ->
      let uu___1 =
        let uu___2 =
          let uu___3 = FStarC_Syntax_Util.un_uinst hd in
          uu___3.FStarC_Syntax_Syntax.n in
        (uu___2, args) in
      (match uu___1 with
       | (FStarC_Syntax_Syntax.Tm_fvar fv,
          (tactic, FStar_Pervasives_Native.None)::(assertion,
                                                   FStar_Pervasives_Native.None)::[])
           when
           FStarC_Syntax_Syntax.fv_eq_lid fv
             FStarC_Parser_Const.by_tactic_lid
           ->
           (match pol1 with
            | StrictlyPositive ->
                let uu___2 =
                  run_tactic_on_typ tactic.FStarC_Syntax_Syntax.pos
                    assertion.FStarC_Syntax_Syntax.pos tactic e assertion in
                (match uu___2 with
                 | (gs, uu___3) -> Simplified (FStarC_Syntax_Util.t_true, gs))
            | Pos ->
                let uu___2 =
                  run_tactic_on_typ tactic.FStarC_Syntax_Syntax.pos
                    assertion.FStarC_Syntax_Syntax.pos tactic e assertion in
                (match uu___2 with
                 | (gs, uu___3) -> Simplified (FStarC_Syntax_Util.t_true, gs))
            | Both ->
                let uu___2 =
                  run_tactic_on_typ tactic.FStarC_Syntax_Syntax.pos
                    assertion.FStarC_Syntax_Syntax.pos tactic e assertion in
                (match uu___2 with
                 | (gs, uu___3) ->
                     Dual (assertion, FStarC_Syntax_Util.t_true, gs))
            | Neg -> Simplified (assertion, []))
       | (FStarC_Syntax_Syntax.Tm_fvar fv,
          (assertion, FStar_Pervasives_Native.None)::[]) when
           FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.spinoff_lid
           ->
           (match pol1 with
            | StrictlyPositive ->
                let g =
                  let uu___2 =
                    FStarC_Tactics_Types.goal_of_goal_ty e assertion in
                  FStar_Pervasives_Native.fst uu___2 in
                let g1 =
                  FStarC_Tactics_Types.set_label "spun-off assertion" g in
                Simplified (FStarC_Syntax_Util.t_true, [g1])
            | Pos ->
                let g =
                  let uu___2 =
                    FStarC_Tactics_Types.goal_of_goal_ty e assertion in
                  FStar_Pervasives_Native.fst uu___2 in
                let g1 =
                  FStarC_Tactics_Types.set_label "spun-off assertion" g in
                Simplified (FStarC_Syntax_Util.t_true, [g1])
            | Both ->
                let g =
                  let uu___2 =
                    FStarC_Tactics_Types.goal_of_goal_ty e assertion in
                  FStar_Pervasives_Native.fst uu___2 in
                let g1 =
                  FStarC_Tactics_Types.set_label "spun-off assertion" g in
                Dual (assertion, FStarC_Syntax_Util.t_true, [g1])
            | Neg -> Simplified (assertion, []))
       | (FStarC_Syntax_Syntax.Tm_fvar fv,
          (tactic, FStar_Pervasives_Native.None)::(typ,
                                                   FStar_Pervasives_Native.Some
                                                   {
                                                     FStarC_Syntax_Syntax.aqual_implicit
                                                       = true;
                                                     FStarC_Syntax_Syntax.aqual_attributes
                                                       = uu___2;_})::
          (tm, FStar_Pervasives_Native.None)::[]) when
           FStarC_Syntax_Syntax.fv_eq_lid fv
             FStarC_Parser_Const.rewrite_by_tactic_lid
           ->
           let uu___3 =
             FStarC_TypeChecker_Env.new_implicit_var_aux
               "rewrite_with_tactic RHS" tm.FStarC_Syntax_Syntax.pos e typ
               FStarC_Syntax_Syntax.Strict FStar_Pervasives_Native.None false in
           (match uu___3 with
            | (uvtm, uu___4, g_imp) ->
                let u = e.FStarC_TypeChecker_Env.universe_of e typ in
                let goal =
                  let uu___5 = FStarC_Syntax_Util.mk_eq2 u typ tm uvtm in
                  FStarC_Syntax_Util.mk_squash FStarC_Syntax_Syntax.U_zero
                    uu___5 in
                let uu___5 =
                  run_tactic_on_typ tactic.FStarC_Syntax_Syntax.pos
                    tm.FStarC_Syntax_Syntax.pos tactic e goal in
                (match uu___5 with
                 | (gs, uu___6) ->
                     let tagged_imps =
                       FStarC_TypeChecker_Rel.resolve_implicits_tac e g_imp in
                     (FStarC_Tactics_Interpreter.report_implicits
                        tm.FStarC_Syntax_Syntax.pos tagged_imps;
                      Simplified (uvtm, gs))))
       | uu___2 -> Unchanged t)
let explode (t : 'a tres_m) :
  ('a * 'a * FStarC_Tactics_Types.goal Prims.list)=
  match t with
  | Unchanged t1 -> (t1, t1, [])
  | Simplified (t1, gs) -> (t1, t1, gs)
  | Dual (tn, tp, gs) -> (tn, tp, gs)
let comb1 (f : 'a -> 'b) (uu___ : 'a tres_m) : 'b tres_m=
  match uu___ with
  | Unchanged t -> let uu___1 = f t in Unchanged uu___1
  | Simplified (t, gs) ->
      let uu___1 = let uu___2 = f t in (uu___2, gs) in Simplified uu___1
  | Dual (tn, tp, gs) ->
      let uu___1 =
        let uu___2 = f tn in let uu___3 = f tp in (uu___2, uu___3, gs) in
      Dual uu___1
let comb2 (f : 'a -> 'b -> 'c) (x : 'a tres_m) (y : 'b tres_m) : 'c tres_m=
  match (x, y) with
  | (Unchanged t1, Unchanged t2) -> let uu___ = f t1 t2 in Unchanged uu___
  | (Unchanged t1, Simplified (t2, gs)) ->
      let uu___ = let uu___1 = f t1 t2 in (uu___1, gs) in Simplified uu___
  | (Simplified (t1, gs), Unchanged t2) ->
      let uu___ = let uu___1 = f t1 t2 in (uu___1, gs) in Simplified uu___
  | (Simplified (t1, gs1), Simplified (t2, gs2)) ->
      let uu___ =
        let uu___1 = f t1 t2 in (uu___1, (FStarC_List.op_At gs1 gs2)) in
      Simplified uu___
  | uu___ ->
      let uu___1 = explode x in
      (match uu___1 with
       | (n1, p1, gs1) ->
           let uu___2 = explode y in
           (match uu___2 with
            | (n2, p2, gs2) ->
                let uu___3 =
                  let uu___4 = f n1 n2 in
                  let uu___5 = f p1 p2 in
                  (uu___4, uu___5, (FStarC_List.op_At gs1 gs2)) in
                Dual uu___3))
let comb_list (rs : 'a tres_m Prims.list) : 'a Prims.list tres_m=
  let rec aux rs1 acc =
    match rs1 with
    | [] -> acc
    | hd::tl -> let uu___ = comb2 (fun l r -> l :: r) hd acc in aux tl uu___ in
  aux (FStarC_List.rev rs) (tpure [])
let emit (gs : FStarC_Tactics_Types.goal Prims.list) (m : 'a tres_m) :
  'a tres_m= comb2 (fun uu___ x -> x) (Simplified ((), gs)) m
let rec traverse
  (f :
    pol -> FStarC_TypeChecker_Env.env -> FStarC_Syntax_Syntax.term -> tres)
  (pol1 : pol) (e : FStarC_TypeChecker_Env.env)
  (t : FStarC_Syntax_Syntax.term) : tres=
  let r =
    let uu___ =
      let uu___1 = FStarC_Syntax_Subst.compress t in
      uu___1.FStarC_Syntax_Syntax.n in
    match uu___ with
    | FStarC_Syntax_Syntax.Tm_uinst (t1, us) ->
        let tr = traverse f pol1 e t1 in
        let uu___1 = comb1 (fun t' -> FStarC_Syntax_Syntax.Tm_uinst (t', us)) in
        uu___1 tr
    | FStarC_Syntax_Syntax.Tm_meta
        { FStarC_Syntax_Syntax.tm2 = t1; FStarC_Syntax_Syntax.meta = m;_} ->
        let tr = traverse f pol1 e t1 in
        let uu___1 =
          comb1
            (fun t' ->
               FStarC_Syntax_Syntax.Tm_meta
                 {
                   FStarC_Syntax_Syntax.tm2 = t';
                   FStarC_Syntax_Syntax.meta = m
                 }) in
        uu___1 tr
    | FStarC_Syntax_Syntax.Tm_app
        {
          FStarC_Syntax_Syntax.hd =
            { 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;_};
          FStarC_Syntax_Syntax.args = (p, uu___4)::(q, uu___5)::[];_}
        when FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.imp_lid ->
        let x = FStarC_Syntax_Syntax.new_bv FStar_Pervasives_Native.None p in
        let r1 = traverse f (flip pol1) e p in
        let r2 =
          let uu___6 = FStarC_TypeChecker_Env.push_bv e x in
          traverse f pol1 uu___6 q in
        comb2
          (fun l r3 ->
             let uu___6 = FStarC_Syntax_Util.mk_imp l r3 in
             uu___6.FStarC_Syntax_Syntax.n) r1 r2
    | FStarC_Syntax_Syntax.Tm_app
        {
          FStarC_Syntax_Syntax.hd =
            { 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;_};
          FStarC_Syntax_Syntax.args = (p, uu___4)::(q, uu___5)::[];_}
        when FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.iff_lid ->
        let xp = FStarC_Syntax_Syntax.new_bv FStar_Pervasives_Native.None p in
        let xq = FStarC_Syntax_Syntax.new_bv FStar_Pervasives_Native.None q in
        let r1 =
          let uu___6 = FStarC_TypeChecker_Env.push_bv e xq in
          traverse f Both uu___6 p in
        let r2 =
          let uu___6 = FStarC_TypeChecker_Env.push_bv e xp in
          traverse f Both uu___6 q in
        (match (r1, r2) with
         | (Unchanged uu___6, Unchanged uu___7) ->
             comb2
               (fun l r3 ->
                  let uu___8 = FStarC_Syntax_Util.mk_iff l r3 in
                  uu___8.FStarC_Syntax_Syntax.n) r1 r2
         | uu___6 ->
             let uu___7 = explode r1 in
             (match uu___7 with
              | (pn, pp, gs1) ->
                  let uu___8 = explode r2 in
                  (match uu___8 with
                   | (qn, qp, gs2) ->
                       let t1 =
                         let uu___9 = FStarC_Syntax_Util.mk_imp pn qp in
                         let uu___10 = FStarC_Syntax_Util.mk_imp qn pp in
                         FStarC_Syntax_Util.mk_conj uu___9 uu___10 in
                       Simplified
                         ((t1.FStarC_Syntax_Syntax.n),
                           (FStarC_List.op_At gs1 gs2)))))
    | FStarC_Syntax_Syntax.Tm_app
        { FStarC_Syntax_Syntax.hd = hd; FStarC_Syntax_Syntax.args = args;_}
        ->
        let r0 = traverse f pol1 e hd in
        let r1 =
          FStarC_List.fold_right
            (fun uu___1 r2 ->
               match uu___1 with
               | (a, q) ->
                   let r' = traverse f pol1 e a in
                   comb2 (fun a1 args1 -> (a1, q) :: args1) r' r2) args
            (tpure []) in
        comb2
          (fun hd1 args1 ->
             FStarC_Syntax_Syntax.Tm_app
               {
                 FStarC_Syntax_Syntax.hd = hd1;
                 FStarC_Syntax_Syntax.args = args1
               }) r0 r1
    | FStarC_Syntax_Syntax.Tm_abs
        { FStarC_Syntax_Syntax.bs = bs; FStarC_Syntax_Syntax.body = t1;
          FStarC_Syntax_Syntax.rc_opt = k;_}
        ->
        let uu___1 = FStarC_Syntax_Subst.open_term bs t1 in
        (match uu___1 with
         | (bs1, topen) ->
             let e' = FStarC_TypeChecker_Env.push_binders e bs1 in
             let r0 =
               FStarC_List.map
                 (fun b ->
                    let r1 =
                      traverse f (flip pol1) e
                        (b.FStarC_Syntax_Syntax.binder_bv).FStarC_Syntax_Syntax.sort in
                    let uu___2 =
                      comb1
                        (fun s' ->
                           {
                             FStarC_Syntax_Syntax.binder_bv =
                               (let uu___3 = b.FStarC_Syntax_Syntax.binder_bv in
                                {
                                  FStarC_Syntax_Syntax.ppname =
                                    (uu___3.FStarC_Syntax_Syntax.ppname);
                                  FStarC_Syntax_Syntax.index =
                                    (uu___3.FStarC_Syntax_Syntax.index);
                                  FStarC_Syntax_Syntax.sort = s'
                                });
                             FStarC_Syntax_Syntax.binder_qual =
                               (b.FStarC_Syntax_Syntax.binder_qual);
                             FStarC_Syntax_Syntax.binder_positivity =
                               (b.FStarC_Syntax_Syntax.binder_positivity);
                             FStarC_Syntax_Syntax.binder_attrs =
                               (b.FStarC_Syntax_Syntax.binder_attrs)
                           }) in
                    uu___2 r1) bs1 in
             let rbs = comb_list r0 in
             let rt = traverse f pol1 e' topen in
             comb2
               (fun bs2 t2 ->
                  let uu___2 = FStarC_Syntax_Util.abs bs2 t2 k in
                  uu___2.FStarC_Syntax_Syntax.n) rbs rt)
    | FStarC_Syntax_Syntax.Tm_ascribed
        { FStarC_Syntax_Syntax.tm = t1; FStarC_Syntax_Syntax.asc = asc;
          FStarC_Syntax_Syntax.eff_opt = ef;_}
        ->
        let uu___1 = traverse f pol1 e t1 in
        let uu___2 =
          comb1
            (fun t2 ->
               FStarC_Syntax_Syntax.Tm_ascribed
                 {
                   FStarC_Syntax_Syntax.tm = t2;
                   FStarC_Syntax_Syntax.asc = asc;
                   FStarC_Syntax_Syntax.eff_opt = ef
                 }) in
        uu___2 uu___1
    | FStarC_Syntax_Syntax.Tm_match
        { FStarC_Syntax_Syntax.scrutinee = sc;
          FStarC_Syntax_Syntax.ret_opt = asc_opt;
          FStarC_Syntax_Syntax.brs = brs;
          FStarC_Syntax_Syntax.rc_opt1 = lopt;_}
        ->
        let uu___1 = traverse f pol1 e sc in
        let uu___2 =
          let uu___3 =
            FStarC_List.map
              (fun br ->
                 let uu___4 = FStarC_Syntax_Subst.open_branch br in
                 match uu___4 with
                 | (pat, w, exp) ->
                     let bvs = FStarC_Syntax_Syntax.pat_bvs pat in
                     let e1 = FStarC_TypeChecker_Env.push_bvs e bvs in
                     let r1 = traverse f pol1 e1 exp in
                     let uu___5 =
                       comb1
                         (fun exp1 ->
                            FStarC_Syntax_Subst.close_branch (pat, w, exp1)) in
                     uu___5 r1) brs in
          comb_list uu___3 in
        comb2
          (fun sc1 brs1 ->
             FStarC_Syntax_Syntax.Tm_match
               {
                 FStarC_Syntax_Syntax.scrutinee = sc1;
                 FStarC_Syntax_Syntax.ret_opt = asc_opt;
                 FStarC_Syntax_Syntax.brs = brs1;
                 FStarC_Syntax_Syntax.rc_opt1 = lopt
               }) uu___1 uu___2
    | x -> tpure x in
  match r with
  | Unchanged tn' ->
      f pol1 e
        {
          FStarC_Syntax_Syntax.n = tn';
          FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
          FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
          FStarC_Syntax_Syntax.hash_code = (t.FStarC_Syntax_Syntax.hash_code)
        }
  | Simplified (tn', gs) ->
      let uu___ =
        f pol1 e
          {
            FStarC_Syntax_Syntax.n = tn';
            FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
            FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
            FStarC_Syntax_Syntax.hash_code =
              (t.FStarC_Syntax_Syntax.hash_code)
          } in
      emit gs uu___
  | Dual (tn, tp, gs) ->
      let rp =
        f pol1 e
          {
            FStarC_Syntax_Syntax.n = tp;
            FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
            FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
            FStarC_Syntax_Syntax.hash_code =
              (t.FStarC_Syntax_Syntax.hash_code)
          } in
      let uu___ = explode rp in
      (match uu___ with
       | (uu___1, p', gs') ->
           Dual
             ({
                FStarC_Syntax_Syntax.n = tn;
                FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
                FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
                FStarC_Syntax_Syntax.hash_code =
                  (t.FStarC_Syntax_Syntax.hash_code)
              }, p', (FStarC_List.op_At gs gs')))
let preprocess (env : FStarC_TypeChecker_Env.env)
  (goal : FStarC_Syntax_Syntax.term) :
  (Prims.bool * (FStarC_TypeChecker_Env.env * FStarC_Syntax_Syntax.term *
    FStarC_Options.optionstate) Prims.list)=
  FStarC_Errors.with_ctx "While preprocessing VC with a tactic"
    (fun uu___ ->
       (let uu___2 = FStarC_Effect.op_Bang dbg_Tac in
        if uu___2
        then
          let uu___3 =
            let uu___4 = FStarC_TypeChecker_Env.all_binders env in
            FStarC_Class_Show.show
              (FStarC_Class_Show.show_list
                 FStarC_Syntax_Print.showable_binder) uu___4 in
          let uu___4 =
            FStarC_Class_Show.show FStarC_Syntax_Print.showable_term goal in
          FStarC_Format.print2 "About to preprocess %s |= %s\n" uu___3 uu___4
        else ());
       (let initial = (Prims.int_one, []) in
        let uu___2 =
          let uu___3 = traverse by_tactic_interp Pos env goal in
          match uu___3 with
          | Unchanged t' -> (false, (t', []))
          | Simplified (t', gs) -> (true, (t', gs))
          | uu___4 ->
              failwith "preprocess: impossible, traverse returned a Dual" in
        match uu___2 with
        | (did_anything, (t', gs)) ->
            ((let uu___4 = FStarC_Effect.op_Bang dbg_Tac in
              if uu___4
              then
                let uu___5 =
                  let uu___6 = FStarC_TypeChecker_Env.all_binders env in
                  FStarC_Class_Show.show
                    (FStarC_Class_Show.show_list
                       FStarC_Syntax_Print.showable_binder) uu___6 in
                let uu___6 =
                  FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t' in
                FStarC_Format.print2 "Main goal simplified to: %s |- %s\n"
                  uu___5 uu___6
              else ());
             (let s = initial in
              let s1 =
                FStarC_List.fold_left
                  (fun uu___4 g ->
                     match uu___4 with
                     | (n, gs1) ->
                         let phi =
                           let uu___5 =
                             let uu___6 = FStarC_Tactics_Types.goal_env g in
                             let uu___7 = FStarC_Tactics_Types.goal_type g in
                             getprop uu___6 uu___7 in
                           match uu___5 with
                           | FStar_Pervasives_Native.None ->
                               let uu___6 =
                                 let uu___7 =
                                   let uu___8 =
                                     FStarC_Tactics_Types.goal_type g in
                                   FStarC_Class_Show.show
                                     FStarC_Syntax_Print.showable_term uu___8 in
                                 FStarC_Format.fmt1
                                   "Tactic returned proof-relevant goal: %s"
                                   uu___7 in
                               FStarC_Errors.raise_error
                                 FStarC_TypeChecker_Env.hasRange_env env
                                 FStarC_Errors_Codes.Fatal_TacticProofRelevantGoal
                                 ()
                                 (Obj.magic
                                    FStarC_Errors_Msg.is_error_message_string)
                                 (Obj.magic uu___6)
                           | FStar_Pervasives_Native.Some phi1 -> phi1 in
                         ((let uu___6 = FStarC_Effect.op_Bang dbg_Tac in
                           if uu___6
                           then
                             let uu___7 =
                               FStarC_Class_Show.show
                                 FStarC_Class_Show.showable_int n in
                             let uu___8 =
                               let uu___9 = FStarC_Tactics_Types.goal_type g in
                               FStarC_Class_Show.show
                                 FStarC_Syntax_Print.showable_term uu___9 in
                             FStarC_Format.print2 "Got goal #%s: %s\n" uu___7
                               uu___8
                           else ());
                          (let label =
                             let uu___6 =
                               let uu___7 =
                                 let uu___8 =
                                   FStarC_Class_PP.pp FStarC_Class_PP.pp_int
                                     n in
                                 let uu___9 =
                                   let uu___10 =
                                     let uu___11 =
                                       FStarC_Tactics_Types.get_label g in
                                     uu___11 = "" in
                                   if uu___10
                                   then FStar_Pprint.empty
                                   else
                                     (let uu___12 =
                                        let uu___13 =
                                          FStarC_Tactics_Types.get_label g in
                                        FStar_Pprint.doc_of_string uu___13 in
                                      FStar_Pprint.parens uu___12) in
                                 FStar_Pprint.op_Hat_Slash_Hat uu___8 uu___9 in
                               FStar_Pprint.op_Hat_Hat
                                 (FStar_Pprint.doc_of_string
                                    "Could not prove goal #") uu___7 in
                             [uu___6] in
                           let gt' =
                             let uu___6 = FStarC_Tactics_Types.goal_range g in
                             FStarC_TypeChecker_Util.label label uu___6 phi in
                           let uu___6 =
                             let uu___7 =
                               let uu___8 = FStarC_Tactics_Types.goal_env g in
                               let uu___9 = FStarC_Tactics_Types.goal_opts g in
                               (uu___8, gt', uu___9) in
                             uu___7 :: gs1 in
                           ((n + Prims.int_one), uu___6)))) s gs in
              let uu___4 = s1 in
              match uu___4 with
              | (uu___5, gs1) ->
                  let gs2 = FStarC_List.rev gs1 in
                  let uu___6 =
                    let uu___7 =
                      let uu___8 = FStarC_Options.peek () in
                      (env, t', uu___8) in
                    uu___7 :: gs2 in
                  (did_anything, uu___6)))))
let rec traverse_for_spinoff (pol1 : pol)
  (label_ctx :
    (FStar_Pprint.document Prims.list * FStarC_Range_Type.t)
      FStar_Pervasives_Native.option)
  (e : FStarC_TypeChecker_Env.env) (t : FStarC_Syntax_Syntax.term) : 
  tres=
  let debug_any = FStarC_Debug.any () in
  let traverse1 pol2 e1 t1 = traverse_for_spinoff pol2 label_ctx e1 t1 in
  let traverse_ctx pol2 ctx e1 t1 =
    let print_lc uu___ =
      match uu___ with
      | (msg, rng) ->
          let uu___1 = FStarC_Range_Ops.string_of_def_range rng in
          let uu___2 = FStarC_Range_Ops.string_of_use_range rng in
          let uu___3 = FStarC_Errors_Msg.rendermsg msg in
          FStarC_Format.fmt3 "(%s,%s) : %s" uu___1 uu___2 uu___3 in
    (let uu___1 = FStarC_Effect.op_Bang dbg_SpinoffAll in
     if uu___1
     then
       let uu___2 =
         match label_ctx with
         | FStar_Pervasives_Native.None -> "None"
         | FStar_Pervasives_Native.Some lc -> print_lc lc in
       let uu___3 = print_lc ctx in
       FStarC_Format.print2 "Changing label context from %s to %s" uu___2
         uu___3
     else ());
    traverse_for_spinoff pol2 (FStar_Pervasives_Native.Some ctx) e1 t1 in
  let should_descend t1 =
    let uu___ = FStarC_Syntax_Util.head_and_args t1 in
    match uu___ with
    | (hd, args) ->
        let res =
          let uu___1 =
            let uu___2 = FStarC_Syntax_Util.un_uinst hd in
            uu___2.FStarC_Syntax_Syntax.n in
          match uu___1 with
          | FStarC_Syntax_Syntax.Tm_fvar fv ->
              ((((FStarC_Syntax_Syntax.fv_eq_lid fv
                    FStarC_Parser_Const.and_lid)
                   ||
                   (FStarC_Syntax_Syntax.fv_eq_lid fv
                      FStarC_Parser_Const.imp_lid))
                  ||
                  (FStarC_Syntax_Syntax.fv_eq_lid fv
                     FStarC_Parser_Const.forall_lid))
                 ||
                 (FStarC_Syntax_Syntax.fv_eq_lid fv
                    FStarC_Parser_Const.auto_squash_lid))
                ||
                (FStarC_Syntax_Syntax.fv_eq_lid fv
                   FStarC_Parser_Const.squash_lid)
          | FStarC_Syntax_Syntax.Tm_meta uu___2 -> true
          | FStarC_Syntax_Syntax.Tm_ascribed uu___2 -> true
          | FStarC_Syntax_Syntax.Tm_abs uu___2 -> true
          | uu___2 -> false in
        res in
  let maybe_spinoff pol2 label_ctx1 e1 t1 =
    let label_goal uu___ =
      match uu___ with
      | (env, t2) ->
          let t3 =
            let uu___1 =
              let uu___2 =
                let uu___3 = FStarC_Syntax_Subst.compress t2 in
                uu___3.FStarC_Syntax_Syntax.n in
              (uu___2, label_ctx1) in
            match uu___1 with
            | (FStarC_Syntax_Syntax.Tm_meta
               { FStarC_Syntax_Syntax.tm2 = uu___2;
                 FStarC_Syntax_Syntax.meta =
                   FStarC_Syntax_Syntax.Meta_labeled uu___3;_},
               uu___4) -> t2
            | (uu___2, FStar_Pervasives_Native.Some (msg, r)) ->
                FStarC_TypeChecker_Util.label msg r t2
            | uu___2 -> t2 in
          let t4 =
            let uu___1 = FStarC_Syntax_Util.is_sub_singleton t3 in
            if uu___1
            then t3
            else
              FStarC_Syntax_Util.mk_auto_squash FStarC_Syntax_Syntax.U_zero
                t3 in
          let uu___1 = FStarC_Tactics_Types.goal_of_goal_ty env t4 in
          FStar_Pervasives_Native.fst uu___1 in
    let spinoff t2 =
      match pol2 with
      | StrictlyPositive ->
          ((let uu___1 = FStarC_Effect.op_Bang dbg_SpinoffAll in
            if uu___1
            then
              let uu___2 =
                FStarC_Class_Show.show FStarC_Syntax_Print.showable_term t2 in
              FStarC_Format.print1 "Spinning off %s\n" uu___2
            else ());
           (let uu___1 =
              let uu___2 = let uu___3 = label_goal (e1, t2) in [uu___3] in
              (FStarC_Syntax_Util.t_true, uu___2) in
            Simplified uu___1))
      | uu___ -> Unchanged t2 in
    let t2 = FStarC_Syntax_Subst.compress t1 in
    let uu___ = let uu___1 = should_descend t2 in Prims.op_Negation uu___1 in
    if uu___ then spinoff t2 else Unchanged t2 in
  let rewrite_boolean_conjunction t1 =
    let uu___ = FStarC_Syntax_Util.head_and_args t1 in
    match uu___ with
    | (hd, args) ->
        let uu___1 =
          let uu___2 =
            let uu___3 = FStarC_Syntax_Util.un_uinst hd in
            uu___3.FStarC_Syntax_Syntax.n in
          (uu___2, args) in
        (match uu___1 with
         | (FStarC_Syntax_Syntax.Tm_fvar fv, (t2, uu___2)::[]) when
             FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.b2t_lid ->
             let uu___3 = FStarC_Syntax_Util.head_and_args t2 in
             (match uu___3 with
              | (hd1, args1) ->
                  let uu___4 =
                    let uu___5 =
                      let uu___6 = FStarC_Syntax_Util.un_uinst hd1 in
                      uu___6.FStarC_Syntax_Syntax.n in
                    (uu___5, args1) in
                  (match uu___4 with
                   | (FStarC_Syntax_Syntax.Tm_fvar fv1,
                      (t0, uu___5)::(t11, uu___6)::[]) when
                       FStarC_Syntax_Syntax.fv_eq_lid fv1
                         FStarC_Parser_Const.op_And
                       ->
                       let t3 =
                         let uu___7 = FStarC_Syntax_Util.b2t t0 in
                         let uu___8 = FStarC_Syntax_Util.b2t t11 in
                         FStarC_Syntax_Util.mk_conj uu___7 uu___8 in
                       FStar_Pervasives_Native.Some t3
                   | uu___5 -> FStar_Pervasives_Native.None))
         | uu___2 -> FStar_Pervasives_Native.None) in
  let try_rewrite_match env t1 =
    let rec pat_as_exp env1 p =
      let uu___ = FStarC_TypeChecker_PatternUtils.raw_pat_as_exp env1 p in
      match uu___ with
      | FStar_Pervasives_Native.None -> FStar_Pervasives_Native.None
      | FStar_Pervasives_Native.Some (e1, uu___1) ->
          let uu___2 = FStarC_TypeChecker_Env.clear_expected_typ env1 in
          (match uu___2 with
           | (env2, uu___3) ->
               let uu___4 =
                 FStarC_TypeChecker_TcTerm.tc_trivial_guard
                   {
                     FStarC_TypeChecker_Env.solver =
                       (env2.FStarC_TypeChecker_Env.solver);
                     FStarC_TypeChecker_Env.range =
                       (env2.FStarC_TypeChecker_Env.range);
                     FStarC_TypeChecker_Env.curmodule =
                       (env2.FStarC_TypeChecker_Env.curmodule);
                     FStarC_TypeChecker_Env.gamma =
                       (env2.FStarC_TypeChecker_Env.gamma);
                     FStarC_TypeChecker_Env.gamma_sig =
                       (env2.FStarC_TypeChecker_Env.gamma_sig);
                     FStarC_TypeChecker_Env.gamma_cache =
                       (env2.FStarC_TypeChecker_Env.gamma_cache);
                     FStarC_TypeChecker_Env.modules =
                       (env2.FStarC_TypeChecker_Env.modules);
                     FStarC_TypeChecker_Env.expected_typ =
                       (env2.FStarC_TypeChecker_Env.expected_typ);
                     FStarC_TypeChecker_Env.sigtab =
                       (env2.FStarC_TypeChecker_Env.sigtab);
                     FStarC_TypeChecker_Env.attrtab =
                       (env2.FStarC_TypeChecker_Env.attrtab);
                     FStarC_TypeChecker_Env.instantiate_imp =
                       (env2.FStarC_TypeChecker_Env.instantiate_imp);
                     FStarC_TypeChecker_Env.effects =
                       (env2.FStarC_TypeChecker_Env.effects);
                     FStarC_TypeChecker_Env.generalize =
                       (env2.FStarC_TypeChecker_Env.generalize);
                     FStarC_TypeChecker_Env.letrecs =
                       (env2.FStarC_TypeChecker_Env.letrecs);
                     FStarC_TypeChecker_Env.top_level =
                       (env2.FStarC_TypeChecker_Env.top_level);
                     FStarC_TypeChecker_Env.check_uvars =
                       (env2.FStarC_TypeChecker_Env.check_uvars);
                     FStarC_TypeChecker_Env.use_eq_strict =
                       (env2.FStarC_TypeChecker_Env.use_eq_strict);
                     FStarC_TypeChecker_Env.is_iface =
                       (env2.FStarC_TypeChecker_Env.is_iface);
                     FStarC_TypeChecker_Env.admit = true;
                     FStarC_TypeChecker_Env.phase1 =
                       (env2.FStarC_TypeChecker_Env.phase1);
                     FStarC_TypeChecker_Env.failhard =
                       (env2.FStarC_TypeChecker_Env.failhard);
                     FStarC_TypeChecker_Env.flychecking =
                       (env2.FStarC_TypeChecker_Env.flychecking);
                     FStarC_TypeChecker_Env.uvar_subtyping =
                       (env2.FStarC_TypeChecker_Env.uvar_subtyping);
                     FStarC_TypeChecker_Env.intactics =
                       (env2.FStarC_TypeChecker_Env.intactics);
                     FStarC_TypeChecker_Env.nocoerce =
                       (env2.FStarC_TypeChecker_Env.nocoerce);
                     FStarC_TypeChecker_Env.tc_term =
                       (env2.FStarC_TypeChecker_Env.tc_term);
                     FStarC_TypeChecker_Env.typeof_tot_or_gtot_term =
                       (env2.FStarC_TypeChecker_Env.typeof_tot_or_gtot_term);
                     FStarC_TypeChecker_Env.universe_of =
                       (env2.FStarC_TypeChecker_Env.universe_of);
                     FStarC_TypeChecker_Env.typeof_well_typed_tot_or_gtot_term
                       =
                       (env2.FStarC_TypeChecker_Env.typeof_well_typed_tot_or_gtot_term);
                     FStarC_TypeChecker_Env.teq_nosmt_force =
                       (env2.FStarC_TypeChecker_Env.teq_nosmt_force);
                     FStarC_TypeChecker_Env.subtype_nosmt_force =
                       (env2.FStarC_TypeChecker_Env.subtype_nosmt_force);
                     FStarC_TypeChecker_Env.qtbl_name_and_index =
                       (env2.FStarC_TypeChecker_Env.qtbl_name_and_index);
                     FStarC_TypeChecker_Env.normalized_eff_names =
                       (env2.FStarC_TypeChecker_Env.normalized_eff_names);
                     FStarC_TypeChecker_Env.fv_delta_depths =
                       (env2.FStarC_TypeChecker_Env.fv_delta_depths);
                     FStarC_TypeChecker_Env.proof_ns =
                       (env2.FStarC_TypeChecker_Env.proof_ns);
                     FStarC_TypeChecker_Env.synth_hook =
                       (env2.FStarC_TypeChecker_Env.synth_hook);
                     FStarC_TypeChecker_Env.try_solve_implicits_hook =
                       (env2.FStarC_TypeChecker_Env.try_solve_implicits_hook);
                     FStarC_TypeChecker_Env.splice =
                       (env2.FStarC_TypeChecker_Env.splice);
                     FStarC_TypeChecker_Env.mpreprocess =
                       (env2.FStarC_TypeChecker_Env.mpreprocess);
                     FStarC_TypeChecker_Env.postprocess =
                       (env2.FStarC_TypeChecker_Env.postprocess);
                     FStarC_TypeChecker_Env.identifier_info =
                       (env2.FStarC_TypeChecker_Env.identifier_info);
                     FStarC_TypeChecker_Env.tc_hooks =
                       (env2.FStarC_TypeChecker_Env.tc_hooks);
                     FStarC_TypeChecker_Env.dsenv =
                       (env2.FStarC_TypeChecker_Env.dsenv);
                     FStarC_TypeChecker_Env.nbe =
                       (env2.FStarC_TypeChecker_Env.nbe);
                     FStarC_TypeChecker_Env.strict_args_tab =
                       (env2.FStarC_TypeChecker_Env.strict_args_tab);
                     FStarC_TypeChecker_Env.erasable_types_tab =
                       (env2.FStarC_TypeChecker_Env.erasable_types_tab);
                     FStarC_TypeChecker_Env.enable_defer_to_tac =
                       (env2.FStarC_TypeChecker_Env.enable_defer_to_tac);
                     FStarC_TypeChecker_Env.unif_allow_ref_guards =
                       (env2.FStarC_TypeChecker_Env.unif_allow_ref_guards);
                     FStarC_TypeChecker_Env.erase_erasable_args =
                       (env2.FStarC_TypeChecker_Env.erase_erasable_args);
                     FStarC_TypeChecker_Env.core_check =
                       (env2.FStarC_TypeChecker_Env.core_check);
                     FStarC_TypeChecker_Env.missing_decl =
                       (env2.FStarC_TypeChecker_Env.missing_decl)
                   } e1 in
               (match uu___4 with
                | (e2, lc) ->
                    let u =
                      FStarC_TypeChecker_TcTerm.universe_of env2
                        lc.FStarC_TypeChecker_Common.res_typ in
                    FStar_Pervasives_Native.Some
                      (e2, (lc.FStarC_TypeChecker_Common.res_typ), u))) in
    let bv_universes env1 bvs =
      FStarC_List.map
        (fun x ->
           let uu___ =
             FStarC_TypeChecker_TcTerm.universe_of env1
               x.FStarC_Syntax_Syntax.sort in
           (x, uu___)) bvs in
    let mk_forall_l bv_univs term =
      FStarC_List.fold_right
        (fun uu___ out ->
           match uu___ with | (x, u) -> FStarC_Syntax_Util.mk_forall u x out)
        bv_univs term in
    let mk_exists_l bv_univs term =
      FStarC_List.fold_right
        (fun uu___ out ->
           match uu___ with | (x, u) -> FStarC_Syntax_Util.mk_exists u x out)
        bv_univs term in
    if pol1 <> StrictlyPositive
    then FStar_Pervasives_Native.None
    else
      (let uu___1 =
         let uu___2 = FStarC_Syntax_Subst.compress t1 in
         uu___2.FStarC_Syntax_Syntax.n in
       match uu___1 with
       | FStarC_Syntax_Syntax.Tm_match
           { FStarC_Syntax_Syntax.scrutinee = sc;
             FStarC_Syntax_Syntax.ret_opt = asc_opt;
             FStarC_Syntax_Syntax.brs = brs;
             FStarC_Syntax_Syntax.rc_opt1 = lopt;_}
           ->
           let rec rewrite_branches path_condition branches =
             match branches with
             | [] ->
                 let uu___2 =
                   FStarC_Syntax_Util.mk_imp path_condition
                     FStarC_Syntax_Util.t_false in
                 FStar_Pervasives.Inr uu___2
             | br::branches1 ->
                 let uu___2 = FStarC_Syntax_Subst.open_branch br in
                 (match uu___2 with
                  | (pat, w, body) ->
                      (match w with
                       | FStar_Pervasives_Native.Some uu___3 ->
                           FStar_Pervasives.Inl "when clause"
                       | uu___3 ->
                           let bvs = FStarC_Syntax_Syntax.pat_bvs pat in
                           let env1 = FStarC_TypeChecker_Env.push_bvs env bvs in
                           let bvs_univs = bv_universes env1 bvs in
                           let uu___4 = pat_as_exp env1 pat in
                           (match uu___4 with
                            | FStar_Pervasives_Native.None ->
                                FStar_Pervasives.Inl "Ill-typed pattern"
                            | FStar_Pervasives_Native.Some (p_e, t2, u) ->
                                let eqn =
                                  FStarC_Syntax_Util.mk_eq2 u t2 sc p_e in
                                let branch_goal =
                                  let uu___5 =
                                    FStarC_Syntax_Util.mk_imp eqn body in
                                  mk_forall_l bvs_univs uu___5 in
                                let branch_goal1 =
                                  FStarC_Syntax_Util.mk_imp path_condition
                                    branch_goal in
                                let next_path_condition =
                                  let uu___5 =
                                    let uu___6 = mk_exists_l bvs_univs eqn in
                                    FStarC_Syntax_Util.mk_neg uu___6 in
                                  FStarC_Syntax_Util.mk_conj path_condition
                                    uu___5 in
                                let uu___5 =
                                  rewrite_branches next_path_condition
                                    branches1 in
                                (match uu___5 with
                                 | FStar_Pervasives.Inl msg ->
                                     FStar_Pervasives.Inl msg
                                 | FStar_Pervasives.Inr rest ->
                                     let uu___6 =
                                       FStarC_Syntax_Util.mk_conj
                                         branch_goal1 rest in
                                     FStar_Pervasives.Inr uu___6)))) in
           let res = rewrite_branches FStarC_Syntax_Util.t_true brs in
           (match res with
            | FStar_Pervasives.Inl msg ->
                (if debug_any
                 then
                   (let uu___3 = FStarC_TypeChecker_Env.get_range env in
                    let uu___4 =
                      let uu___5 =
                        FStarC_Class_Show.show
                          FStarC_Syntax_Print.showable_term t1 in
                      FStarC_Format.fmt2
                        "Failed to split match term because %s (%s)" msg
                        uu___5 in
                    FStarC_Errors.diag FStarC_Class_HasRange.hasRange_range
                      uu___3 ()
                      (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                      (Obj.magic uu___4))
                 else ();
                 FStar_Pervasives_Native.None)
            | FStar_Pervasives.Inr res1 ->
                (if debug_any
                 then
                   (let uu___3 = FStarC_TypeChecker_Env.get_range env in
                    let uu___4 =
                      let uu___5 =
                        FStarC_Class_Show.show
                          FStarC_Syntax_Print.showable_term t1 in
                      let uu___6 =
                        FStarC_Class_Show.show
                          FStarC_Syntax_Print.showable_term res1 in
                      FStarC_Format.fmt2 "Rewrote match term\n%s\ninto %s\n"
                        uu___5 uu___6 in
                    FStarC_Errors.diag FStarC_Class_HasRange.hasRange_range
                      uu___3 ()
                      (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                      (Obj.magic uu___4))
                 else ();
                 FStar_Pervasives_Native.Some res1))
       | uu___2 -> FStar_Pervasives_Native.None) in
  let maybe_rewrite_term t1 =
    if pol1 <> StrictlyPositive
    then FStar_Pervasives_Native.None
    else
      (let uu___1 = rewrite_boolean_conjunction t1 in
       match uu___1 with
       | FStar_Pervasives_Native.Some t2 -> FStar_Pervasives_Native.Some t2
       | FStar_Pervasives_Native.None -> try_rewrite_match e t1) in
  let uu___ = maybe_rewrite_term t in
  match uu___ with
  | FStar_Pervasives_Native.Some t1 -> traverse1 pol1 e t1
  | uu___1 ->
      let r =
        let t1 = FStarC_Syntax_Subst.compress t in
        let uu___2 =
          let uu___3 = should_descend t1 in Prims.op_Negation uu___3 in
        if uu___2
        then tpure t1.FStarC_Syntax_Syntax.n
        else
          (match t1.FStarC_Syntax_Syntax.n with
           | FStarC_Syntax_Syntax.Tm_uinst (t2, us) ->
               let tr = traverse1 pol1 e t2 in
               let uu___4 =
                 comb1 (fun t' -> FStarC_Syntax_Syntax.Tm_uinst (t', us)) in
               uu___4 tr
           | FStarC_Syntax_Syntax.Tm_meta
               { FStarC_Syntax_Syntax.tm2 = t2;
                 FStarC_Syntax_Syntax.meta =
                   FStarC_Syntax_Syntax.Meta_labeled (msg, r1, uu___4);_}
               ->
               let tr = traverse_ctx pol1 (msg, r1) e t2 in
               let uu___5 =
                 comb1
                   (fun t' ->
                      FStarC_Syntax_Syntax.Tm_meta
                        {
                          FStarC_Syntax_Syntax.tm2 = t';
                          FStarC_Syntax_Syntax.meta =
                            (FStarC_Syntax_Syntax.Meta_labeled
                               (msg, r1, false))
                        }) in
               uu___5 tr
           | FStarC_Syntax_Syntax.Tm_meta
               { FStarC_Syntax_Syntax.tm2 = t2;
                 FStarC_Syntax_Syntax.meta = m;_}
               ->
               let tr = traverse1 pol1 e t2 in
               let uu___4 =
                 comb1
                   (fun t' ->
                      FStarC_Syntax_Syntax.Tm_meta
                        {
                          FStarC_Syntax_Syntax.tm2 = t';
                          FStarC_Syntax_Syntax.meta = m
                        }) in
               uu___4 tr
           | FStarC_Syntax_Syntax.Tm_ascribed
               { FStarC_Syntax_Syntax.tm = t2;
                 FStarC_Syntax_Syntax.asc = asc;
                 FStarC_Syntax_Syntax.eff_opt = ef;_}
               ->
               let uu___4 = traverse1 pol1 e t2 in
               let uu___5 =
                 comb1
                   (fun t3 ->
                      FStarC_Syntax_Syntax.Tm_ascribed
                        {
                          FStarC_Syntax_Syntax.tm = t3;
                          FStarC_Syntax_Syntax.asc = asc;
                          FStarC_Syntax_Syntax.eff_opt = ef
                        }) in
               uu___5 uu___4
           | FStarC_Syntax_Syntax.Tm_app
               {
                 FStarC_Syntax_Syntax.hd =
                   {
                     FStarC_Syntax_Syntax.n = FStarC_Syntax_Syntax.Tm_fvar fv;
                     FStarC_Syntax_Syntax.pos = uu___4;
                     FStarC_Syntax_Syntax.vars = uu___5;
                     FStarC_Syntax_Syntax.hash_code = uu___6;_};
                 FStarC_Syntax_Syntax.args = (p, uu___7)::(q, uu___8)::[];_}
               when
               FStarC_Syntax_Syntax.fv_eq_lid fv FStarC_Parser_Const.imp_lid
               ->
               let x =
                 FStarC_Syntax_Syntax.new_bv FStar_Pervasives_Native.None p in
               let r1 = traverse1 (flip pol1) e p in
               let r2 =
                 let uu___9 = FStarC_TypeChecker_Env.push_bv e x in
                 traverse1 pol1 uu___9 q in
               comb2
                 (fun l r3 ->
                    let uu___9 = FStarC_Syntax_Util.mk_imp l r3 in
                    uu___9.FStarC_Syntax_Syntax.n) r1 r2
           | FStarC_Syntax_Syntax.Tm_app
               { FStarC_Syntax_Syntax.hd = hd;
                 FStarC_Syntax_Syntax.args = args;_}
               ->
               let uu___4 =
                 let uu___5 =
                   let uu___6 = FStarC_Syntax_Util.un_uinst hd in
                   uu___6.FStarC_Syntax_Syntax.n in
                 (uu___5, args) in
               (match uu___4 with
                | (FStarC_Syntax_Syntax.Tm_fvar fv,
                   (t2, FStar_Pervasives_Native.Some aq0)::(body, aq)::[])
                    when
                    ((FStarC_Syntax_Syntax.fv_eq_lid fv
                        FStarC_Parser_Const.forall_lid)
                       ||
                       (FStarC_Syntax_Syntax.fv_eq_lid fv
                          FStarC_Parser_Const.exists_lid))
                      && aq0.FStarC_Syntax_Syntax.aqual_implicit
                    ->
                    let r0 = traverse1 pol1 e hd in
                    let rt = traverse1 (flip pol1) e t2 in
                    let rbody = traverse1 pol1 e body in
                    let rargs =
                      comb2
                        (fun t3 body1 ->
                           [(t3, (FStar_Pervasives_Native.Some aq0));
                           (body1, aq)]) rt rbody in
                    comb2
                      (fun hd1 args1 ->
                         FStarC_Syntax_Syntax.Tm_app
                           {
                             FStarC_Syntax_Syntax.hd = hd1;
                             FStarC_Syntax_Syntax.args = args1
                           }) r0 rargs
                | uu___5 ->
                    let r0 = traverse1 pol1 e hd in
                    let r1 =
                      FStarC_List.fold_right
                        (fun uu___6 r2 ->
                           match uu___6 with
                           | (a, q) ->
                               let r' = traverse1 pol1 e a in
                               comb2 (fun a1 args1 -> (a1, q) :: args1) r' r2)
                        args (tpure []) in
                    let simplified =
                      (uu___is_Simplified r0) || (uu___is_Simplified r1) in
                    comb2
                      (fun hd1 args1 ->
                         let uu___6 =
                           let uu___7 =
                             let uu___8 = FStarC_Syntax_Util.un_uinst hd1 in
                             uu___8.FStarC_Syntax_Syntax.n in
                           (uu___7, args1) in
                         match uu___6 with
                         | (FStarC_Syntax_Syntax.Tm_fvar fv,
                            (t2, uu___7)::[]) when
                             (simplified &&
                                (FStarC_Syntax_Syntax.fv_eq_lid fv
                                   FStarC_Parser_Const.squash_lid))
                               &&
                               (let uu___8 =
                                  FStarC_TypeChecker_TermEqAndSimplify.eq_tm
                                    e t2 FStarC_Syntax_Util.t_true in
                                uu___8 =
                                  FStarC_TypeChecker_TermEqAndSimplify.Equal)
                             ->
                             ((let uu___9 =
                                 FStarC_Effect.op_Bang dbg_SpinoffAll in
                               if uu___9
                               then
                                 FStarC_Format.print_string
                                   "Simplified squash True to True"
                               else ());
                              FStarC_Syntax_Util.t_true.FStarC_Syntax_Syntax.n)
                         | uu___7 ->
                             let t' =
                               FStarC_Syntax_Syntax.Tm_app
                                 {
                                   FStarC_Syntax_Syntax.hd = hd1;
                                   FStarC_Syntax_Syntax.args = args1
                                 } in
                             t') r0 r1)
           | FStarC_Syntax_Syntax.Tm_abs
               { FStarC_Syntax_Syntax.bs = bs;
                 FStarC_Syntax_Syntax.body = t2;
                 FStarC_Syntax_Syntax.rc_opt = k;_}
               ->
               let uu___4 = FStarC_Syntax_Subst.open_term bs t2 in
               (match uu___4 with
                | (bs1, topen) ->
                    let e' = FStarC_TypeChecker_Env.push_binders e bs1 in
                    let r0 =
                      FStarC_List.map
                        (fun b ->
                           let r1 =
                             traverse1 (flip pol1) e
                               (b.FStarC_Syntax_Syntax.binder_bv).FStarC_Syntax_Syntax.sort in
                           let uu___5 =
                             comb1
                               (fun s' ->
                                  {
                                    FStarC_Syntax_Syntax.binder_bv =
                                      (let uu___6 =
                                         b.FStarC_Syntax_Syntax.binder_bv in
                                       {
                                         FStarC_Syntax_Syntax.ppname =
                                           (uu___6.FStarC_Syntax_Syntax.ppname);
                                         FStarC_Syntax_Syntax.index =
                                           (uu___6.FStarC_Syntax_Syntax.index);
                                         FStarC_Syntax_Syntax.sort = s'
                                       });
                                    FStarC_Syntax_Syntax.binder_qual =
                                      (b.FStarC_Syntax_Syntax.binder_qual);
                                    FStarC_Syntax_Syntax.binder_positivity =
                                      (b.FStarC_Syntax_Syntax.binder_positivity);
                                    FStarC_Syntax_Syntax.binder_attrs =
                                      (b.FStarC_Syntax_Syntax.binder_attrs)
                                  }) in
                           uu___5 r1) bs1 in
                    let rbs = comb_list r0 in
                    let rt = traverse1 pol1 e' topen in
                    comb2
                      (fun bs2 t3 ->
                         let uu___5 = FStarC_Syntax_Util.abs bs2 t3 k in
                         uu___5.FStarC_Syntax_Syntax.n) rbs rt)
           | x -> tpure x) in
      (match r with
       | Unchanged tn' ->
           maybe_spinoff pol1 label_ctx e
             {
               FStarC_Syntax_Syntax.n = tn';
               FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
               FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
               FStarC_Syntax_Syntax.hash_code =
                 (t.FStarC_Syntax_Syntax.hash_code)
             }
       | Simplified (tn', gs) ->
           let uu___2 =
             maybe_spinoff pol1 label_ctx e
               {
                 FStarC_Syntax_Syntax.n = tn';
                 FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
                 FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
                 FStarC_Syntax_Syntax.hash_code =
                   (t.FStarC_Syntax_Syntax.hash_code)
               } in
           emit gs uu___2
       | Dual (tn, tp, gs) ->
           let rp =
             maybe_spinoff pol1 label_ctx e
               {
                 FStarC_Syntax_Syntax.n = tp;
                 FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
                 FStarC_Syntax_Syntax.vars = (t.FStarC_Syntax_Syntax.vars);
                 FStarC_Syntax_Syntax.hash_code =
                   (t.FStarC_Syntax_Syntax.hash_code)
               } in
           let uu___2 = explode rp in
           (match uu___2 with
            | (uu___3, p', gs') ->
                Dual
                  ({
                     FStarC_Syntax_Syntax.n = tn;
                     FStarC_Syntax_Syntax.pos = (t.FStarC_Syntax_Syntax.pos);
                     FStarC_Syntax_Syntax.vars =
                       (t.FStarC_Syntax_Syntax.vars);
                     FStarC_Syntax_Syntax.hash_code =
                       (t.FStarC_Syntax_Syntax.hash_code)
                   }, p', (FStarC_List.op_At gs gs'))))
let pol_to_string (uu___ : pol) : Prims.string=
  match uu___ with
  | StrictlyPositive -> "StrictlyPositive"
  | Pos -> "Positive"
  | Neg -> "Negative"
  | Both -> "Both"
let spinoff_strictly_positive_goals (env : FStarC_TypeChecker_Env.env)
  (goal : FStarC_Syntax_Syntax.term) :
  (FStarC_TypeChecker_Env.env * FStarC_Syntax_Syntax.term) Prims.list=
  (let uu___1 = FStarC_Effect.op_Bang dbg_SpinoffAll in
   if uu___1
   then
     let uu___2 =
       FStarC_Class_Show.show FStarC_Syntax_Print.showable_term goal in
     FStarC_Format.print1 "spinoff_all called with %s\n" uu___2
   else ());
  FStarC_Errors.with_ctx "While spinning off all goals"
    (fun uu___1 ->
       let initial = (Prims.int_one, []) in
       let uu___2 =
         let uu___3 =
           traverse_for_spinoff StrictlyPositive FStar_Pervasives_Native.None
             env goal in
         match uu___3 with
         | Unchanged t' -> (t', [])
         | Simplified (t', gs) -> (t', gs)
         | uu___4 ->
             failwith "preprocess: impossible, traverse returned a Dual" in
       match uu___2 with
       | (t', gs) ->
           let t'1 =
             FStarC_TypeChecker_Normalize.normalize
               [FStarC_TypeChecker_Env.Eager_unfolding;
               FStarC_TypeChecker_Env.Simplify;
               FStarC_TypeChecker_Env.Primops] env t' in
           let main_goal =
             let t = FStarC_TypeChecker_Common.check_trivial t'1 in
             match t with
             | FStarC_TypeChecker_Common.Trivial -> []
             | FStarC_TypeChecker_Common.NonTrivial t1 ->
                 ((let uu___4 = FStarC_Effect.op_Bang dbg_SpinoffAll in
                   if uu___4
                   then
                     let msg =
                       let uu___5 =
                         let uu___6 = FStarC_TypeChecker_Env.all_binders env in
                         FStarC_Class_Show.show
                           (FStarC_Class_Show.show_list
                              FStarC_Syntax_Print.showable_binder) uu___6 in
                       let uu___6 =
                         FStarC_Class_Show.show
                           FStarC_Syntax_Print.showable_term t1 in
                       FStarC_Format.fmt2
                         "Main goal simplified to: %s |- %s\n" uu___5 uu___6 in
                     let uu___5 = FStarC_TypeChecker_Env.get_range env in
                     let uu___6 =
                       FStarC_Format.fmt1
                         "Verification condition was to be split into several atomic sub-goals, but this query had some sub-goals that couldn't be split---the error report, if any, may be inaccurate.\n%s\n"
                         msg in
                     FStarC_Errors.diag FStarC_Class_HasRange.hasRange_range
                       uu___5 ()
                       (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                       (Obj.magic uu___6)
                   else ());
                  [(env, t1)]) in
           let s = initial in
           let s1 =
             FStarC_List.fold_left
               (fun uu___3 g ->
                  match uu___3 with
                  | (n, gs1) ->
                      let phi = FStarC_Tactics_Types.goal_type g in
                      let uu___4 =
                        let uu___5 =
                          let uu___6 = FStarC_Tactics_Types.goal_env g in
                          (uu___6, phi) in
                        uu___5 :: gs1 in
                      ((n + Prims.int_one), uu___4)) s gs in
           let uu___3 = s1 in
           (match uu___3 with
            | (uu___4, gs1) ->
                let gs2 = FStarC_List.rev gs1 in
                let gs3 =
                  FStarC_List.filter_map
                    (fun uu___5 ->
                       match uu___5 with
                       | (env1, t) ->
                           let t1 =
                             FStarC_TypeChecker_Normalize.normalize
                               [FStarC_TypeChecker_Env.Eager_unfolding;
                               FStarC_TypeChecker_Env.Simplify;
                               FStarC_TypeChecker_Env.Primops] env1 t in
                           let uu___6 =
                             FStarC_TypeChecker_Common.check_trivial t1 in
                           (match uu___6 with
                            | FStarC_TypeChecker_Common.Trivial ->
                                FStar_Pervasives_Native.None
                            | FStarC_TypeChecker_Common.NonTrivial t2 ->
                                ((let uu___8 =
                                    FStarC_Effect.op_Bang dbg_SpinoffAll in
                                  if uu___8
                                  then
                                    let uu___9 =
                                      FStarC_Class_Show.show
                                        FStarC_Syntax_Print.showable_term t2 in
                                    FStarC_Format.print1 "Got goal: %s\n"
                                      uu___9
                                  else ());
                                 FStar_Pervasives_Native.Some (env1, t2))))
                    gs2 in
                ((let uu___6 = FStarC_Effect.op_Bang dbg_Tac in
                  if uu___6
                  then
                    let uu___7 = FStarC_TypeChecker_Env.get_range env in
                    let uu___8 =
                      let uu___9 =
                        FStarC_Class_Show.show FStarC_Class_Show.showable_nat
                          (FStarC_List.length gs3) in
                      FStarC_Format.fmt1 "Split query into %s sub-goals"
                        uu___9 in
                    FStarC_Errors.diag FStarC_Class_HasRange.hasRange_range
                      uu___7 ()
                      (Obj.magic FStarC_Errors_Msg.is_error_message_string)
                      (Obj.magic uu___8)
                  else ());
                 FStarC_List.op_At main_goal gs3)))
let synthesize (env : FStarC_TypeChecker_Env.env)
  (typ : FStarC_Syntax_Syntax.typ) (tau : FStarC_Syntax_Syntax.term)
  (rng : FStarC_Range_Type.range) : FStarC_Syntax_Syntax.term=
  FStarC_Errors.with_ctx "While synthesizing term with a tactic"
    (fun uu___ ->
       if env.FStarC_TypeChecker_Env.flychecking
       then
         let uu___1 =
           FStarC_TypeChecker_Util.fvar_env env FStarC_Parser_Const.magic_lid in
         let uu___2 =
           let uu___3 =
             FStarC_Syntax_Syntax.as_arg FStarC_Syntax_Util.exp_unit in
           [uu___3] in
         FStarC_Syntax_Syntax.mk_Tm_app uu___1 uu___2
           typ.FStarC_Syntax_Syntax.pos
       else
         (let uu___2 =
            run_tactic_on_typ tau.FStarC_Syntax_Syntax.pos rng tau env typ in
          match uu___2 with
          | (gs, w) ->
              (FStarC_List.iter
                 (fun g ->
                    let uu___4 =
                      let uu___5 = FStarC_Tactics_Types.goal_env g in
                      let uu___6 = FStarC_Tactics_Types.goal_type g in
                      getprop uu___5 uu___6 in
                    match uu___4 with
                    | FStar_Pervasives_Native.Some vc ->
                        ((let uu___6 = FStarC_Effect.op_Bang dbg_Tac in
                          if uu___6
                          then
                            let uu___7 =
                              FStarC_Class_Show.show
                                FStarC_Syntax_Print.showable_term vc in
                            FStarC_Format.print1
                              "Synthesis left a goal: %s\n" uu___7
                          else ());
                         (let guard =
                            FStarC_TypeChecker_Env.guard_of_guard_formula
                              (FStarC_TypeChecker_Common.NonTrivial vc) in
                          let uu___6 = FStarC_Tactics_Types.goal_env g in
                          FStarC_TypeChecker_Rel.force_trivial_guard uu___6
                            guard))
                    | FStar_Pervasives_Native.None ->
                        FStarC_Errors.raise_error
                          (FStarC_Syntax_Syntax.has_range_syntax ()) typ
                          FStarC_Errors_Codes.Fatal_OpenGoalsInSynthesis ()
                          (Obj.magic
                             FStarC_Errors_Msg.is_error_message_string)
                          (Obj.magic "synthesis left open goals")) gs;
               w)))
let solve_implicits (env : FStarC_TypeChecker_Env.env)
  (tau : FStarC_Syntax_Syntax.term) (imps : FStarC_TypeChecker_Env.implicits)
  : unit=
  FStarC_Errors.with_ctx "While solving implicits with a tactic"
    (fun uu___ ->
       if env.FStarC_TypeChecker_Env.flychecking
       then ()
       else
         (let gs =
            let uu___2 = FStarC_TypeChecker_Env.get_range env in
            run_tactic_on_all_implicits tau.FStarC_Syntax_Syntax.pos uu___2
              tau env imps in
          (let uu___3 =
             FStarC_Options.profile_enabled FStar_Pervasives_Native.None
               "FStarC.TypeChecker" in
           if uu___3
           then
             let uu___4 =
               FStarC_Class_Show.show FStarC_Class_Show.showable_nat
                 (FStarC_List.length gs) in
             FStarC_Format.print1 "solve_implicits produced %s goals\n"
               uu___4
           else ());
          FStarC_Options.with_saved_options
            (fun uu___3 ->
               let uu___4 = FStarC_Options.set_options "--no_tactics" in
               FStarC_List.iter
                 (fun g ->
                    (let uu___6 = FStarC_Tactics_Types.goal_opts g in
                     FStarC_Options.set uu___6);
                    (let uu___6 =
                       let uu___7 = FStarC_Tactics_Types.goal_env g in
                       let uu___8 = FStarC_Tactics_Types.goal_type g in
                       getprop uu___7 uu___8 in
                     match uu___6 with
                     | FStar_Pervasives_Native.Some vc ->
                         ((let uu___8 = FStarC_Effect.op_Bang dbg_Tac in
                           if uu___8
                           then
                             let uu___9 =
                               FStarC_Class_Show.show
                                 FStarC_Syntax_Print.showable_term vc in
                             FStarC_Format.print1
                               "Synthesis left a goal: %s\n" uu___9
                           else ());
                          if
                            Prims.op_Negation
                              env.FStarC_TypeChecker_Env.admit
                          then
                            (let guard =
                               FStarC_TypeChecker_Env.guard_of_guard_formula
                                 (FStarC_TypeChecker_Common.NonTrivial vc) in
                             FStarC_Profiling.profile
                               (fun uu___8 ->
                                  let uu___9 =
                                    FStarC_Tactics_Types.goal_env g in
                                  FStarC_TypeChecker_Rel.force_trivial_guard
                                    uu___9 guard)
                               FStar_Pervasives_Native.None
                               "FStarC.TypeChecker.Hooks.force_trivial_guard")
                          else ())
                     | FStar_Pervasives_Native.None ->
                         FStarC_Errors.raise_error
                           FStarC_TypeChecker_Env.hasRange_env env
                           FStarC_Errors_Codes.Fatal_OpenGoalsInSynthesis ()
                           (Obj.magic
                              FStarC_Errors_Msg.is_error_message_string)
                           (Obj.magic "synthesis left open goals"))) gs)))
let find_user_tac_for_attr (env : FStarC_TypeChecker_Env.env)
  (a : FStarC_Syntax_Syntax.term) :
  FStarC_Syntax_Syntax.sigelt FStar_Pervasives_Native.option=
  let hooks =
    let uu___ =
      FStarC_Ident.string_of_lid FStarC_Parser_Const.handle_smt_goals_attr in
    FStarC_TypeChecker_Env.lookup_attr env uu___ in
  FStarC_Util.try_find (fun uu___ -> true) hooks
let handle_smt_goal (env : FStarC_TypeChecker_Env.env)
  (goal : FStarC_TypeChecker_Env.goal) :
  (FStarC_TypeChecker_Env.env * FStarC_Syntax_Syntax.term) Prims.list=
  let uu___ = FStarC_TypeChecker_Common.check_trivial goal in
  match uu___ with
  | FStarC_TypeChecker_Common.Trivial -> [(env, goal)]
  | FStarC_TypeChecker_Common.NonTrivial goal1 ->
      let uu___1 =
        let uu___2 =
          FStarC_Syntax_Syntax.tconst
            FStarC_Parser_Const.handle_smt_goals_attr in
        find_user_tac_for_attr env uu___2 in
      (match uu___1 with
       | FStar_Pervasives_Native.Some tac ->
           let tau =
             match tac.FStarC_Syntax_Syntax.sigel with
             | FStarC_Syntax_Syntax.Sig_let
                 { FStarC_Syntax_Syntax.lbs1 = uu___2;
                   FStarC_Syntax_Syntax.lids1 = lid::[];_}
                 ->
                 let qn = FStarC_TypeChecker_Env.lookup_qname env lid in
                 let fv =
                   FStarC_Syntax_Syntax.lid_as_fv lid
                     FStar_Pervasives_Native.None in
                 let uu___3 =
                   FStarC_Syntax_Syntax.lid_as_fv lid
                     FStar_Pervasives_Native.None in
                 FStarC_Syntax_Syntax.fv_to_tm uu___3
             | uu___2 -> failwith "Resolve_tac not found" in
           let gs =
             FStarC_Errors.with_ctx
               "While handling an SMT goal with a tactic"
               (fun uu___2 ->
                  let uu___3 =
                    let uu___4 = FStarC_TypeChecker_Env.get_range env in
                    let uu___5 =
                      FStarC_Syntax_Util.mk_squash
                        FStarC_Syntax_Syntax.U_zero goal1 in
                    run_tactic_on_typ tau.FStarC_Syntax_Syntax.pos uu___4 tau
                      env uu___5 in
                  match uu___3 with
                  | (gs1, uu___4) ->
                      FStarC_List.map
                        (fun g ->
                           let uu___5 =
                             let uu___6 = FStarC_Tactics_Types.goal_env g in
                             let uu___7 = FStarC_Tactics_Types.goal_type g in
                             getprop uu___6 uu___7 in
                           match uu___5 with
                           | FStar_Pervasives_Native.Some vc ->
                               ((let uu___7 = FStarC_Effect.op_Bang dbg_Tac in
                                 if uu___7
                                 then
                                   let uu___8 =
                                     FStarC_Class_Show.show
                                       FStarC_Syntax_Print.showable_term vc in
                                   FStarC_Format.print1
                                     "handle_smt_goals left a goal: %s\n"
                                     uu___8
                                 else ());
                                (let uu___7 = FStarC_Tactics_Types.goal_env g in
                                 (uu___7, vc)))
                           | FStar_Pervasives_Native.None ->
                               FStarC_Errors.raise_error
                                 FStarC_TypeChecker_Env.hasRange_env env
                                 FStarC_Errors_Codes.Fatal_OpenGoalsInSynthesis
                                 ()
                                 (Obj.magic
                                    FStarC_Errors_Msg.is_error_message_string)
                                 (Obj.magic
                                    "Handling an SMT goal by tactic left non-prop open goals"))
                        gs1) in
           gs
       | FStar_Pervasives_Native.None -> [(env, goal1)])
let uu___0 :
  FStarC_Syntax_Syntax.term FStarC_Syntax_Embeddings_Base.embedding=
  FStarC_Reflection_V2_Embeddings.e_term
type blob_t =
  (Prims.string * FStarC_Syntax_Syntax.term) FStar_Pervasives_Native.option
type dsl_typed_sigelt_t = (Prims.bool * FStarC_Syntax_Syntax.sigelt * blob_t)
type dsl_tac_result_t =
  (dsl_typed_sigelt_t Prims.list * dsl_typed_sigelt_t * dsl_typed_sigelt_t
    Prims.list)
let rec us_equals (us : FStarC_Syntax_Syntax.univ_name Prims.list)
  (vs : FStarC_Syntax_Syntax.univ_name Prims.list) : Prims.bool=
  match (us, vs) with
  | (u::us1, v::vs1) ->
      let uu___ = FStarC_Ident.ident_equals u v in
      if uu___ then us_equals us1 vs1 else false
  | uu___ -> true
let splice : FStarC_TypeChecker_Env.splice_t=
  fun env quals attrs is_typed lids tau rng ->
    FStarC_Errors.with_ctx "While running splice with a tactic"
      (fun uu___ ->
         if env.FStarC_TypeChecker_Env.flychecking
         then []
         else
           (let uu___2 =
              if is_typed
              then
                FStarC_TypeChecker_TcTerm.tc_check_tot_or_gtot_term env tau
                  FStarC_Syntax_Util.t_dsl_tac_typ
                  FStar_Pervasives_Native.None
              else
                FStarC_TypeChecker_TcTerm.tc_tactic
                  FStarC_Syntax_Syntax.t_unit FStarC_Syntax_Syntax.t_decls
                  env tau in
            match uu___2 with
            | (tau1, uu___3, g) ->
                (FStarC_TypeChecker_Rel.force_trivial_guard env g;
                 (let ps =
                    FStarC_Tactics_V2_Basic.proofstate_of_goals
                      tau1.FStarC_Syntax_Syntax.pos env [] [] in
                  let ps1 =
                    {
                      FStarC_Tactics_Types.main_context =
                        (ps.FStarC_Tactics_Types.main_context);
                      FStarC_Tactics_Types.all_implicits =
                        (ps.FStarC_Tactics_Types.all_implicits);
                      FStarC_Tactics_Types.goals =
                        (ps.FStarC_Tactics_Types.goals);
                      FStarC_Tactics_Types.smt_goals =
                        (ps.FStarC_Tactics_Types.smt_goals);
                      FStarC_Tactics_Types.splice_quals = quals;
                      FStarC_Tactics_Types.splice_attrs = attrs;
                      FStarC_Tactics_Types.depth =
                        (ps.FStarC_Tactics_Types.depth);
                      FStarC_Tactics_Types.__dump =
                        (ps.FStarC_Tactics_Types.__dump);
                      FStarC_Tactics_Types.psc =
                        (ps.FStarC_Tactics_Types.psc);
                      FStarC_Tactics_Types.entry_range =
                        (ps.FStarC_Tactics_Types.entry_range);
                      FStarC_Tactics_Types.guard_policy =
                        (ps.FStarC_Tactics_Types.guard_policy);
                      FStarC_Tactics_Types.freshness =
                        (ps.FStarC_Tactics_Types.freshness);
                      FStarC_Tactics_Types.tac_verb_dbg =
                        (ps.FStarC_Tactics_Types.tac_verb_dbg);
                      FStarC_Tactics_Types.local_state =
                        (ps.FStarC_Tactics_Types.local_state);
                      FStarC_Tactics_Types.urgency =
                        (ps.FStarC_Tactics_Types.urgency);
                      FStarC_Tactics_Types.dump_on_failure =
                        (ps.FStarC_Tactics_Types.dump_on_failure)
                    } in
                  let tactic_already_typed = true in
                  let uu___5 =
                    if is_typed
                    then
                      (if (FStarC_List.length lids) > Prims.int_one
                       then
                         let uu___6 =
                           let uu___7 =
                             FStarC_Class_Show.show
                               (FStarC_Class_Show.show_list
                                  FStarC_Ident.showable_lident) lids in
                           FStarC_Format.fmt1
                             "Typed splice: unexpected lids length (> 1) (%s)"
                             uu___7 in
                         FStarC_Errors.raise_error
                           FStarC_Class_HasRange.hasRange_range rng
                           FStarC_Errors_Codes.Error_BadSplice ()
                           (Obj.magic
                              FStarC_Errors_Msg.is_error_message_string)
                           (Obj.magic uu___6)
                       else
                         (let uu___7 =
                            if (FStarC_List.length lids) = Prims.int_zero
                            then
                              (FStar_Pervasives_Native.None,
                                FStar_Pervasives_Native.None)
                            else
                              (let uu___9 =
                                 let uu___10 = FStarC_List.hd lids in
                                 FStarC_TypeChecker_Env.try_lookup_val_decl
                                   env uu___10 in
                               match uu___9 with
                               | FStar_Pervasives_Native.None ->
                                   (FStar_Pervasives_Native.None,
                                     FStar_Pervasives_Native.None)
                               | FStar_Pervasives_Native.Some
                                   ((uvs, tval), uu___10) ->
                                   let uu___11 =
                                     FStarC_Syntax_Subst.open_univ_vars uvs
                                       tval in
                                   (match uu___11 with
                                    | (uvs1, tval1) ->
                                        ((FStar_Pervasives_Native.Some tval1),
                                          (FStar_Pervasives_Native.Some uvs1)))) in
                          match uu___7 with
                          | (val_t, uv_t) ->
                              let uu___8 = uu___7 in
                              let uu___9 =
                                FStarC_Tactics_Interpreter.run_tactic_on_ps
                                  tau1.FStarC_Syntax_Syntax.pos
                                  tau1.FStarC_Syntax_Syntax.pos false
                                  (FStarC_Syntax_Embeddings.e_tuple2
                                     FStarC_Reflection_V2_Embeddings.e_env
                                     (FStarC_Syntax_Embeddings.e_option
                                        uu___0))
                                  ({
                                     FStarC_TypeChecker_Env.solver =
                                       (env.FStarC_TypeChecker_Env.solver);
                                     FStarC_TypeChecker_Env.range =
                                       (env.FStarC_TypeChecker_Env.range);
                                     FStarC_TypeChecker_Env.curmodule =
                                       (env.FStarC_TypeChecker_Env.curmodule);
                                     FStarC_TypeChecker_Env.gamma = [];
                                     FStarC_TypeChecker_Env.gamma_sig =
                                       (env.FStarC_TypeChecker_Env.gamma_sig);
                                     FStarC_TypeChecker_Env.gamma_cache =
                                       (env.FStarC_TypeChecker_Env.gamma_cache);
                                     FStarC_TypeChecker_Env.modules =
                                       (env.FStarC_TypeChecker_Env.modules);
                                     FStarC_TypeChecker_Env.expected_typ =
                                       (env.FStarC_TypeChecker_Env.expected_typ);
                                     FStarC_TypeChecker_Env.sigtab =
                                       (env.FStarC_TypeChecker_Env.sigtab);
                                     FStarC_TypeChecker_Env.attrtab =
                                       (env.FStarC_TypeChecker_Env.attrtab);
                                     FStarC_TypeChecker_Env.instantiate_imp =
                                       (env.FStarC_TypeChecker_Env.instantiate_imp);
                                     FStarC_TypeChecker_Env.effects =
                                       (env.FStarC_TypeChecker_Env.effects);
                                     FStarC_TypeChecker_Env.generalize =
                                       (env.FStarC_TypeChecker_Env.generalize);
                                     FStarC_TypeChecker_Env.letrecs =
                                       (env.FStarC_TypeChecker_Env.letrecs);
                                     FStarC_TypeChecker_Env.top_level =
                                       (env.FStarC_TypeChecker_Env.top_level);
                                     FStarC_TypeChecker_Env.check_uvars =
                                       (env.FStarC_TypeChecker_Env.check_uvars);
                                     FStarC_TypeChecker_Env.use_eq_strict =
                                       (env.FStarC_TypeChecker_Env.use_eq_strict);
                                     FStarC_TypeChecker_Env.is_iface =
                                       (env.FStarC_TypeChecker_Env.is_iface);
                                     FStarC_TypeChecker_Env.admit =
                                       (env.FStarC_TypeChecker_Env.admit);
                                     FStarC_TypeChecker_Env.phase1 =
                                       (env.FStarC_TypeChecker_Env.phase1);
                                     FStarC_TypeChecker_Env.failhard =
                                       (env.FStarC_TypeChecker_Env.failhard);
                                     FStarC_TypeChecker_Env.flychecking =
                                       (env.FStarC_TypeChecker_Env.flychecking);
                                     FStarC_TypeChecker_Env.uvar_subtyping =
                                       (env.FStarC_TypeChecker_Env.uvar_subtyping);
                                     FStarC_TypeChecker_Env.intactics =
                                       (env.FStarC_TypeChecker_Env.intactics);
                                     FStarC_TypeChecker_Env.nocoerce =
                                       (env.FStarC_TypeChecker_Env.nocoerce);
                                     FStarC_TypeChecker_Env.tc_term =
                                       (env.FStarC_TypeChecker_Env.tc_term);
                                     FStarC_TypeChecker_Env.typeof_tot_or_gtot_term
                                       =
                                       (env.FStarC_TypeChecker_Env.typeof_tot_or_gtot_term);
                                     FStarC_TypeChecker_Env.universe_of =
                                       (env.FStarC_TypeChecker_Env.universe_of);
                                     FStarC_TypeChecker_Env.typeof_well_typed_tot_or_gtot_term
                                       =
                                       (env.FStarC_TypeChecker_Env.typeof_well_typed_tot_or_gtot_term);
                                     FStarC_TypeChecker_Env.teq_nosmt_force =
                                       (env.FStarC_TypeChecker_Env.teq_nosmt_force);
                                     FStarC_TypeChecker_Env.subtype_nosmt_force
                                       =
                                       (env.FStarC_TypeChecker_Env.subtype_nosmt_force);
                                     FStarC_TypeChecker_Env.qtbl_name_and_index
                                       =
                                       (env.FStarC_TypeChecker_Env.qtbl_name_and_index);
                                     FStarC_TypeChecker_Env.normalized_eff_names
                                       =
                                       (env.FStarC_TypeChecker_Env.normalized_eff_names);
                                     FStarC_TypeChecker_Env.fv_delta_depths =
                                       (env.FStarC_TypeChecker_Env.fv_delta_depths);
                                     FStarC_TypeChecker_Env.proof_ns =
                                       (env.FStarC_TypeChecker_Env.proof_ns);
                                     FStarC_TypeChecker_Env.synth_hook =
                                       (env.FStarC_TypeChecker_Env.synth_hook);
                                     FStarC_TypeChecker_Env.try_solve_implicits_hook
                                       =
                                       (env.FStarC_TypeChecker_Env.try_solve_implicits_hook);
                                     FStarC_TypeChecker_Env.splice =
                                       (env.FStarC_TypeChecker_Env.splice);
                                     FStarC_TypeChecker_Env.mpreprocess =
                                       (env.FStarC_TypeChecker_Env.mpreprocess);
                                     FStarC_TypeChecker_Env.postprocess =
                                       (env.FStarC_TypeChecker_Env.postprocess);
                                     FStarC_TypeChecker_Env.identifier_info =
                                       (env.FStarC_TypeChecker_Env.identifier_info);
                                     FStarC_TypeChecker_Env.tc_hooks =
                                       (env.FStarC_TypeChecker_Env.tc_hooks);
                                     FStarC_TypeChecker_Env.dsenv =
                                       (env.FStarC_TypeChecker_Env.dsenv);
                                     FStarC_TypeChecker_Env.nbe =
                                       (env.FStarC_TypeChecker_Env.nbe);
                                     FStarC_TypeChecker_Env.strict_args_tab =
                                       (env.FStarC_TypeChecker_Env.strict_args_tab);
                                     FStarC_TypeChecker_Env.erasable_types_tab
                                       =
                                       (env.FStarC_TypeChecker_Env.erasable_types_tab);
                                     FStarC_TypeChecker_Env.enable_defer_to_tac
                                       =
                                       (env.FStarC_TypeChecker_Env.enable_defer_to_tac);
                                     FStarC_TypeChecker_Env.unif_allow_ref_guards
                                       =
                                       (env.FStarC_TypeChecker_Env.unif_allow_ref_guards);
                                     FStarC_TypeChecker_Env.erase_erasable_args
                                       =
                                       (env.FStarC_TypeChecker_Env.erase_erasable_args);
                                     FStarC_TypeChecker_Env.core_check =
                                       (env.FStarC_TypeChecker_Env.core_check);
                                     FStarC_TypeChecker_Env.missing_decl =
                                       (env.FStarC_TypeChecker_Env.missing_decl)
                                   }, val_t)
                                  (FStarC_Syntax_Embeddings.e_tuple3
                                     (FStarC_Syntax_Embeddings.e_list
                                        (FStarC_Syntax_Embeddings.e_tuple3
                                           FStarC_Syntax_Embeddings.e_bool
                                           FStarC_Reflection_V2_Embeddings.e_sigelt
                                           (FStarC_Syntax_Embeddings.e_option
                                              (FStarC_Syntax_Embeddings.e_tuple2
                                                 FStarC_Syntax_Embeddings.e_string
                                                 uu___0))))
                                     (FStarC_Syntax_Embeddings.e_tuple3
                                        FStarC_Syntax_Embeddings.e_bool
                                        FStarC_Reflection_V2_Embeddings.e_sigelt
                                        (FStarC_Syntax_Embeddings.e_option
                                           (FStarC_Syntax_Embeddings.e_tuple2
                                              FStarC_Syntax_Embeddings.e_string
                                              uu___0)))
                                     (FStarC_Syntax_Embeddings.e_list
                                        (FStarC_Syntax_Embeddings.e_tuple3
                                           FStarC_Syntax_Embeddings.e_bool
                                           FStarC_Reflection_V2_Embeddings.e_sigelt
                                           (FStarC_Syntax_Embeddings.e_option
                                              (FStarC_Syntax_Embeddings.e_tuple2
                                                 FStarC_Syntax_Embeddings.e_string
                                                 uu___0))))) tau1
                                  tactic_already_typed ps1 in
                              (match uu___9 with
                               | (gs,
                                  (sig_blobs_before, sig_blob,
                                   sig_blobs_after)) ->
                                   let uu___10 = uu___9 in
                                   ((match (uv_t, sig_blob) with
                                     | (FStar_Pervasives_Native.Some uv_t1,
                                        (true,
                                         {
                                           FStarC_Syntax_Syntax.sigel = sigel;
                                           FStarC_Syntax_Syntax.sigrng =
                                             uu___12;
                                           FStarC_Syntax_Syntax.sigquals =
                                             uu___13;
                                           FStarC_Syntax_Syntax.sigmeta =
                                             uu___14;
                                           FStarC_Syntax_Syntax.sigattrs =
                                             uu___15;
                                           FStarC_Syntax_Syntax.sigopens_and_abbrevs
                                             = uu___16;
                                           FStarC_Syntax_Syntax.sigopts =
                                             uu___17;_},
                                         uu___18)) ->
                                         let actual_uv =
                                           match sigel with
                                           | FStarC_Syntax_Syntax.Sig_let
                                               {
                                                 FStarC_Syntax_Syntax.lbs1 =
                                                   (uu___19,
                                                    {
                                                      FStarC_Syntax_Syntax.lbname
                                                        = uu___20;
                                                      FStarC_Syntax_Syntax.lbunivs
                                                        = lbunivs;
                                                      FStarC_Syntax_Syntax.lbtyp
                                                        = uu___21;
                                                      FStarC_Syntax_Syntax.lbeff
                                                        = uu___22;
                                                      FStarC_Syntax_Syntax.lbdef
                                                        = uu___23;
                                                      FStarC_Syntax_Syntax.lbattrs
                                                        = uu___24;
                                                      FStarC_Syntax_Syntax.lbpos
                                                        = uu___25;_}::[]);
                                                 FStarC_Syntax_Syntax.lids1 =
                                                   uu___26;_}
                                               -> lbunivs
                                           | uu___19 -> [] in
                                         let uu___19 =
                                           let uu___20 =
                                             us_equals uv_t1 actual_uv in
                                           Prims.op_Negation uu___20 in
                                         if uu___19
                                         then
                                           let uu___20 =
                                             let uu___21 =
                                               let uu___22 =
                                                 FStarC_List.hd lids in
                                               FStarC_Class_Show.show
                                                 FStarC_Ident.showable_lident
                                                 uu___22 in
                                             let uu___22 =
                                               FStarC_Class_Show.show
                                                 (FStarC_Class_Show.show_list
                                                    FStarC_Ident.showable_ident)
                                                 actual_uv in
                                             let uu___23 =
                                               FStarC_Class_Show.show
                                                 (FStarC_Class_Show.show_list
                                                    FStarC_Ident.showable_ident)
                                                 uv_t1 in
                                             FStarC_Format.fmt3
                                               "Typed splice: val declaration for %s is universe polymorphic in %s, expected %s"
                                               uu___21 uu___22 uu___23 in
                                           FStarC_Errors.raise_error
                                             FStarC_Class_HasRange.hasRange_range
                                             rng
                                             FStarC_Errors_Codes.Error_BadSplice
                                             ()
                                             (Obj.magic
                                                FStarC_Errors_Msg.is_error_message_string)
                                             (Obj.magic uu___20)
                                         else ()
                                     | uu___12 -> ());
                                    (let sig_blobs =
                                       FStarC_List.op_At sig_blobs_before
                                         (sig_blob :: sig_blobs_after) in
                                     let sigelts =
                                       FStarC_List.map
                                         (fun uu___12 ->
                                            match uu___12 with
                                            | (checked, se, blob_opt) ->
                                                let uu___13 =
                                                  let uu___14 =
                                                    se.FStarC_Syntax_Syntax.sigmeta in
                                                  let uu___15 =
                                                    match blob_opt with
                                                    | FStar_Pervasives_Native.Some
                                                        (s, blob) ->
                                                        let uu___16 =
                                                          let uu___17 =
                                                            FStarC_Dyn.mkdyn
                                                              blob in
                                                          (s, uu___17) in
                                                        [uu___16]
                                                    | FStar_Pervasives_Native.None
                                                        -> [] in
                                                  {
                                                    FStarC_Syntax_Syntax.sigmeta_active
                                                      =
                                                      (uu___14.FStarC_Syntax_Syntax.sigmeta_active);
                                                    FStarC_Syntax_Syntax.sigmeta_fact_db_ids
                                                      =
                                                      (uu___14.FStarC_Syntax_Syntax.sigmeta_fact_db_ids);
                                                    FStarC_Syntax_Syntax.sigmeta_admit
                                                      =
                                                      (uu___14.FStarC_Syntax_Syntax.sigmeta_admit);
                                                    FStarC_Syntax_Syntax.sigmeta_spliced
                                                      =
                                                      (uu___14.FStarC_Syntax_Syntax.sigmeta_spliced);
                                                    FStarC_Syntax_Syntax.sigmeta_already_checked
                                                      = checked;
                                                    FStarC_Syntax_Syntax.sigmeta_extension_data
                                                      = uu___15
                                                  } in
                                                {
                                                  FStarC_Syntax_Syntax.sigel
                                                    =
                                                    (se.FStarC_Syntax_Syntax.sigel);
                                                  FStarC_Syntax_Syntax.sigrng
                                                    =
                                                    (se.FStarC_Syntax_Syntax.sigrng);
                                                  FStarC_Syntax_Syntax.sigquals
                                                    =
                                                    (se.FStarC_Syntax_Syntax.sigquals);
                                                  FStarC_Syntax_Syntax.sigmeta
                                                    = uu___13;
                                                  FStarC_Syntax_Syntax.sigattrs
                                                    =
                                                    (se.FStarC_Syntax_Syntax.sigattrs);
                                                  FStarC_Syntax_Syntax.sigopens_and_abbrevs
                                                    =
                                                    (se.FStarC_Syntax_Syntax.sigopens_and_abbrevs);
                                                  FStarC_Syntax_Syntax.sigopts
                                                    =
                                                    (se.FStarC_Syntax_Syntax.sigopts)
                                                }) sig_blobs in
                                     (gs, sigelts))))))
                    else
                      FStarC_Tactics_Interpreter.run_tactic_on_ps
                        tau1.FStarC_Syntax_Syntax.pos
                        tau1.FStarC_Syntax_Syntax.pos false
                        FStarC_Syntax_Embeddings.e_unit ()
                        (FStarC_Syntax_Embeddings.e_list
                           FStarC_Reflection_V2_Embeddings.e_sigelt) tau1
                        tactic_already_typed ps1 in
                  match uu___5 with
                  | (gs, sigelts) ->
                      let sigelts1 =
                        let proc_lb lb =
                          let uu___6 = lb in
                          match uu___6 with
                          | {
                              FStarC_Syntax_Syntax.lbname =
                                FStar_Pervasives.Inr fv;
                              FStarC_Syntax_Syntax.lbunivs = uu___7;
                              FStarC_Syntax_Syntax.lbtyp = uu___8;
                              FStarC_Syntax_Syntax.lbeff = uu___9;
                              FStarC_Syntax_Syntax.lbdef = lbdef;
                              FStarC_Syntax_Syntax.lbattrs = uu___10;
                              FStarC_Syntax_Syntax.lbpos = uu___11;_} ->
                              let r =
                                let uu___12 =
                                  FStarC_List.tryFind
                                    (fun i ->
                                       FStarC_Ident.lid_equals i
                                         fv.FStarC_Syntax_Syntax.fv_name)
                                    lids in
                                match uu___12 with
                                | FStar_Pervasives_Native.Some i ->
                                    FStarC_Class_HasRange.pos
                                      FStarC_Ident.hasrange_lident i
                                | uu___13 -> rng in
                              let fv1 =
                                FStarC_Class_HasRange.setPos
                                  FStarC_Syntax_Syntax.hasRange_fv r fv in
                              {
                                FStarC_Syntax_Syntax.lbname =
                                  (FStar_Pervasives.Inr fv1);
                                FStarC_Syntax_Syntax.lbunivs =
                                  (lb.FStarC_Syntax_Syntax.lbunivs);
                                FStarC_Syntax_Syntax.lbtyp =
                                  (lb.FStarC_Syntax_Syntax.lbtyp);
                                FStarC_Syntax_Syntax.lbeff =
                                  (lb.FStarC_Syntax_Syntax.lbeff);
                                FStarC_Syntax_Syntax.lbdef =
                                  (lb.FStarC_Syntax_Syntax.lbdef);
                                FStarC_Syntax_Syntax.lbattrs =
                                  (lb.FStarC_Syntax_Syntax.lbattrs);
                                FStarC_Syntax_Syntax.lbpos =
                                  (lb.FStarC_Syntax_Syntax.lbpos)
                              } in
                        FStarC_List.map
                          (fun se ->
                             match se.FStarC_Syntax_Syntax.sigel with
                             | FStarC_Syntax_Syntax.Sig_let
                                 { FStarC_Syntax_Syntax.lbs1 = (is_rec, lbs);
                                   FStarC_Syntax_Syntax.lids1 = lids1;_}
                                 ->
                                 let uu___6 =
                                   let uu___7 =
                                     let uu___8 =
                                       let uu___9 =
                                         FStarC_List.map proc_lb lbs in
                                       (is_rec, uu___9) in
                                     {
                                       FStarC_Syntax_Syntax.lbs1 = uu___8;
                                       FStarC_Syntax_Syntax.lids1 = lids1
                                     } in
                                   FStarC_Syntax_Syntax.Sig_let uu___7 in
                                 {
                                   FStarC_Syntax_Syntax.sigel = uu___6;
                                   FStarC_Syntax_Syntax.sigrng =
                                     (se.FStarC_Syntax_Syntax.sigrng);
                                   FStarC_Syntax_Syntax.sigquals =
                                     (se.FStarC_Syntax_Syntax.sigquals);
                                   FStarC_Syntax_Syntax.sigmeta =
                                     (se.FStarC_Syntax_Syntax.sigmeta);
                                   FStarC_Syntax_Syntax.sigattrs =
                                     (se.FStarC_Syntax_Syntax.sigattrs);
                                   FStarC_Syntax_Syntax.sigopens_and_abbrevs
                                     =
                                     (se.FStarC_Syntax_Syntax.sigopens_and_abbrevs);
                                   FStarC_Syntax_Syntax.sigopts =
                                     (se.FStarC_Syntax_Syntax.sigopts)
                                 }
                             | uu___6 -> se) sigelts in
                      (FStarC_Options.with_saved_options
                         (fun uu___7 ->
                            FStarC_List.iter
                              (fun g1 ->
                                 (let uu___9 =
                                    FStarC_Tactics_Types.goal_opts g1 in
                                  FStarC_Options.set uu___9);
                                 (let uu___9 =
                                    let uu___10 =
                                      FStarC_Tactics_Types.goal_env g1 in
                                    let uu___11 =
                                      FStarC_Tactics_Types.goal_type g1 in
                                    getprop uu___10 uu___11 in
                                  match uu___9 with
                                  | FStar_Pervasives_Native.Some vc ->
                                      ((let uu___11 =
                                          FStarC_Effect.op_Bang dbg_Tac in
                                        if uu___11
                                        then
                                          let uu___12 =
                                            FStarC_Class_Show.show
                                              FStarC_Syntax_Print.showable_term
                                              vc in
                                          FStarC_Format.print1
                                            "Splice left a goal: %s\n"
                                            uu___12
                                        else ());
                                       (let guard =
                                          FStarC_TypeChecker_Env.guard_of_guard_formula
                                            (FStarC_TypeChecker_Common.NonTrivial
                                               vc) in
                                        let uu___11 =
                                          FStarC_Tactics_Types.goal_env g1 in
                                        FStarC_TypeChecker_Rel.force_trivial_guard
                                          uu___11 guard))
                                  | FStar_Pervasives_Native.None ->
                                      FStarC_Errors.raise_error
                                        FStarC_Class_HasRange.hasRange_range
                                        rng
                                        FStarC_Errors_Codes.Fatal_OpenGoalsInSynthesis
                                        ()
                                        (Obj.magic
                                           FStarC_Errors_Msg.is_error_message_string)
                                        (Obj.magic "splice left open goals")))
                              gs);
                       (let lids' =
                          FStarC_List.collect
                            FStarC_Syntax_Util.lids_of_sigelt sigelts1 in
                        FStarC_List.iter
                          (fun lid ->
                             let uu___8 =
                               FStarC_List.tryFind
                                 (FStarC_Ident.lid_equals lid) lids' in
                             match uu___8 with
                             | FStar_Pervasives_Native.None when
                                 Prims.op_Negation
                                   env.FStarC_TypeChecker_Env.flychecking
                                 ->
                                 let uu___9 =
                                   let uu___10 =
                                     FStarC_Class_Show.show
                                       FStarC_Ident.showable_lident lid in
                                   let uu___11 =
                                     FStarC_Class_Show.show
                                       (FStarC_Class_Show.show_list
                                          FStarC_Ident.showable_lident) lids' in
                                   FStarC_Format.fmt2
                                     "Splice declared the name %s but it was not defined.\nThose defined were: %s"
                                     uu___10 uu___11 in
                                 FStarC_Errors.raise_error
                                   FStarC_Class_HasRange.hasRange_range rng
                                   FStarC_Errors_Codes.Fatal_SplicedUndef ()
                                   (Obj.magic
                                      FStarC_Errors_Msg.is_error_message_string)
                                   (Obj.magic uu___9)
                             | uu___9 -> ()) lids;
                        (let uu___9 = FStarC_Effect.op_Bang dbg_Tac in
                         if uu___9
                         then
                           let uu___10 =
                             FStarC_Class_Show.show
                               (FStarC_Class_Show.show_list
                                  FStarC_Syntax_Print.showable_sigelt)
                               sigelts1 in
                           FStarC_Format.print1
                             "splice: got decls = {\n\n%s\n\n}\n" uu___10
                         else ());
                        (let sigelts2 =
                           FStarC_List.map
                             (fun se ->
                                (match se.FStarC_Syntax_Syntax.sigel with
                                 | FStarC_Syntax_Syntax.Sig_datacon uu___10
                                     ->
                                     let uu___11 =
                                       let uu___12 =
                                         let uu___13 =
                                           FStarC_Errors_Msg.text
                                             "Tactic returned bad sigelt:" in
                                         let uu___14 =
                                           let uu___15 =
                                             FStarC_Syntax_Print.sigelt_to_string_short
                                               se in
                                           FStar_Pprint.doc_of_string uu___15 in
                                         FStar_Pprint.op_Hat_Slash_Hat
                                           uu___13 uu___14 in
                                       let uu___13 =
                                         let uu___14 =
                                           FStarC_Errors_Msg.text
                                             "If you wanted to splice an inductive type, call `pack` providing a `Sg_Inductive` to get a proper sigelt." in
                                         [uu___14] in
                                       uu___12 :: uu___13 in
                                     FStarC_Errors.raise_error
                                       FStarC_Class_HasRange.hasRange_range
                                       rng
                                       FStarC_Errors_Codes.Error_BadSplice ()
                                       (Obj.magic
                                          FStarC_Errors_Msg.is_error_message_list_doc)
                                       (Obj.magic uu___11)
                                 | FStarC_Syntax_Syntax.Sig_inductive_typ
                                     uu___10 ->
                                     let uu___11 =
                                       let uu___12 =
                                         let uu___13 =
                                           FStarC_Errors_Msg.text
                                             "Tactic returned bad sigelt:" in
                                         let uu___14 =
                                           let uu___15 =
                                             FStarC_Syntax_Print.sigelt_to_string_short
                                               se in
                                           FStar_Pprint.doc_of_string uu___15 in
                                         FStar_Pprint.op_Hat_Slash_Hat
                                           uu___13 uu___14 in
                                       let uu___13 =
                                         let uu___14 =
                                           FStarC_Errors_Msg.text
                                             "If you wanted to splice an inductive type, call `pack` providing a `Sg_Inductive` to get a proper sigelt." in
                                         [uu___14] in
                                       uu___12 :: uu___13 in
                                     FStarC_Errors.raise_error
                                       FStarC_Class_HasRange.hasRange_range
                                       rng
                                       FStarC_Errors_Codes.Error_BadSplice ()
                                       (Obj.magic
                                          FStarC_Errors_Msg.is_error_message_list_doc)
                                       (Obj.magic uu___11)
                                 | uu___10 -> ());
                                {
                                  FStarC_Syntax_Syntax.sigel =
                                    (se.FStarC_Syntax_Syntax.sigel);
                                  FStarC_Syntax_Syntax.sigrng = rng;
                                  FStarC_Syntax_Syntax.sigquals =
                                    (se.FStarC_Syntax_Syntax.sigquals);
                                  FStarC_Syntax_Syntax.sigmeta =
                                    (se.FStarC_Syntax_Syntax.sigmeta);
                                  FStarC_Syntax_Syntax.sigattrs =
                                    (se.FStarC_Syntax_Syntax.sigattrs);
                                  FStarC_Syntax_Syntax.sigopens_and_abbrevs =
                                    (se.FStarC_Syntax_Syntax.sigopens_and_abbrevs);
                                  FStarC_Syntax_Syntax.sigopts =
                                    (se.FStarC_Syntax_Syntax.sigopts)
                                }) sigelts1 in
                         if is_typed
                         then ()
                         else
                           FStarC_List.iter
                             (fun se ->
                                FStarC_List.iter
                                  (fun q ->
                                     let uu___11 =
                                       FStarC_Syntax_Syntax.is_internal_qualifier
                                         q in
                                     if uu___11
                                     then
                                       let uu___12 =
                                         let uu___13 =
                                           let uu___14 =
                                             let uu___15 =
                                               FStarC_Class_Show.show
                                                 FStarC_Syntax_Print.showable_qualifier
                                                 q in
                                             FStarC_Format.fmt1
                                               "The qualifier %s is internal."
                                               uu___15 in
                                           FStarC_Errors_Msg.text uu___14 in
                                         let uu___14 =
                                           let uu___15 =
                                             let uu___16 =
                                               FStarC_Errors_Msg.text
                                                 "It cannot be attached to spliced declaration:" in
                                             let uu___17 =
                                               let uu___18 =
                                                 FStarC_Syntax_Print.sigelt_to_string_short
                                                   se in
                                               FStar_Pprint.arbitrary_string
                                                 uu___18 in
                                             FStar_Pprint.prefix
                                               (Prims.of_int (2))
                                               Prims.int_one uu___16 uu___17 in
                                           [uu___15] in
                                         uu___13 :: uu___14 in
                                       FStarC_Errors.raise_error
                                         FStarC_Class_HasRange.hasRange_range
                                         rng
                                         FStarC_Errors_Codes.Error_InternalQualifier
                                         ()
                                         (Obj.magic
                                            FStarC_Errors_Msg.is_error_message_list_doc)
                                         (Obj.magic uu___12)
                                     else ())
                                  se.FStarC_Syntax_Syntax.sigquals) sigelts2;
                         (match () with | () -> sigelts2))))))))
let mpreprocess (env : FStarC_TypeChecker_Env.env)
  (tau : FStarC_Syntax_Syntax.term) (tm : FStarC_Syntax_Syntax.term) :
  FStarC_Syntax_Syntax.term=
  FStarC_Errors.with_ctx "While preprocessing a definition with a tactic"
    (fun uu___ ->
       if env.FStarC_TypeChecker_Env.flychecking
       then tm
       else
         (let ps =
            FStarC_Tactics_V2_Basic.proofstate_of_goals
              tm.FStarC_Syntax_Syntax.pos env [] [] in
          let tactic_already_typed = false in
          let uu___2 =
            FStarC_Tactics_Interpreter.run_tactic_on_ps
              tau.FStarC_Syntax_Syntax.pos tm.FStarC_Syntax_Syntax.pos false
              FStarC_Reflection_V2_Embeddings.e_term tm
              FStarC_Reflection_V2_Embeddings.e_term tau tactic_already_typed
              ps in
          match uu___2 with | (gs, tm1) -> tm1))
let postprocess (env : FStarC_TypeChecker_Env.env)
  (tau : FStarC_Syntax_Syntax.term) (typ : FStarC_Syntax_Syntax.term)
  (tm : FStarC_Syntax_Syntax.term) : FStarC_Syntax_Syntax.term=
  FStarC_Errors.with_ctx "While postprocessing a definition with a tactic"
    (fun uu___ ->
       if env.FStarC_TypeChecker_Env.flychecking
       then tm
       else
         (let uu___2 =
            FStarC_TypeChecker_Env.new_implicit_var_aux "postprocess RHS"
              tm.FStarC_Syntax_Syntax.pos env typ
              (FStarC_Syntax_Syntax.Allow_untyped "postprocess")
              FStar_Pervasives_Native.None false in
          match uu___2 with
          | (uvtm, uu___3, g_imp) ->
              let u = env.FStarC_TypeChecker_Env.universe_of env typ in
              let goal =
                let uu___4 = FStarC_Syntax_Util.mk_eq2 u typ tm uvtm in
                FStarC_Syntax_Util.mk_squash FStarC_Syntax_Syntax.U_zero
                  uu___4 in
              let uu___4 =
                run_tactic_on_typ tau.FStarC_Syntax_Syntax.pos
                  tm.FStarC_Syntax_Syntax.pos tau env goal in
              (match uu___4 with
               | (gs, w) ->
                   (FStarC_List.iter
                      (fun g ->
                         let uu___6 =
                           let uu___7 = FStarC_Tactics_Types.goal_env g in
                           let uu___8 = FStarC_Tactics_Types.goal_type g in
                           getprop uu___7 uu___8 in
                         match uu___6 with
                         | FStar_Pervasives_Native.Some vc ->
                             ((let uu___8 = FStarC_Effect.op_Bang dbg_Tac in
                               if uu___8
                               then
                                 let uu___9 =
                                   FStarC_Class_Show.show
                                     FStarC_Syntax_Print.showable_term vc in
                                 FStarC_Format.print1
                                   "Postprocessing left a goal: %s\n" uu___9
                               else ());
                              (let guard =
                                 FStarC_TypeChecker_Env.guard_of_guard_formula
                                   (FStarC_TypeChecker_Common.NonTrivial vc) in
                               let uu___8 = FStarC_Tactics_Types.goal_env g in
                               FStarC_TypeChecker_Rel.force_trivial_guard
                                 uu___8 guard))
                         | FStar_Pervasives_Native.None ->
                             FStarC_Errors.raise_error
                               (FStarC_Syntax_Syntax.has_range_syntax ()) typ
                               FStarC_Errors_Codes.Fatal_OpenGoalsInSynthesis
                               ()
                               (Obj.magic
                                  FStarC_Errors_Msg.is_error_message_string)
                               (Obj.magic "postprocessing left open goals"))
                      gs;
                    (let tagged_imps =
                       FStarC_TypeChecker_Rel.resolve_implicits_tac env g_imp in
                     FStarC_Tactics_Interpreter.report_implicits
                       tm.FStarC_Syntax_Syntax.pos tagged_imps;
                     uvtm)))))
