aboutsummaryrefslogtreecommitdiffhomepage
path: root/contrib/linear/ccidpc.ml4
blob: 1823b2d48ca28d79a3ab85b5b15052234dd007ce (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
(***********************************************************************)
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team    *)
(* <O___,, *        INRIA-Rocquencourt  &  LRI-CNRS-Orsay              *)
(*   \VV/  *************************************************************)
(*    //   *      This file is distributed under the terms of the      *)
(*         *       GNU Lesser General Public License Version 2.1       *)
(***********************************************************************)

(*i camlp4deps: "parsing/grammar.cma" i*)

(*i $Id$ i*)

open Dpctypes

open Names
open Nameops
open Pp
open Term
open Termops
open Environ
open Himsg
open Tacmach
open Reductionops
open Clenv
open Tactics
open Hipattern
open Tacticals
open Tactics
open Util
open Sign
open Tacinterp

(*
let mmk = make_module_marker ["#Prelude.obj"]

let and_pattern   = put_pat mmk "(and ? ?)"
let or_pattern    = put_pat mmk "(or ? ?)"
let not_pattern   = put_pat mmk "(not ?)"
let exist_pattern = put_pat mmk "(ex ? ?)"

let and_head      = put_pat mmk "and"
let or_head       = put_pat mmk "or"
let not_head      = put_pat mmk "not"
let exist_head    = put_pat mmk "ex"

*)

let op2bool=function Some _->true |None->false

let match_with_imp_term t =
  match kind_of_term t with
      Prod (_,a,b)->
	if not (dependent (mkRel 1) b) then
	  Some (a,b) else None
    | _-> None

let is_imp_term t=op2bool (match_with_imp_term t)

let match_with_forall_term t =
  match kind_of_term (whd_betaiota t) with
      Prod (x,a,b)->
	if dependent (mkRel 1) b then Some (x,a,b) else None
    | _ -> None

let is_forall_term t=op2bool (match_with_forall_term t)

let constr_of_string s () =
  Libnames.constr_of_reference (Nametab.locate (Libnames.qualid_of_string s))

let id_ex=constr_of_string "Coq.Init.Logic.ex" 

let match_with_exist_term t=
  match kind_of_term t with
      App(t,v)->
	if t=id_ex () && (Array.length v)=2 then
	  match kind_of_term v.(1) with
	      Lambda(na,a,b)->Some(na,a,b)
	    |_->assert false
	else None
    | _->None

let is_exist_term t=op2bool (match_with_exist_term t)

let id_not=constr_of_string "Coq.Init.Logic.not"

let id_false=constr_of_string "Coq.Init.Logic.False"

let match_with_not_term t=
  match kind_of_term t with
      App(t,v)->
	if t=id_not () && (Array.length v)=1 then
	  Some v.(0) 
	else None
    | Prod(_,a,b)->
	if b=id_false () then
	  Some a
	else None
    | _->None


let is_not_term t=op2bool (match_with_not_term t)

let ctr = ref 0

let gen_ident id = make_ident (atompart_of_id id) (incr ctr;Some !ctr)

let gen_name a na =
    match (named_hd Environ.empty_env a na) with 
	(Name id)->gen_ident id
      | Anonymous->assert false

let dpc_of_cci_term lid = 
 let rec tradrec cciterm =
    let (hd,args) = whd_betaiota_stack cciterm in
    let dpcargs = List.map tradrec args
    in (match kind_of_term hd with
            Var id -> if dpcargs=[] then VAR id 
                  else if List.mem id lid 
                  then failwith "dpc_of_cci_term (not first order)"
                  else APP (VAR id :: dpcargs)

      | (Const _ | Ind _ | Construct _) as t 
      	   -> if dpcargs=[] then GLOB (CN hd)
	                    else APP (GLOB (CN hd) :: dpcargs)

      | _ -> errorlabstrm "dpc_of_cci_term"
                (str "Not a first order formula"))
 in tradrec
    

let cci_of_dpc_term tradsign sign = 
  let rec tradrec = function
      VAR id -> 
	(try let (_,t,_)=lookup_named id tradsign in
	   match t with
	       Some t'-> t'
	     |None ->Term.mkVar id
	   with Not_found->Term.mkVar id)
    | GLOB (ID id) -> Term.mkVar id
    | GLOB (CN t)  -> t
    | APP (t::dpcargs) ->
	let t' = tradrec t in
	  Term.applist(t', List.map tradrec dpcargs)
    | _-> assert false
  in tradrec
    

let dpc_of_cci_fmla gls cciterm = 
  let rec tradrec lid cciterm =
    match match_with_conjunction cciterm with
	Some (_,[a;b])->Conj(tradrec lid a,tradrec lid b)
      |_->
	  (match match_with_disjunction cciterm with
	       Some (_,[a;b])->Disj(tradrec lid a,tradrec lid b)
	     |_->
		 (match match_with_not_term cciterm with
		   	       Some a->Neg(tradrec lid a)
		    |_->
		       (match match_with_imp_term cciterm with
			    Some (a,b)->Imp (tradrec lid a,tradrec lid (pop b))
			  |_->
    (match match_with_forall_term cciterm with
	 Some ((na,a,b) as trp)->
	   let id = gen_name a na in
	   let f=whd_beta (mkApp ((mkLambda trp),[|mkVar id|])) in
	     ForAll(id,tradrec (id::lid) f)
       |_-> 
	   (match match_with_exist_term cciterm with
		Some ((na,a,b)as trp)->
		  let id = gen_name a na in
		  let f=whd_beta (mkApp ((mkLambda trp),[|mkVar id|])) in
		    Exists(id,tradrec (id::lid) f)
	      |_->   
    let (hd,args) = whd_betaiota_stack cciterm in
    let dpcargs = List.map (dpc_of_cci_term lid) args
    in (match kind_of_term hd with
	    Var id -> if List.mem id lid 
	    then errorlabstrm "dpc_of_cci_fmla"
	      (str "Quantification over a predicate")
	    else Atom((ID id,0),dpcargs)
	  | Ind _ | Construct _ | Const _ 
    	      -> Atom( (CN hd,0) , dpcargs)
	  | _ -> errorlabstrm "dpc_of_cci_flma"
		((Printer.prterm_env 
		    (Global.env_of_context (pf_hyps gls)) hd) ++ 
		 (spc ()) ++
		 (str "is not an atomic predicate"))))))))
	  in tradrec [] (whd_betaiota cciterm)  
	       
let rec index x=function
    []-> raise Not_found
  | y::q-> if x=y then 0 else 1+(index x q)
      

let rec alpha_term bl1 bl2 p_0 p_1 =
  match p_0,p_1 with
      ((VAR id1), (VAR id2)) ->
      	if not (List.mem id1 bl1) then
	  id1=id2
      	else
	  index id1 bl1 = index id2 bl2
    | ((GLOB t1), (GLOB t2)) -> t1=t2
    | ((APP al1), (APP al2)) ->
      	List.for_all2 (alpha_term bl1 bl2) al1 al2
    | (_, _) -> false


let forAllI gls=if is_forall_term (pf_concl gls) then
  intro gls else tclFAIL 0 gls

let forAllE id t gls =
  let rgl=pf_whd_betadeltaiota gls (pf_type_of gls (mkVar id)) in
    if is_forall_term rgl then
      tclTHEN (generalize [mkApp (mkVar id,[|t|])]) intro gls
    else  tclFAIL 0 gls

let existE id gls =
  let (_,_,t)=lookup_named id (pf_hyps gls) in
    if is_exist_term t then
        ((tclTHEN (simplest_elim (mkVar id))
         (tclDO 2 (dImp None)))) gls
    else tclFAIL 0 gls

let negE id gls = 
  let (_,_,t)=lookup_named id (pf_hyps gls) in
    if is_not_term t then
        (simplest_elim (mkVar id)) gls
    else tclFAIL 0 gls

(*t exist_intro_head = put_pat mmk "ex_intro"*)

let existI t gls =
(*  if is_exist_term (pf_concl gls) then
    split (Rawterm.ImplicitBindings [t]) gls
  else tclFAIL 0 gls *)
    
 
    let (wc,kONT) = Evar_refiner.startWalk gls in
    let clause = mk_clenv_hnf_constr_type_of wc (pf_concl gls) in
    let clause' = clenv_constrain_missing_args [t] clause
    in res_pf kONT clause' gls


let rec alpha_fmla bl1 bl2 p_0 p_1 =
  match p_0,p_1 with
      ((Atom((cn1,_),al1)), (Atom((cn2,_),al2))) ->
    	cn1=cn2 & List.for_all2 (alpha_term bl1 bl2) al1 al2
    | ((Conj(a1,b1)),(Conj(a2,b2))) ->
    	alpha_fmla bl1 bl2 a1 a2 & alpha_fmla bl1 bl2 b1 b2

    | ((Disj(a1,b1)),(Disj(a2,b2))) ->
    	alpha_fmla bl1 bl2 a1 a2 & alpha_fmla bl1 bl2 b1 b2

    | ((Imp(a1,b1)),(Imp(a2,b2))) ->
    	alpha_fmla bl1 bl2 a1 a2 & alpha_fmla bl1 bl2 b1 b2

    | ((Neg(a1)), (Neg(a2))) -> alpha_fmla bl1 bl2 a1 a2

    | ((ForAll(x1,a1)), (ForAll(x2,a2))) ->
    	alpha_fmla (x1::bl1) (x2::bl2) a1 a2

    | ((Exists(x1,a1)), (Exists(x2,a2))) ->
    	alpha_fmla (x1::bl1) (x2::bl2) a1 a2

    | (_, _) -> false

let alpha_eq (kspine,m) (jspine,n) = alpha_fmla kspine jspine m n

let first_pred p = 
 let rec firstrec = function
    [] -> error "first_pred"
  | h::t -> if p h then h else firstrec t
 in firstrec


let find_fmla_left (kspine,f) (jspine,gl) =
    let ids = pf_ids_of_hyps gl 
    and sign= pf_hyps gl in
      first_pred 
        (fun id -> 
	   let (_,_,t)=lookup_named id sign in
	   ( try alpha_eq (kspine,f)
                       (jspine,dpc_of_cci_fmla gl t)
		     with _ -> false) 
        ) ids


let onNthClause tac n gls =
    let cls = nth_clause n gls
    in onClause tac cls gls


let elimTypeFalse gls =
  (elim_type (pf_global gls (id_of_string "False"))) gls


let rec tradpf kspine jspine dpcpf gls =
    match dpcpf with

    Proof2(_,_,Axiom2 f) ->
    let id = find_fmla_left (kspine,f) (jspine,gls)
    in exact_no_check (mkVar id) gls

  | Proof2(_,_,LWeakening2(_,pf)) -> trad kspine jspine pf gls

  | Proof2(_,_,RWeakening2(_,pf)) ->
     ( (tclTHEN (elimTypeFalse) (tradpf kspine jspine pf)) ) gls

  | Proof2(_,_,RConj2(f1,pf1,f2,pf2)) ->
    ((tclTHENS (dAnd None) ([trad kspine jspine pf1;
                      trad kspine jspine pf2]))) gls

  | Proof2(_,_,LConj2(f1,f2,pf)) ->
    let id = find_fmla_left (kspine,Conj(f1,f2)) (jspine,gls)
    in ((tclTHEN (dAnd (Some id)) ((trad kspine jspine pf)))) gls

  | Proof2(_,_,LDisj2(f1,pf1,f2,pf2)) ->
    let id = find_fmla_left (kspine,Disj(f1,f2)) (jspine,gls)
    in (match pf1 with 
          Proof2(_,[],_) -> ((tclTHENS (orE id) 
                            ([ ((tclTHEN (elimTypeFalse) (trad kspine jspine pf1)));
                              trad kspine jspine pf2]))) gls
        | _              -> ((tclTHENS (orE id) 
                            ([ trad kspine jspine pf1;
                              ((tclTHEN (elimTypeFalse) (trad kspine jspine pf2)))]))) gls
       )

  | Proof2(_,_,RImp2(f1,f2,pf)) ->
    ((tclTHEN (dImp None) ((trad kspine jspine pf)))) gls

  | Proof2(_,_,LImp2(f1,pf1,f2,pf2)) ->
    let id = find_fmla_left (kspine,Imp(f1,f2)) (jspine,gls)
    in ((tclTHENS (dImp (Some id))
	   ([trad kspine jspine pf2;
             trad kspine jspine pf1]))) gls

  | Proof2(_,_,RForAll2(kid,f,pf)) ->
    ((tclTHEN forAllI
     ((onLastHyp (fun jid ->
                     trad (kid::kspine) (jid::jspine) pf))))) gls

  | Proof2(_,_,LForAll2(kid,kterm,f,pf)) ->
    let jterm = cci_of_dpc_term (pf_hyps gls) (kspine,jspine) kterm in
    let id = find_fmla_left (kspine,ForAll(kid,f)) (jspine,gls)
    in ((tclTHEN (forAllE id jterm)
        (trad kspine jspine pf))) gls

  | Proof2(_,_,LExists2(kid,f,pf)) ->
    let id = find_fmla_left (kspine,Exists(kid,f)) (jspine,gls)
    in ((tclTHEN (existE id)
        ((onNthClause (function (Some jid) ->
                          trad (kid::kspine) (jid::jspine) pf
			 | None-> assert false)
         (-2))))) gls

  | Proof2(_,_,RExists2(kid,kterm,f,pf)) ->
    let jterm = cci_of_dpc_term (pf_hyps gls) (kspine,jspine) kterm
    in ((tclTHEN (existI jterm) (tradpf kspine jspine pf))) gls

  | Proof2(_,_,RDisj2(f1,f2,Proof2(_,_,RWeakening2(f3,pf)))) ->
    if alpha_eq (kspine,f1) (kspine,f3) then
        ((tclTHEN (right Rawterm.NoBindings) (tradpf kspine jspine pf))) gls
    else if alpha_eq (kspine,f2) (kspine,f3) then
        ((tclTHEN (left Rawterm.NoBindings) (tradpf kspine jspine pf))) gls
    else error "Not Intuitionistic, eh?"

  | Proof2(_,_,RNeg2(f,pf)) -> 
      ((tclTHEN ((tclTHEN (red_in_concl) (Tactics.intro))) (tradpf kspine jspine pf))) gls

  | Proof2(_,_,LNeg2(f,pf)) -> 
     let id = find_fmla_left (kspine,Neg(f)) (jspine,gls)
     in ((tclTHEN (negE id) (tradpf kspine jspine pf))) gls

  | _ -> error "tradpf : Not an intuitionistic proof !"

and trad kspine jspine dpcpf gls =
    tradpf kspine jspine dpcpf gls