X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2Fsoftware%2Fcomponents%2Facic_procedural%2Fprocedural2.ml;h=ff8f864eabb31320e8af90737ae1501be4085434;hb=ddd6560f4e70ec3306d223738a441d5f1dd3eac9;hp=958fc4abbd0f80b5db55d89c48872193859260b0;hpb=d3548c16f481b14ce94e64c790bc767c59590050;p=helm.git diff --git a/helm/software/components/acic_procedural/procedural2.ml b/helm/software/components/acic_procedural/procedural2.ml index 958fc4abb..ff8f864ea 100644 --- a/helm/software/components/acic_procedural/procedural2.ml +++ b/helm/software/components/acic_procedural/procedural2.ml @@ -26,6 +26,7 @@ module C = Cic module I = CicInspect module S = CicSubstitution +module R = CicReduction module TC = CicTypeChecker module Un = CicUniv module UM = UriManager @@ -53,6 +54,7 @@ type status = { max_depth: int option; depth : int; defaults : bool; + cr : bool; context : C.context; case : int list } @@ -135,19 +137,10 @@ let get_inner_types st v = 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" - -let is_proof st v = -try - let id = Ut.id_of_annterm v in - try match Hashtbl.find st.sorts id with - | `Prop -> true - | _ -> false - with Not_found -> H.is_proof st.context (H.cic v) -with Invalid_argument _ -> failwith "P1.is_proof" +with Invalid_argument _ -> failwith "P2.get_inner_types" let get_entry st id = let rec aux = function @@ -176,47 +169,101 @@ let get_sub_names head l = 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 aux b = function - | [] -> b, [] + let rec rev a = function + | [] -> a | hd :: tl -> - if hd = meta "" then aux true tl else b, List.rev (hd :: tl) + if snd hd <> Cn.meta "" then incr exp; + rev (snd hd :: a) tl + in + let rec aux = function + | [] -> [] + | 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 = @@ -230,6 +277,10 @@ let get_intro = function | 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 @@ -237,14 +288,14 @@ let mk_arg st = function | 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 -> @@ -265,15 +316,27 @@ let mk_fwd_rewrite st dtext name tl direction v t ity = 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 @@ -281,28 +344,53 @@ let rec proc_lambda st what name v t = 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 @@ -338,47 +426,59 @@ and proc_appl st what hd tl = 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)] @@ -395,7 +495,12 @@ and proc_case st what uri tyno u v ts = 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, "")] @@ -412,14 +517,17 @@ and proc_other st what = 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 @@ -458,48 +566,7 @@ try with Invalid_argument s -> failwith ("A2P.proc_bkd_proofs: " ^ s) -(* object costruction *******************************************************) - -let th_flavours = [`Theorem; `Lemma; `Remark; `Fact] - -let def_flavours = [`Definition; `Variant] - -let get_flavour st v attrs = - let rec aux = function - | [] -> - if is_proof st v then List.hd th_flavours else List.hd def_flavours - | `Flavour fl :: _ -> fl - | _ :: tl -> aux tl - in - let flavour_map x y = match x, y with - | None, G.IPAs flavour -> Some flavour - | _ -> x - in - match List.fold_left flavour_map None st.params with - | Some fl -> fl - | None -> aux attrs - -let proc_obj ?(info="") st = function - | C.AConstant (_, _, s, Some v, t, [], attrs) -> - begin match get_flavour st v attrs with - | flavour when List.mem flavour th_flavours -> - let ast = proc_proof st v in - let steps, nodes = T.count_steps 0 ast, T.count_nodes 0 ast in - let text = Printf.sprintf "%s\n%s%s: %u\n%s: %u\n%s" - "COMMENTS" info "Tactics" steps "Final nodes" nodes "END" - in - T.Statement (flavour, Some s, t, None, "") :: ast @ [T.Qed text] - | flavour when List.mem flavour def_flavours -> - [T.Statement (flavour, Some s, t, Some v, "")] - | _ -> - failwith "not a theorem, definition, axiom or inductive type" - end - | C.AConstant (_, _, s, None, t, [], attrs) -> - [T.Statement (`Axiom, Some s, t, None, "")] - | C.AInductiveDefinition (_, types, [], lpsno, attrs) -> - [T.Inductive (types, lpsno, "")] - | _ -> - failwith "not a theorem, definition, axiom or inductive type" +(* initialization ***********************************************************) let init ~ids_to_inner_sorts ~ids_to_inner_types params context = let depth_map x y = match x, y with @@ -513,6 +580,7 @@ let init ~ids_to_inner_sorts ~ids_to_inner_types params context = 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 = [] }