module C = Cic
module I = CicInspect
module S = CicSubstitution
+module R = CicReduction
module TC = CicTypeChecker
module Un = CicUniv
module UM = UriManager
max_depth: int option;
depth : int;
defaults : bool;
+ cr : bool;
context : C.context;
case : int list
}
try
let id = Ut.id_of_annterm v in
try match Hashtbl.find st.types id with
- | {A.annsynthesized = st; A.annexpected = Some et} -> Some (st, et)
- | {A.annsynthesized = st; A.annexpected = None} -> Some (st, st)
+ | {A.annsynthesized = ity; A.annexpected = Some ety} -> Some (ity, ety)
+ | {A.annsynthesized = ity; A.annexpected = None} -> Some (ity, ity)
with Not_found -> None
-with Invalid_argument _ -> failwith "A2P.get_inner_types"
+with Invalid_argument _ -> failwith "P2.get_inner_types"
let get_entry st id =
let rec aux = function
let get_type msg st t = H.get_type msg st.context (H.cic t)
+let get_uri_of_head = function
+ | C.AConst (_, u, _) ->
+ Some (u, 0, 0, 0)
+ | C.AAppl (_, C.AConst (_, u, _) :: vs) ->
+ Some (u, 0, 0, List.length vs)
+ | C.AMutInd (_, u, i, _) ->
+ Some (u, succ i, 0, 0)
+ | C.AAppl (_, C.AMutInd (_, u, i, _) :: vs) ->
+ Some (u, succ i, 0, List.length vs)
+ | C.AMutConstruct (_, u, i, j, _) ->
+ Some (u, succ i, j, 0)
+ | C.AAppl (_, C.AMutConstruct (_, u, i, j, _) :: vs) ->
+ Some (u, succ i, j, List.length vs)
+ | _ ->
+ None
+
+let get_uri_of_apply = function
+ | T.Exact (t, _)
+ | T.Apply (t, _) -> get_uri_of_head t
+ | _ -> None
+
+let is_reflexivity st step =
+ match get_uri_of_apply step with
+ | None -> false
+ | Some (uri, i, j, n) ->
+ st.defaults && Obj.is_eq_URI uri && i = 1 && j = 1 && n = 0
+
+let is_ho_reflexivity st step =
+ match get_uri_of_apply step with
+ | None -> false
+ | Some (uri, i, j, n) ->
+ st.defaults && Obj.is_eq_URI uri && i = 1 && j = 1 && n > 0
+
+let are_convertible st pred sx dx =
+ let pred, sx, dx = H.cic pred, H.cic sx, H.cic dx in
+ let sx, dx = C.Appl [pred; sx], C.Appl [pred; dx] in
+ fst (R.are_convertible st.context sx dx Un.default_ugraph)
+
(* proof construction *******************************************************)
let anonymous_premise = C.Name "UNNAMED"
-let mk_exp_args hd tl classes synth =
- let meta id = C.AImplicit (id, None) in
+let mk_lapply_args hd tl classes =
+ let map _ = Cn.meta "" in
+ let args = List.rev_map map tl in
+ if args = [] then hd else C.AAppl ("", hd :: args)
+
+let mk_apply_args hd tl classes synth qs =
+ let exp = ref 0 in
let map v (cl, b) =
- if I.overlaps synth cl && b then v else meta ""
+ if I.overlaps synth cl
+ then if b then v, v else Cn.meta "", v
+ else Cn.meta "", Cn.meta ""
+ in
+ let rec rev a = function
+ | [] -> a
+ | hd :: tl ->
+ if snd hd <> Cn.meta "" then incr exp;
+ rev (snd hd :: a) tl
in
- let rec aux b = function
- | [] -> b, []
+ let rec aux = function
+ | [] -> []
| hd :: tl ->
- if hd = meta "" then aux true tl else b, List.rev (hd :: tl)
+ if fst hd = Cn.meta "" then aux tl else rev [] (hd :: tl)
in
let args = T.list_rev_map2 map tl classes in
- let b, args = aux false args in
- if args = [] then b, hd else b, C.AAppl ("", hd :: args)
+ let args = aux args in
+ let part = !exp < List.length tl in
+ if args = [] then part, hd, qs else part, C.AAppl ("", hd :: args), qs
let mk_convert st ?name sty ety note =
+ let ppterm t =
+ let a = ref "" in Ut.pp_term (fun s -> a := !a ^ s) [] st.context t; !a
+ in
let e = Cn.hole "" in
let csty, cety = H.cic sty, H.cic ety in
- let script =
+ let note =
if !debug then
let sname = match name with None -> "" | Some (id, _) -> id in
- let note = Printf.sprintf "%s: %s\nSINTH: %s\nEXP: %s"
- note sname (Pp.ppterm csty) (Pp.ppterm cety)
- in
- [T.Note note]
- else []
+ Printf.sprintf "%s: %s\nSINTH: %s\nEXP: %s"
+ note sname (ppterm csty) (ppterm cety)
+ else ""
in
- assert (Ut.is_sober st.context csty);
- assert (Ut.is_sober st.context cety);
- if Ut.alpha_equivalence csty cety then script else
+ if H.alpha ~flatten:true st.context csty cety then [T.Note note] else
let sty, ety = H.acic_bc st.context sty, H.acic_bc st.context ety in
match name with
- | None -> T.Change (sty, ety, None, e, "") :: script
+ | None -> [T.Change (sty, ety, None, e, note)]
| Some (id, i) ->
begin match get_entry st id with
- | C.Def _ -> assert false (* T.ClearBody (id, "") :: script *)
+ | C.Def _ ->
+ [T.Change (ety, sty, Some (id, Some id), e, note);
+ T.ClearBody (id, "")
+ ]
| C.Decl _ ->
- T.Change (ety, sty, Some (id, Some id), e, "") :: script
+ [T.Change (ety, sty, Some (id, Some id), e, note)]
end
let convert st ?name v =
| C.Name s -> Some s
let mk_preamble st what script = match script with
+ | step :: script when is_reflexivity st step ->
+ T.Reflexivity (T.note_of_step step) :: script
+ | step :: script when is_ho_reflexivity st step ->
+ convert st what @ T.Reflexivity (T.note_of_step step) :: script
| T.Exact _ :: _ -> script
| _ -> convert st what @ script
| C.ARel (_, _, i, name) as what -> convert st ~name:(name, i) what
| _ -> []
-let mk_fwd_rewrite st dtext name tl direction v t ity =
+let mk_fwd_rewrite st dtext name tl direction v t ity ety =
let compare premise = function
| None -> true
| Some s -> s = premise
in
assert (List.length tl = 6);
let what, where, predicate = List.nth tl 5, List.nth tl 3, List.nth tl 2 in
- let e = Cn.mk_pattern 1 predicate in
+ let e = Cn.mk_pattern 1 ety predicate in
if (Cn.does_not_occur e) then st, [] else
match where with
| C.ARel (_, _, i, premise) as w ->
end
| _ -> assert false
-let mk_rewrite st dtext where qs tl direction t =
+let mk_rewrite st dtext where qs tl direction t ity =
+ let ppterm t =
+ let a = ref "" in Ut.pp_term (fun s -> a := !a ^ s) [] st.context t; !a
+ in
assert (List.length tl = 5);
- let predicate = List.nth tl 2 in
- let e = Cn.mk_pattern 1 predicate in
+ let pred, sx, dx = List.nth tl 2, List.nth tl 1, List.nth tl 4 in
+ let dtext = if !debug then dtext ^ ppterm (H.cic pred) else dtext in
+ let e = Cn.mk_pattern 1 ity pred in
let script = [T.Branch (qs, "")] in
- if (Cn.does_not_occur e) then script else
+ if Cn.does_not_occur e then script else
+ if st.cr && are_convertible st pred sx dx then
+ let dtext = "convertible rewrite" ^ dtext in
+ let ity, ety, e = Cn.beta sx pred, Cn.beta dx pred, Cn.hole "" in
+ let city, cety = H.cic ity, H.cic ety in
+ if H.alpha ~flatten:true st.context city cety then script else
+ T.Change (ity, ety, None, e, dtext) :: script
+ else
T.Rewrite (direction, where, None, e, dtext) :: script
let rec proc_lambda st what name v t =
+ let dtext = if !debug then CicPp.ppcontext st.context else "" in
let name = match name with
| C.Anonymous -> H.mk_fresh_name true st.context anonymous_premise
| name -> name
let entry = Some (name, C.Decl (H.cic v)) in
let intro = get_intro name in
let script = proc_proof (add st entry) t in
- let script = T.Intros (Some 1, [intro], "") :: script in
+ let script = T.Intros (Some 1, [intro], dtext) :: script in
mk_preamble st what script
and proc_letin st what name v w t =
let intro = get_intro name in
let proceed, dtext = test_depth st in
let script = if proceed then
- let st, hyp, rqv = match get_inner_types st v with
- | Some (ity, _) ->
+ let st, hyp, rqv = match get_inner_types st what, get_inner_types st v with
+ | Some (C.ALetIn (_, _, iv, iw, _), _), _ when
+ H.alpha ~flatten:true st.context (H.cic v) (H.cic iv) &&
+ H.alpha ~flatten:true st.context (H.cic w) (H.cic iw)
+ ->
+ st, C.Def (H.cic v, H.cic w), [T.Intros (Some 1, [intro], dtext)]
+ | _, Some (ity, ety) ->
let st, rqv = match v with
| C.AAppl (_, hd :: tl) when is_fwd_rewrite_right st hd tl ->
- mk_fwd_rewrite st dtext intro tl true v t ity
+ mk_fwd_rewrite st dtext intro tl true v t ity ety
| C.AAppl (_, hd :: tl) when is_fwd_rewrite_left st hd tl ->
- mk_fwd_rewrite st dtext intro tl false v t ity
+ mk_fwd_rewrite st dtext intro tl false v t ity ety
+ | C.AAppl (_, hd :: tl) ->
+ let ty = match get_inner_types st hd with
+ | Some (ity, _) -> H.cic ity
+ | None -> get_type "TC3" st hd
+ in
+ let classes, _ = Cl.classify st.context ty in
+ let parsno, argsno = List.length classes, List.length tl in
+ let decurry = parsno - argsno in
+ if decurry <> 0 then begin
+(* FG: we fall back in the cut case *)
+ assert (Ut.is_sober st.context (H.cic ety));
+ let ety = H.acic_bc st.context ety in
+ let qs = [proc_proof (next st) v; [T.Id ""]] in
+ st, [T.Branch (qs, ""); T.Cut (intro, ety, dtext)]
+ end else
+ let names, synth = get_sub_names hd tl, I.S.empty in
+ let qs = proc_bkd_proofs (next st) synth names classes tl in
+ let hd = mk_lapply_args hd tl classes in
+ let qs = [T.Id ""] :: qs in
+ st, [T.Branch (qs, ""); T.LApply (intro, hd, dtext)]
| v ->
- assert (Ut.is_sober st.context (H.cic ity));
- let ity = H.acic_bc st.context ity in
+ assert (Ut.is_sober st.context (H.cic ety));
+ let ety = H.acic_bc st.context ety in
let qs = [proc_proof (next st) v; [T.Id ""]] in
- st, [T.Branch (qs, ""); T.Cut (intro, ity, dtext)]
+ st, [T.Branch (qs, ""); T.Cut (intro, ety, dtext)]
in
st, C.Decl (H.cic ity), rqv
- | None ->
+ | _, None ->
st, C.Def (H.cic v, H.cic w), [T.LetIn (intro, v, dtext)]
in
let entry = Some (name, hyp) in
in
let classes, rc = Cl.classify st.context ty in
let goal_arity, goal = match get_inner_types st what with
- | None -> 0, None
- | Some (ity, ety) ->
- snd (PEH.split_with_whd (st.context, H.cic ity)), Some (H.cic ety)
+ | None -> 0, None
+ | Some (ity, _) ->
+ snd (PEH.split_with_whd (st.context, H.cic ity)), Some (H.cic ity)
in
let parsno, argsno = List.length classes, List.length tl in
let decurry = parsno - argsno in
let diff = goal_arity - decurry in
- if diff < 0 then failwith (Printf.sprintf "NOT TOTAL: %i %s |--- %s" diff (Pp.ppcontext st.context) (Pp.ppterm (H.cic hd)));
+ if diff < 0 then
+ let text = Printf.sprintf "partial application: %i" diff in
+ prerr_endline ("Procedural 2: " ^ text);
+ [T.Exact (what, dtext ^ text)]
+ else
let classes = Cl.adjust st.context tl ?goal classes in
let rec mk_synth a n =
if n < 0 then a else mk_synth (I.S.add n a) (pred n)
in
let synth = mk_synth I.S.empty decurry in
- let text = "" (* Printf.sprintf "%u %s" parsno (Cl.to_string h) *) in
+ let text = if !debug
+ then Printf.sprintf "%u %s" parsno (Cl.to_string synth (classes, rc))
+ else ""
+ in
let script = List.rev (mk_arg st hd) in
let tactic b t n = if b then T.Apply (t, n) else T.Exact (t, n) in
match rc with
- | Some (i, j, uri, tyno) ->
+ | Some (i, j, uri, tyno) when decurry = 0 ->
let classes2, tl2, _, where = split2_last classes tl in
let script2 = List.rev (mk_arg st where) @ script in
let synth2 = I.S.add 1 synth in
let names = H.get_ind_names uri tyno in
let qs = proc_bkd_proofs (next st) synth2 names classes2 tl2 in
- if List.length qs <> List.length names then
+ let ity = match get_inner_types st what with
+ | Some (ity, _) -> ity
+ | None ->
+ Cn.fake_annotate "" st.context (get_type "TC3" st what)
+ in
+ if List.length qs <> List.length names then
let qs = proc_bkd_proofs (next st) synth [] classes tl in
- let b, hd = mk_exp_args hd tl classes synth in
+ let b, hd, qs = mk_apply_args hd tl classes synth qs in
script @ [tactic b hd (dtext ^ text); T.Branch (qs, "")]
else if is_rewrite_right st hd then
- script2 @ mk_rewrite st dtext where qs tl2 false what
+ script2 @ mk_rewrite st dtext where qs tl2 false what ity
else if is_rewrite_left st hd then
- script2 @ mk_rewrite st dtext where qs tl2 true what
+ script2 @ mk_rewrite st dtext where qs tl2 true what ity
else
let predicate = List.nth tl2 (parsno - i) in
- let e = Cn.mk_pattern j predicate in
+ let e = Cn.mk_pattern j ity predicate in
let using = Some hd in
script2 @
[T.Elim (where, using, e, dtext ^ text); T.Branch (qs, "")]
- | None ->
+ | _ ->
let names = get_sub_names hd tl in
let qs = proc_bkd_proofs (next st) synth names classes tl in
- let b, hd = mk_exp_args hd tl classes synth in
+ let b, hd, qs = mk_apply_args hd tl classes synth qs in
script @ [tactic b hd (dtext ^ text); T.Branch (qs, "")]
else
[T.Exact (what, dtext)]
let ps, _ = H.get_ind_parameters st.context (H.cic v) in
let _, rps = HEL.split_nth lpsno ps in
let rpsno = List.length rps in
- let e = Cn.mk_pattern rpsno u in
+ let ity = match get_inner_types st what with
+ | Some (ity, _) -> ity
+ | None ->
+ Cn.fake_annotate "" st.context (get_type "TC4" st what)
+ in
+ let e = Cn.mk_pattern rpsno ity u in
let text = "" in
let script = List.rev (mk_arg st v) in
script @ [T.Cases (v, e, dtext ^ text); T.Branch (qs, "")]
and proc_proof st t =
let f st =
+(*
let xtypes, note = match get_inner_types st t with
| Some (it, et) -> Some (H.cic it, H.cic et),
(Printf.sprintf "\nInferred: %s\nExpected: %s"
(Pp.ppterm (H.cic it)) (Pp.ppterm (H.cic et)))
| None -> None, "\nNo types"
- in
- let context, _clears = Cn.get_clears st.context (H.cic t) xtypes in
+ in
+ let context, clears = Cn.get_clears st.context (H.cic t) xtypes in
{st with context = context}
+*)
+ st
in
match t with
| C.ALambda (_, name, w, t) as what -> proc_lambda (f st) what name w t
max_depth = List.fold_left depth_map None params;
depth = 0;
defaults = not (List.mem G.IPNoDefaults params);
+ cr = List.mem G.IPCR params;
context = context;
case = []
}