1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
(************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) (* This file is (C) Copyright 2006-2015 Microsoft Corporation and Inria. *) open Util open Names open Term open Ltac_plugin open Tacinterp open Glob_term open Tacmach open Tacticals open Ssrcommon (* The table and its display command *) (* FIXME this looks hackish *) let viewtab : glob_constr list array = Array.make 3 [] let _ = let init () = Array.fill viewtab 0 3 [] in let freeze _ = Array.copy viewtab in let unfreeze vt = Array.blit vt 0 viewtab 0 3 in Summary.declare_summary "ssrview" { Summary.freeze_function = freeze; Summary.unfreeze_function = unfreeze; Summary.init_function = init } (* Populating the table *) let cache_viewhint (_, (i, lvh)) = let mem_raw h = List.exists (Glob_ops.glob_constr_eq h) in let add_hint h hdb = if mem_raw h hdb then hdb else h :: hdb in viewtab.(i) <- List.fold_right add_hint lvh viewtab.(i) let subst_viewhint ( subst, (i, lvh as ilvh)) = let lvh' = List.smartmap (Detyping.subst_glob_constr subst) lvh in if lvh' == lvh then ilvh else i, lvh' let classify_viewhint x = Libobject.Substitute x let in_viewhint = Libobject.declare_object {(Libobject.default_object "VIEW_HINTS") with Libobject.open_function = (fun i o -> if i = 1 then cache_viewhint o); Libobject.cache_function = cache_viewhint; Libobject.subst_function = subst_viewhint; Libobject.classify_function = classify_viewhint } let glob_view_hints lvh = List.map (Constrintern.intern_constr (Global.env ())) lvh let add_view_hints lvh i = Lib.add_anonymous_leaf (in_viewhint (i, lvh)) let interp_view ist si env sigma gv rv rid = match DAst.get rv with | GApp (h, rargs) when (match DAst.get h with GHole _ -> true | _ -> false) -> let loc = rv.CAst.loc in let rv = DAst.make ?loc @@ GApp (rid, rargs) in snd (interp_open_constr ist (re_sig si sigma) (rv, None)) | _ -> let interp rc rargs = interp_open_constr ist (re_sig si sigma) (mkRApp rc rargs, None) in let rec simple_view rargs n = if n < 0 then view_error "use" gv else try interp rv rargs with _ -> simple_view (mkRHole :: rargs) (n - 1) in let view_nbimps = interp_view_nbimps ist (re_sig si sigma) rv in let view_args = [mkRApp rv (mkRHoles view_nbimps); rid] in let rec view_with = function | [] -> simple_view [rid] (interp_nbargs ist (re_sig si sigma) rv) | hint :: hints -> try interp hint view_args with _ -> view_with hints in snd (view_with (if view_nbimps < 0 then [] else viewtab.(0))) let with_view ist ~next si env (gl0 : (Goal.goal * tac_ctx) Evd.sigma) c name cl prune (conclude : EConstr.t -> EConstr.t -> tac_ctx tac_a) clr = let c2r ist x = { ist with lfun = Id.Map.add top_id (Value.of_constr x) ist.lfun } in let terminate (sigma, c') = let sigma = Typeclasses.resolve_typeclasses ~fail:false env sigma in let c' = Reductionops.nf_evar sigma c' in let n, c', _, ucst = without_ctx pf_abs_evars gl0 (sigma, c') in let c' = if not prune then c' else without_ctx pf_abs_cterm gl0 n c' in let gl0 = pf_merge_uc ucst gl0 in let gl0, ap = let gl0, ctx = pull_ctx gl0 in let gl0, ap = pf_abs_prod name gl0 c' (Termops.prod_applist sigma cl [c]) in push_ctx ctx gl0, ap in let gl0 = pf_merge_uc_of sigma gl0 in ap, c', gl0 in let rec loop (sigma, c') = function | [] -> let ap, c', gl = terminate (sigma, c') in ap, c', conclude ap c' gl | f :: view -> let ist, rid = match EConstr.kind sigma c' with | Var id -> ist,mkRVar id | _ -> c2r ist c',mkRltacVar top_id in let v = intern_term ist env f in loop (interp_view ist si env sigma f v rid) view in loop let pfa_with_view ist ?(next=ref []) (prune, view) cl c conclude clr gl = let env, sigma, si = without_ctx pf_env gl, Refiner.project gl, without_ctx sig_it gl in with_view ist ~next si env gl c (constr_name sigma c) cl prune conclude clr (sigma, c) view let pf_with_view_linear ist gl v cl c = let x,y,gl = pfa_with_view ist v cl c (fun _ _ -> tac_ctx tclIDTAC) [] (push_ctx (new_ctx ()) gl) in let gl, _ = pull_ctxs gl in assert(List.length (sig_it gl) = 1); x,y,re_sig (List.hd (sig_it gl)) (Refiner.project gl) (* vim: set filetype=ocaml foldmethod=marker: *)