aboutsummaryrefslogtreecommitdiffhomepage
path: root/kernel/opaqueproof.ml
blob: 7aed4bf501ec6449b434c0915b7cd8e9fa3f0076 (plain)
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
(************************************************************************)
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
(* <O___,, *   INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012     *)
(*   \VV/  **************************************************************)
(*    //   *      This file is distributed under the terms of the       *)
(*         *       GNU Lesser General Public License Version 2.1        *)
(************************************************************************)

open Names
open Univ
open Term
open Mod_subst

type work_list = (Instance.t * Id.t array) Cmap.t * 
  (Instance.t * Id.t array) Mindmap.t

type cooking_info = { 
  modlist : work_list; 
  abstract : Context.named_context in_universe_context } 
type proofterm = (constr * Univ.universe_context_set) Future.computation
type opaque =
  | Indirect of substitution list * DirPath.t * int (* subst, lib, index *)
  | Direct of cooking_info list * proofterm
  | NoIndirect of substitution list * proofterm

(* hooks *)
let default_get_opaque dp _ =
  Errors.error
    ("Cannot access opaque proofs in library " ^ DirPath.to_string dp)
let default_get_univ dp _ =
  Errors.error
    ("Cannot access universe constraints of opaque proofs in library " ^
    DirPath.to_string dp)
let default_mk_indirect _ = None
let default_join_indirect_local_opaque _ _ = ()
let default_join_indirect_local_univ _ _ = ()

let get_opaque = ref default_get_opaque
let get_univ = ref default_get_univ
let join_indirect_local_opaque = ref default_join_indirect_local_opaque
let join_indirect_local_univ = ref default_join_indirect_local_univ
let mk_indirect = ref default_mk_indirect

let set_indirect_opaque_accessor f = (get_opaque := f)
let set_indirect_univ_accessor f = (get_univ := f)
let set_indirect_creator f = (mk_indirect := f)
let set_join_indirect_local_opaque f = join_indirect_local_opaque := f
let set_join_indirect_local_univ f = join_indirect_local_univ := f
let reset_indirect_creator () = mk_indirect := default_mk_indirect
(* /hooks *)

let create cu = Direct ([],cu)

let turn_indirect o = match o with
  | Indirect _
  | NoIndirect _ -> Errors.anomaly (Pp.str "Already an indirect opaque")
  | Direct (d,cu) ->
      let cu = Future.chain ~pure:true cu (fun (c, u) -> hcons_constr c, u) in
      match !mk_indirect (d,cu) with
      | None -> Future.sink cu; NoIndirect([],cu)
      | Some (dp,i) -> Indirect ([],dp,i)

let subst_opaque sub = function
  | Indirect (s,dp,i) -> Indirect (sub::s,dp,i)
  | NoIndirect (s,uc) -> NoIndirect (sub::s,uc)
  | Direct _ -> Errors.anomaly (Pp.str "Substituting a Direct opaque")

let iter_direct_opaque f = function
  | Indirect _
  | NoIndirect _ -> Errors.anomaly (Pp.str "Not a direct opaque")
  | Direct (d,cu) ->
      Direct (d,Future.chain ~pure:true cu (fun (c, u) -> f c; c, u))

let discharge_direct_opaque ~cook_constr ci = function
  | Indirect _
  | NoIndirect _ -> Errors.anomaly (Pp.str "Not a direct opaque")
  | Direct (d,cu) ->
      Direct (ci::d,Future.chain ~pure:true cu (fun (c, u) -> cook_constr c, u))

let join_opaque = function
  | Direct (_,cu) -> ignore(Future.join cu)
  | NoIndirect (_,cu) -> ignore(Future.join cu)
  | Indirect (_,dp,i) ->
      !join_indirect_local_opaque dp i;
      !join_indirect_local_univ dp i

let force_proof = function
  | Direct (_,cu) ->
      fst(Future.force cu)
  | NoIndirect (l,cu) ->
      let c, _ = Future.force cu in
      force_constr (List.fold_right subst_substituted l (from_val c))
  | Indirect (l,dp,i) ->
      let c = Future.force (!get_opaque dp i) in
      force_constr (List.fold_right subst_substituted l (from_val c))

let force_constraints = function
  | Direct (_,cu)
  | NoIndirect(_,cu) -> snd(Future.force cu)
  | Indirect (_,dp,i) ->
      match !get_univ dp i with
      | None -> Univ.ContextSet.empty
      | Some u -> Future.force u

let get_constraints = function
  | Direct (_,cu)
  | NoIndirect(_,cu) -> Some(Future.chain ~pure:true cu snd)
  | Indirect (_,dp,i) -> !get_univ dp i

let get_proof = function
  | Direct (_,cu) -> Future.chain ~pure:true cu fst
  | NoIndirect(l,cu) ->
      Future.chain ~pure:true cu (fun (c,_) ->
        force_constr (List.fold_right subst_substituted l (from_val c)))
  | Indirect (l,dp,i) ->
      Future.chain ~pure:true (!get_opaque dp i) (fun c ->
        force_constr (List.fold_right subst_substituted l (from_val c)))