diff options
author | msozeau <msozeau@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2012-03-14 09:52:41 +0000 |
---|---|---|
committer | msozeau <msozeau@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2012-03-14 09:52:41 +0000 |
commit | 2053e46c8d6a4da32b4155d346d1b04da3686d06 (patch) | |
tree | 13113d33071207f1c0133416374b0f8b72e21352 /pretyping | |
parent | 1b3efc6dc25be1bfde5fb7d2d39cc5c35e44a4d8 (diff) |
Everything compiles again.
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@15034 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'pretyping')
-rw-r--r-- | pretyping/cases.ml | 192 | ||||
-rw-r--r-- | pretyping/cases.mli | 62 | ||||
-rw-r--r-- | pretyping/pretyping.ml | 29 | ||||
-rw-r--r-- | pretyping/program.ml | 84 |
4 files changed, 277 insertions, 90 deletions
diff --git a/pretyping/cases.ml b/pretyping/cases.ml index 8652dbd03..ef65f2d8f 100644 --- a/pretyping/cases.ml +++ b/pretyping/cases.ml @@ -507,14 +507,15 @@ let occur_in_rhs na rhs = | Name id -> List.mem id rhs.rhs_vars let is_dep_patt_in eqn = function - | PatVar (_,name) -> occur_in_rhs name eqn.rhs + | PatVar (_,name) -> Flags.is_program_mode () || occur_in_rhs name eqn.rhs | PatCstr _ -> true let mk_dep_patt_row (pats,_,eqn) = List.map (is_dep_patt_in eqn) pats let dependencies_in_pure_rhs nargs eqns = - if eqns = [] then list_make nargs false (* Only "_" patts *) else + if eqns = [] && not (Flags.is_program_mode ()) then + list_make nargs false (* Only "_" patts *) else let deps_rows = List.map mk_dep_patt_row eqns in let deps_columns = matrix_transpose deps_rows in List.map (List.exists ((=) true)) deps_columns @@ -1321,7 +1322,7 @@ and compile_alias pb (na,orig,(expanded,expanded_typ)) rest = else mkLetIn (na,c,t,j.uj_val); uj_type = subst1 c j.uj_type } in - if isRel orig or isVar orig then + if not (Flags.is_program_mode ()) && (isRel orig or isVar orig) then (* Try to compile first using non expanded alias *) try f orig (Retyping.get_type_of pb.env !(pb.evdref) orig) with e when precatchable_exception e -> @@ -1784,7 +1785,7 @@ let prepare_predicate loc typing_fun sigma env tomatchs arsign tycon pred = sigma,nal,pred) preds -module ProgramCases = struct +(** Program cases *) open Program @@ -1833,7 +1834,8 @@ let constr_of_pat env isevars arsign pat avoid = let previd, id = prime avoid (Name (id_of_string "wildcard")) in Name id, id :: avoid in - PatVar (l, name), [name, None, ty] @ realargs, mkRel 1, ty, (List.map (fun x -> mkRel 1) realargs), 1, avoid + (PatVar (l, name), [name, None, ty] @ realargs, mkRel 1, ty, + (List.map (fun x -> mkRel 1) realargs), 1, avoid) | PatCstr (l,((_, i) as cstr),args,alias) -> let cind = inductive_of_constructor cstr in let IndType (indf, _) = @@ -1851,7 +1853,8 @@ let constr_of_pat env isevars arsign pat avoid = List.fold_right2 (fun (na, c, t) ua (patargs, args, sign, env, n, m, avoid) -> let pat', sign', arg', typ', argtypargs, n', avoid = - typ env (substl args (liftn (List.length sign) (succ (List.length args)) t), []) ua avoid + let liftt = liftn (List.length sign) (succ (List.length args)) t in + typ env (substl args liftt, []) ua avoid in let args' = arg' :: List.map (lift n') args in let env' = push_rels sign' env in @@ -1875,7 +1878,8 @@ let constr_of_pat env isevars arsign pat avoid = let sign, i, avoid = try let env = push_rels sign env in - isevars := the_conv_x_leq (push_rels sign env) (lift (succ m) ty) (lift 1 apptype) !isevars; + isevars := the_conv_x_leq (push_rels sign env) + (lift (succ m) ty) (lift 1 apptype) !isevars; let eq_t = mk_eq (lift (succ m) ty) (mkRel 1) (* alias *) (lift 1 app) (* aliased term *) @@ -1928,7 +1932,8 @@ let rec is_included x y = if i = i' then List.for_all2 is_included args args' else false -(* liftsign is the current pattern's complete signature length. Hence pats is already typed in its +(* liftsign is the current pattern's complete signature length. + Hence pats is already typed in its full signature. However prevpatterns are in the original one signature per pattern form. *) let build_ineqs prevpatterns pats liftsign = @@ -1964,13 +1969,13 @@ let build_ineqs prevpatterns pats liftsign = in match acc with None -> c | Some (sign, len, _, c') -> - let conj = it_mkProd_or_LetIn (mk_coq_not (mk_coq_conj c')) + let conj = it_mkProd_or_LetIn (mk_coq_not (mk_coq_and c')) (lift_rel_context liftsign sign) in conj :: c) [] prevpatterns in match diffs with [] -> None - | _ -> Some (mk_coq_conj diffs) + | _ -> Some (mk_coq_and diffs) let subst_rel_context k ctx subst = let (_, ctx') = @@ -2009,14 +2014,16 @@ let constrs_of_pats typing_fun env isevars eqns tomatchs sign neqs arity = let len = List.length sign' in (sign' @ renv, (* lift to get outside of previous pattern's signatures. *) - (sign', liftn n (succ len) c, (s, List.map (liftn n (succ len)) args), p) :: pats, + (sign', liftn n (succ len) c, + (s, List.map (liftn n (succ len)) args), p) :: pats, len + n)) ([], [], 0) opats in let pats, _ = List.fold_left (* lift to get outside of past patterns to get terms in the combined environment. *) (fun (pats, n) (sign, c, (s, args), p) -> let len = List.length sign in - ((rels_of_patsign sign, lift n c, (s, List.map (lift n) args), p) :: pats, len + n)) + ((rels_of_patsign sign, lift n c, + (s, List.map (lift n) args), p) :: pats, len + n)) ([], 0) pats in let ineqs = build_ineqs prevpatterns pats signlen in @@ -2077,7 +2084,9 @@ let constrs_of_pats typing_fun env isevars eqns tomatchs sign neqs arity = let lift_ctx n ctx = let ctx', _ = - List.fold_right (fun (c, t) (ctx, n') -> (liftn n n' c, liftn_tomatch_type n n' t) :: ctx, succ n') ctx ([], 0) + List.fold_right (fun (c, t) (ctx, n') -> + (liftn n n' c, liftn_tomatch_type n n' t) :: ctx, succ n') + ctx ([], 0) in ctx' (* Turn matched terms into variables. *) @@ -2117,70 +2126,70 @@ let build_dependent_signature env evars avoid tomatchs arsign = new arity signatures *) match ty with - IsInd (ty, IndType (indf, args), _) when List.length args > 0 -> - (* Build the arity signature following the names in matched terms as much as possible *) - let argsign = List.tl arsign in (* arguments in inverse application order *) - let (appn, appb, appt) as _appsign = List.hd arsign in (* The matched argument *) - let argsign = List.rev argsign in (* arguments in application order *) - let env', nargeqs, argeqs, refl_args, slift, argsign' = - List.fold_left2 - (fun (env, nargeqs, argeqs, refl_args, slift, argsign') arg (name, b, t) -> - let argt = Retyping.get_type_of env evars arg in - let eq, refl_arg = - if Reductionops.is_conv env evars argt t then - (mk_eq (lift (nargeqs + slift) argt) - (mkRel (nargeqs + slift)) - (lift (nargeqs + nar) arg), - mk_eq_refl argt arg) - else - (mk_JMeq (lift (nargeqs + slift) t) - (mkRel (nargeqs + slift)) - (lift (nargeqs + nar) argt) - (lift (nargeqs + nar) arg), - mk_JMeq_refl argt arg) - in - let previd, id = - let name = - match kind_of_term arg with - Rel n -> pi1 (lookup_rel n env) - | _ -> name - in - make_prime avoid name + | IsInd (ty, IndType (indf, args), _) when List.length args > 0 -> + (* Build the arity signature following the names in matched terms + as much as possible *) + let argsign = List.tl arsign in (* arguments in inverse application order *) + let (appn, appb, appt) as _appsign = List.hd arsign in (* The matched argument *) + let argsign = List.rev argsign in (* arguments in application order *) + let env', nargeqs, argeqs, refl_args, slift, argsign' = + List.fold_left2 + (fun (env, nargeqs, argeqs, refl_args, slift, argsign') arg (name, b, t) -> + let argt = Retyping.get_type_of env evars arg in + let eq, refl_arg = + if Reductionops.is_conv env evars argt t then + (mk_eq (lift (nargeqs + slift) argt) + (mkRel (nargeqs + slift)) + (lift (nargeqs + nar) arg), + mk_eq_refl argt arg) + else + (mk_JMeq (lift (nargeqs + slift) t) + (mkRel (nargeqs + slift)) + (lift (nargeqs + nar) argt) + (lift (nargeqs + nar) arg), + mk_JMeq_refl argt arg) + in + let previd, id = + let name = + match kind_of_term arg with + Rel n -> pi1 (lookup_rel n env) + | _ -> name in - (env, succ nargeqs, - (Name (eq_id avoid previd), None, eq) :: argeqs, - refl_arg :: refl_args, - pred slift, - (Name id, b, t) :: argsign')) - (env, neqs, [], [], slift, []) args argsign - in - let eq = mk_JMeq - (lift (nargeqs + slift) appt) - (mkRel (nargeqs + slift)) - (lift (nargeqs + nar) ty) - (lift (nargeqs + nar) tm) - in - let refl_eq = mk_JMeq_refl ty tm in - let previd, id = make_prime avoid appn in - (((Name (eq_id avoid previd), None, eq) :: argeqs) :: eqs, - succ nargeqs, - refl_eq :: refl_args, - pred slift, - (((Name id, appb, appt) :: argsign') :: arsigns)) - - | _ -> - (* Non dependent inductive or not inductive, just use a regular equality *) - let (name, b, typ) = match arsign with [x] -> x | _ -> assert(false) in - let previd, id = make_prime avoid name in - let arsign' = (Name id, b, typ) in - let tomatch_ty = type_of_tomatch ty in - let eq = - mk_eq (lift nar tomatch_ty) - (mkRel slift) (lift nar tm) - in - ([(Name (eq_id avoid previd), None, eq)] :: eqs, succ neqs, - (mk_eq_refl tomatch_ty tm) :: refl_args, - pred slift, (arsign' :: []) :: arsigns)) + make_prime avoid name + in + (env, succ nargeqs, + (Name (eq_id avoid previd), None, eq) :: argeqs, + refl_arg :: refl_args, + pred slift, + (Name id, b, t) :: argsign')) + (env, neqs, [], [], slift, []) args argsign + in + let eq = mk_JMeq + (lift (nargeqs + slift) appt) + (mkRel (nargeqs + slift)) + (lift (nargeqs + nar) ty) + (lift (nargeqs + nar) tm) + in + let refl_eq = mk_JMeq_refl ty tm in + let previd, id = make_prime avoid appn in + (((Name (eq_id avoid previd), None, eq) :: argeqs) :: eqs, + succ nargeqs, + refl_eq :: refl_args, + pred slift, + (((Name id, appb, appt) :: argsign') :: arsigns)) + + | _ -> (* Non dependent inductive or not inductive, just use a regular equality *) + let (name, b, typ) = match arsign with [x] -> x | _ -> assert(false) in + let previd, id = make_prime avoid name in + let arsign' = (Name id, b, typ) in + let tomatch_ty = type_of_tomatch ty in + let eq = + mk_eq (lift nar tomatch_ty) + (mkRel slift) (lift nar tm) + in + ([(Name (eq_id avoid previd), None, eq)] :: eqs, succ neqs, + (mk_eq_refl tomatch_ty tm) :: refl_args, + pred slift, (arsign' :: []) :: arsigns)) ([], 0, [], nar, []) tomatchs arsign in let arsign'' = List.rev arsign' in @@ -2190,11 +2199,12 @@ let build_dependent_signature env evars avoid tomatchs arsign = let context_of_arsign l = let (x, _) = List.fold_right (fun c (x, n) -> - (lift_rel_context n c @ x, List.length c + n)) + (lift_rel_context n c @ x, List.length c + n)) l ([], 0) in x -let compile_program_cases loc style (typing_function, evdref) tycon env (predopt, tomatchl, eqns) = +let compile_program_cases loc style (typing_function, evdref) tycon env + (predopt, tomatchl, eqns) = let typing_fun tycon env = function | Some t -> typing_function tycon env evdref t | None -> coq_unit_judge () in @@ -2253,15 +2263,34 @@ let compile_program_cases loc style (typing_function, evdref) tycon env (predopt (* We push the initial terms to match and push their alias to rhs' envs *) (* names of aliases will be recovered from patterns (hence Anonymous here) *) - let initial_pushed = List.map (fun tm -> Pushed (tm,[],Anonymous)) tomatchs in + let out_tmt na = function NotInd (c,t) -> (na,c,t) | IsInd (typ,_,_) -> (na,None,typ) in + let typs = List.map2 (fun na (tm,tmt) -> (tm,out_tmt na tmt)) nal tomatchs in + + let typs = + List.map (fun (c,d) -> (c,extract_inductive_data env !evdref d,d)) typs in + + let dep_sign = + find_dependencies_signature + (list_make (List.length typs) true) + typs in + + let typs' = + list_map3 + (fun (tm,tmt) deps na -> + let deps = if not (isRel tm) then [] else deps in + ((tm,tmt),deps,na)) + tomatchs dep_sign nal in + + let initial_pushed = List.map (fun x -> Pushed x) typs' in + let typing_function tycon env evdref = function | Some t -> typing_function tycon env evdref t | None -> coq_unit_judge () in let pb = { env = env; - evdref = evdref; + evdref = evdref; pred = pred; tomatch = initial_pushed; history = start_history (List.length initial_pushed); @@ -2278,14 +2307,13 @@ let compile_program_cases loc style (typing_function, evdref) tycon env (predopt { uj_val = it_mkLambda_or_LetIn body tomatchs_lets; uj_type = nf_evar !evdref tycon; } in j -end (**************************************************************************) (* Main entry of the matching compilation *) let compile_cases loc style (typing_fun, evdref) tycon env (predopt, tomatchl, eqns) = if predopt = None && Flags.is_program_mode () then - ProgramCases.compile_program_cases loc style (typing_fun, evdref) + compile_program_cases loc style (typing_fun, evdref) tycon env (predopt, tomatchl, eqns) else diff --git a/pretyping/cases.mli b/pretyping/cases.mli index 39677f38b..d0dd870de 100644 --- a/pretyping/cases.mli +++ b/pretyping/cases.mli @@ -55,3 +55,65 @@ val compile_cases : env -> glob_constr option * tomatch_tuples * cases_clauses -> unsafe_judgment +val constr_of_pat : + Environ.env -> + Evd.evar_map ref -> + Term.rel_declaration list -> + Glob_term.cases_pattern -> + Names.identifier list -> + Glob_term.cases_pattern * + (Term.rel_declaration list * Term.constr * + (Term.types * Term.constr list) * Glob_term.cases_pattern) * + Names.identifier list + +type 'a rhs = + { rhs_env : env; + rhs_vars : identifier list; + avoid_ids : identifier list; + it : 'a option} + +type 'a equation = + { patterns : cases_pattern list; + rhs : 'a rhs; + alias_stack : name list; + eqn_loc : loc; + used : bool ref } + +type 'a matrix = 'a equation list + +(* 1st argument of IsInd is the original ind before extracting the summary *) +type tomatch_type = + | IsInd of types * inductive_type * name list + | NotInd of constr option * types + +type tomatch_status = + | Pushed of ((constr * tomatch_type) * int list * name) + | Alias of (name * constr * (constr * types)) + | NonDepAlias + | Abstract of int * rel_declaration + +type tomatch_stack = tomatch_status list + +(* We keep a constr for aliases and a cases_pattern for error message *) + +type pattern_history = + | Top + | MakeConstructor of constructor * pattern_continuation + +and pattern_continuation = + | Continuation of int * cases_pattern list * pattern_history + | Result of cases_pattern list + +type 'a pattern_matching_problem = + { env : env; + evdref : evar_map ref; + pred : constr; + tomatch : tomatch_stack; + history : pattern_continuation; + mat : 'a matrix; + caseloc : loc; + casestyle : case_style; + typing_function: type_constraint -> env -> evar_map ref -> 'a option -> unsafe_judgment } + + +val compile : 'a pattern_matching_problem -> Environ.unsafe_judgment diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml index e75dfcca8..2bbadfded 100644 --- a/pretyping/pretyping.ml +++ b/pretyping/pretyping.ml @@ -315,6 +315,15 @@ let rec pretype (tycon : type_constraint) env evdref lvar = function let ftys = array_map2 (fun e a -> it_mkProd_or_LetIn a e) ctxtv lara in let nbfix = Array.length lar in let names = Array.map (fun id -> Name id) names in + let _ = + match tycon with + | Some t -> + let fixi = match fixkind with + | GFix (vn,i) -> i + | GCoFix i -> i + in e_conv env evdref ftys.(fixi) t + | None -> true + in (* Note: bodies are not used by push_rec_types, so [||] is safe *) let newenv = push_rec_types (names,ftys,[||]) env in let vdefj = @@ -341,11 +350,12 @@ let rec pretype (tycon : type_constraint) env evdref lvar = function but doing it properly involves delta-reduction, and it finally doesn't seem worth the effort (except for huge mutual fixpoints ?) *) - let possible_indexes = Array.to_list (Array.mapi - (fun i (n,_) -> match n with - | Some n -> [n] - | None -> list_map_i (fun i _ -> i) 0 ctxtv.(i)) - vn) + let possible_indexes = + Array.to_list (Array.mapi + (fun i (n,_) -> match n with + | Some n -> [n] + | None -> list_map_i (fun i _ -> i) 0 ctxtv.(i)) + vn) in let fixdecls = (names,ftys,fdefs) in let indexes = search_guard loc env possible_indexes fixdecls in @@ -489,10 +499,12 @@ let rec pretype (tycon : type_constraint) env evdref lvar = function in let cstrs = get_constructors env indf in if Array.length cstrs <> 1 then - user_err_loc (loc,"",str "Destructing let is only for inductive types with one constructor."); + user_err_loc (loc,"",str "Destructing let is only for inductive types" ++ + str " with one constructor."); let cs = cstrs.(0) in if List.length nal <> cs.cs_nargs then - user_err_loc (loc,"", str "Destructing let on this type expects " ++ int cs.cs_nargs ++ str " variables."); + user_err_loc (loc,"", str "Destructing let on this type expects " ++ + int cs.cs_nargs ++ str " variables."); let fsign = List.map2 (fun na (_,c,t) -> (na,c,t)) (List.rev nal) cs.cs_args in let env_f = push_rels fsign env in @@ -636,7 +648,8 @@ let rec pretype (tycon : type_constraint) env evdref lvar = function with Reduction.NotConvertible -> error_actual_type_loc loc env !evdref cj tval end - else user_err_loc (loc,"",str "Cannot check cast with vm: unresolved arguments remain.") + else user_err_loc (loc,"",str "Cannot check cast with vm: " ++ + str "unresolved arguments remain.") | _ -> inh_conv_coerce_to_tycon loc env evdref cj (mk_tycon tval) in let v = mkCast (cj.uj_val, k, tval) in diff --git a/pretyping/program.ml b/pretyping/program.ml new file mode 100644 index 000000000..bb0cbe1c7 --- /dev/null +++ b/pretyping/program.ml @@ -0,0 +1,84 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2010 *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +open Pp +open Errors +open Util +open Names +open Term +open Reductionops +open Environ +open Typeops +open Pretype_errors +open Classops +open Recordops +open Evarutil +open Evarconv +open Retyping +open Evd +open Termops + +type message = string + +let make_dir l = make_dirpath (List.map id_of_string (List.rev l)) + +let find_reference locstr dir s = + let sp = Libnames.make_path (make_dir dir) (id_of_string s) in + try Nametab.global_of_path sp + with Not_found -> anomaly (locstr^": cannot find "^(Libnames.string_of_path sp)) + +let coq_reference locstr dir s = find_reference locstr ("Coq"::dir) s +let coq_constant locstr dir s = Libnames.constr_of_global (coq_reference locstr dir s) + +let init_constant dir s () = coq_constant "Program" dir s +let init_reference dir s () = coq_reference "Program" dir s + +let sig_typ = init_constant ["Init"; "Specif"] "sig" +let sig_intro = init_constant ["Init"; "Specif"] "exist" +let sig_proj1 = init_constant ["Init"; "Specif"] "proj1_sig" + +let sigT_typ = init_constant ["Init"; "Specif"] "sigT" +let sigT_intro = init_constant ["Init"; "Specif"] "existT" +let sigT_proj1 = init_constant ["Init"; "Specif"] "projT1" +let sigT_proj2 = init_constant ["Init"; "Specif"] "projT2" + +let prod_typ = init_constant ["Init"; "Datatypes"] "prod" +let prod_intro = init_constant ["Init"; "Datatypes"] "pair" +let prod_proj1 = init_constant ["Init"; "Datatypes"] "fst" +let prod_proj2 = init_constant ["Init"; "Datatypes"] "snd" + +let coq_eq_ind = init_constant ["Init"; "Logic"] "eq" +let coq_eq_refl = init_constant ["Init"; "Logic"] "eq_refl" +let coq_eq_refl_ref = init_reference ["Init"; "Logic"] "eq_refl" +let coq_eq_rect = init_constant ["Init"; "Logic"] "eq_rect" + +let coq_JMeq_ind = init_constant ["Logic";"JMeq"] "JMeq" +let coq_JMeq_refl = init_constant ["Logic";"JMeq"] "JMeq_refl" + +let coq_not = init_constant ["Init";"Logic"] "not" +let coq_and = init_constant ["Init";"Logic"] "and" + +let mk_coq_not x = mkApp (delayed_force coq_not, [| x |]) + +let unsafe_fold_right f = function + hd :: tl -> List.fold_right f tl hd + | [] -> raise (Invalid_argument "unsafe_fold_right") + +let mk_coq_and l = + let and_typ = delayed_force coq_and in + unsafe_fold_right + (fun c conj -> + mkApp (and_typ, [| c ; conj |])) + l + +let with_program f c = + let mode = !Flags.program_mode in + Flags.program_mode := true; + let res = f c in + Flags.program_mode := mode; + res |