(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
open Names open EConstr open Inductiveops
(* This represents how a term is getting extracted from another term *) type term_extraction =
| Id (* the constructor from which to extract, type of the constructor that is getting extracted, index (1 based) to extract from, further extraction *)
| Extraction of ((constructor * EInstance.t) * EConstr.t * int * term_extraction)
(* this represents how a term is getting composed from an inductive type *) type term_composition = (* env type to compose *)
| FromEnv of EConstr.t (* env type to compose, env parameter term to extract from, index (1 based) of parameter, extraction for the given type*)
| FromParameter of EConstr.t * EConstr.t * int * term_extraction (* env type to compose, index (1 based) index to compose from, extraction for the given type *)
| FromIndex of EConstr.t * int * term_extraction (* composition for f, array of composition for arg *)
| Composition of term_composition * term_composition array
type projection_type = (* simply typed fields *)
| Simple (* dependently typed fields for wich a type term_composition exists *)
| Dependent_Extractable of term_composition (* dependently typed fields for which currently no projection generation is known, simply typed generation is getting tried anyways *)
| NotProjectable
(*get the ith (1 based) argument in a series of prods*) let get_ith_arg sigma i term = let (rels_to_arg, rest) = decompose_prod_n sigma (i-1) term in let (arg_name, arg_type,rest) = destProd sigma rest in
(rels_to_arg, (arg_name, arg_type), rest)
(*determin if the ith (1 based real constructor arguments without parametes) field of a constructor depends on its other fields*) let is_field_i_dependent env sigma cnstr i = let constructor_type = e_type_of_constructor env sigma cnstr in let ind_n_params = inductive_nparams env (fst (fst cnstr)) in let (_, (_, field_type), _) = get_ith_arg sigma (i + ind_n_params) constructor_type in not (Vars.noccur_between sigma 1 (i - 1) field_type)
(*this builds a projection in the simply typed case*) let build_simple_projection env sigma intype cnstr special default = letopen Context in let ci = (snd (fst cnstr)) in let body = Combinators.make_selector env sigma ~pos:ci ~special ~default (mkRel 1) intype in let id = Id.of_string "t"in
mkLambda (make_annot (Name id) ERelevance.relevant, intype, body)
let (let*) m f = match m with
| None -> None
| Some x -> f x
(*find a composition to form a given term by extracting from given terms*) let find_term_composition env sigma cnstr argindex env_field_type ind env_ind_params env_ind_args = (*first we need to get some information about the inductive type*) let env_ind_n_params = Array.length env_ind_params in let rel_type_of_constructor = type_of_constructor env cnstr in let (_, (_, rel_field_type), rel_field_rest) = get_ith_arg sigma (argindex+env_ind_n_params) rel_type_of_constructor in let (rel_target_context, rel_target_type) = decompose_prod sigma rel_field_rest in let rel_field_type_lifted = Vars.lift (List.length rel_target_context + 1) rel_field_type in let (_, rel_args) = decompose_app sigma rel_target_type in let (rel_ind_params, rel_ind_args) = CArray.chop env_ind_n_params rel_args in (*the actual recursive search for the term_composition*) let rec find_term_composition_rec env sigma rel_term_to_compose env_term_to_compose = if isRef sigma rel_term_to_compose then
Some (FromEnv rel_term_to_compose) elsematch find_arg env sigma rel_term_to_compose rel_ind_params env_ind_params with
| Some (i, extraction) ->
Some (FromParameter (env_term_to_compose, env_ind_params.(i-1), i, extraction))
| None -> beginmatch find_arg env sigma rel_term_to_compose rel_ind_args env_ind_args with
| Some (i, extraction) ->
Some (FromIndex (env_term_to_compose, i, extraction))
| None -> beginmatch EConstr.kind sigma rel_term_to_compose with
| App (rel_f,rel_args) -> let (env_f,env_args) = decompose_app sigma env_term_to_compose in let* f_composition = find_term_composition_rec env sigma rel_f env_f in if Array.length env_args != Array.length rel_args then
None else let* args_compositions = let exception ArgNotComposable in letmap i rel_arg = let arg_composition = find_term_composition_rec env sigma rel_arg env_args.(i) in match arg_composition with
| Some arg_composition -> arg_composition
| None -> raise ArgNotComposable in try Some (CArray.mapi map rel_args) with ArgNotComposable -> None in
Some (Composition (f_composition, args_compositions))
| _ -> None end end
(*finds the first argument from which a term can be extracted*) and find_arg env sigma term_to_extract terms_to_extract_from env_types_of_fields = letfind (i, term_to_extract_from) = let* r = find_term_extraction env sigma term_to_extract term_to_extract_from env_types_of_fields.(i) in
Some (i + 1, r) in let rec seq_find_map xs = match xs() with
| Seq.Nil -> None
| Seq.Cons(x,xs) -> matchfind x with
| None -> seq_find_map xs
| Some _ as result -> result in
seq_find_map (Array.to_seqi terms_to_extract_from)
(*finds the term_extraction for a given term*) and find_term_extraction env sigma term_to_extract term_to_extract_from type_of_term_to_extract_from = if eq_constr_nounivs sigma term_to_extract term_to_extract_from then
Some Id elsematch EConstr.kind sigma term_to_extract_from with
| App (f, args) -> beginmatch EConstr.kind sigma f with
| Construct c -> let (_, env_args) = decompose_app sigma type_of_term_to_extract_from in let* (i, extraction_result) = find_arg env sigma term_to_extract args env_args in
Some (Extraction (c, type_of_term_to_extract_from, i, extraction_result))
| _ -> None end
| _ -> None in
find_term_composition_rec env sigma rel_field_type_lifted env_field_type
(*tests if a field is projectable and returns the type_composition if it is*) let projectability_test env sigma cnstr argindex field_type ind ind_params ind_args = let dependent = is_field_i_dependent env sigma cnstr argindex in if dependent then let composition = find_term_composition env sigma cnstr argindex field_type ind ind_params ind_args in match composition with
| Some composition -> Dependent_Extractable composition
| None -> NotProjectable else Simple
(*builds the term of a given term_extraction*) let rec build_term_extraction env sigma default rel_term_to_extract_from env_term_to_extract_from extraction = match extraction with
| Id -> rel_term_to_extract_from (* The term that is getting extracted, the term from wich its getting extracted, The constructor from which zu extract, index (1 based without params) to extract from, further extraction *)
| Extraction ((cnstr, _), env_next_term_to_extract_from, index, next_extraction) -> let cnstr_n_args = constructor_nrealargs env cnstr in let special = build_term_extraction env sigma default (mkRel (cnstr_n_args-(index-1))) env_next_term_to_extract_from next_extraction in let pos = snd cnstr in let (_, match_type) = Typing.type_of env sigma env_term_to_extract_from in
Combinators.make_selector env sigma ~pos ~special ~default rel_term_to_extract_from match_type
(*builds the term of a given term_composition*) let rec build_term_composition env sigma term_composition ind_params n_ind_params ind_args n_ind_args = match term_composition with (* type to compose *)
| FromEnv env_type_to_compose -> env_type_to_compose (* type to compose, parameter term to extract from, index (1 based) of parameter, extraction for the given type*)
| FromParameter (env_type_to_compose, env_parameter_to_extract_from, parameter_index, extraction) -> let type_to_extract_from = ind_params.(parameter_index-1) in
build_term_extraction env sigma env_type_to_compose env_parameter_to_extract_from type_to_extract_from extraction (* type to compose, indec term to extract from, index (1 based) index to compose from, extraction for the given type *)
| FromIndex (env_type_to_compose, index_index, extraction) -> let type_to_extract_from = ind_args.(index_index-1) in
build_term_extraction env sigma env_type_to_compose (mkRel (n_ind_args-(index_index-1))) type_to_extract_from extraction (* (f type to compose, composition for f), array of (arg type to compose, composition for arg)*)
| Composition (f_composition, arg_compositions) -> let f_extraction_term = build_term_composition env sigma f_composition ind_params n_ind_params ind_args n_ind_args in letmap arg_composition = build_term_composition env sigma arg_composition ind_params n_ind_params ind_args n_ind_args in let arg_extraction_terms = Array.mapmap arg_compositions in
mkApp (f_extraction_term, arg_extraction_terms)
(*replaces all rel variables corresponding to indices in a match statment with the index definition in the inductive definition*) let match_indices env sigma cnst_summary term_to_match n_ind_args max_free_rel = let rec replace_rec n t = match EConstr.kind sigma t with
| Rel i -> if i <= n_ind_args + n && i > n then
cnst_summary.cs_concl_realargs.(n_ind_args-i) else t
| _ -> EConstr.map_with_binders sigma (fun n -> n+1) replace_rec n t in
EConstr.map_with_binders sigma (fun n -> n+1) replace_rec 0 term_to_match
let make_annot_numbered s i r =
Context.make_annot (Name.mk_name (Nameops.make_ident s i)) r
(*makes a match statement where the index variables in the branches get replaced by the index definitions inside the inductive definition*) let make_selector_match_indices env sigma ~pos ~special c (ind_fam, ind_args) return_type composition_type_template = let n_ind_args = List.length ind_args in let indt = IndType (ind_fam, ind_args) in let (ind, _),_ = dest_ind_family ind_fam in let () = Tacred.check_privacy env ind in let (_, mip) = Inductive.lookup_mind_specif env ind in let deparsign = make_arity_signature env sigma true ind_fam in let p = it_mkLambda_or_LetIn return_type deparsign in let cstrs = get_constructors env ind_fam in let build_branch i = let max_free_rel = Option.default 0 (Int.Set.max_elt_opt (Termops.free_rels sigma composition_type_template)) in let matched_template = match_indices env sigma cstrs.(i-1) composition_type_template n_ind_args max_free_rel in let endpt = if Int.equal i pos then
mkLambda (Context.make_annot Name.Anonymous ERelevance.relevant, matched_template, Vars.lift 1 special) else
mkLambda (make_annot_numbered "t" None ERelevance.relevant, matched_template, mkRel 1) in let args = cstrs.(i-1).cs_args in
it_mkLambda_or_LetIn endpt args in let brl = List.map build_branch(CList.interval 1 (Array.length mip.mind_consnames)) in let rci = ERelevance.relevant in(* TODO relevance *) let ci = make_case_info env ind RegularStyle in
make_case_or_project env sigma indt ci (p, rci) c (Array.of_list brl)
(*builds a projection in the dependently typed case where a term_composition was found for the fields type*) let build_dependent_projection_with_term_composition env sigma cnstr default special argty term_composition ((ind, ind_params) as ind_fam) ind_args = let n_ind_params = List.length ind_params in let n_ind_args = List.length ind_args in let composition_type_template = build_term_composition env sigma term_composition (Array.of_list ind_params) n_ind_params (Array.of_list ind_args) n_ind_args in let return_type = Vars.lift 1 (
mkProd (Context.make_annot Name.Anonymous ERelevance.relevant, composition_type_template, Vars.lift 1 composition_type_template)
) in let e_match = make_selector_match_indices env sigma ~pos:(snd (fst cnstr)) ~special (mkRel 1) (make_ind_family ind_fam, ind_args) return_type composition_type_template in let match_default = mkApp (e_match, [|default|]) in let proj = mkLambda (make_annot_numbered "e" None ERelevance.relevant, argty, match_default) in
proj
(*checks the projectability of the given field and builds the according projection. If the field is found to be NotProjectable the simply typed projection generation is tried*) let build_projection env sigma
cnstr (*constructor that is getting projected*)
argindex (*1 based index of the field to project counted from left without induction params*)
field_type (*type of the field that gets projected*)
default (*p.p_lhs so the thing inside the constructor*)
special (*Rel (nargs-argind+1) so the debrujin index of the field to project directly after binding*)
argty (*type of the constructor term that is getting projected*) = let IndType (ind_family,ind_args) = try find_rectype env sigma argty with Not_found ->
CErrors.user_err
Pp.(str "Cannot discriminate on inductive constructors with \
dependent types.") in let (ind, ind_params) = dest_ind_family ind_family in let cnstr = (fst cnstr, EInstance.make (snd cnstr)) in let proj_result = projectability_test env sigma cnstr argindex field_type ind (Array.of_list ind_params) (Array.of_list ind_args) in match proj_result with
| Simple | NotProjectable -> let p = build_simple_projection env sigma argty cnstr special default in
sigma, p
| Dependent_Extractable type_composition -> let p = build_dependent_projection_with_term_composition env sigma cnstr default special argty type_composition (ind, ind_params) ind_args in
sigma, p
Messung V0.5
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.