LibBindingThis file contain a lightweight API for meta-programming: to traverse binders and either keep them, create new ones.
With this API, variables are refered abstractly using access_key. For instance, to compute the term associated to a variable (debruijn variable) one should use get_term : acces_key -> constr t. Such terms can easily be created using the monadic bind: let* t = get_term k in ....
So that the users do not have to create access_key themselves, and make mistakes, the creation of access_key is directly handled by the functions creating binders. For instance, to create a product Prod A B, the body B has type access_key -> constr t where the access_key of the variable A. To easily write code, it recomended to use the notation let@: let@ key_A = make_binder naming na A in (* def of B : constr t *) .
It also provides facilities for naming variables, the different functions taking type naming_scheme = rel_declaration -> rel_declaration t as arguments. A few basic ones are provided.
To do so, the API uses a reader monad with a state that contains:
module State : sig ... endval fold_right_state : ('c -> 'b list -> 'b list) -> 'a list -> (int -> 'a -> ('c -> 'd State.t) -> 'd State.t) -> ('b list -> 'd State.t) -> 'd State.tThis function is meant to iterate a function creating binders. 'c -> 'b list -> 'b list explains which access_key to save, e.g. :: to save them all.
val fold_left_state : ('c -> 'b list -> 'b list) -> 'a list -> (int -> 'a -> ('c -> 'd State.t) -> 'd State.t) -> ('b list -> 'd State.t) -> 'd State.tThis function is meant to iterate a function creating binders: int -> 'a -> ('c -> 'd t) -> 'd t. 'c -> 'b list -> 'b list explains which access_key to save, e.g. :: to save them all.
val fold_right_state_3 : ('c -> 'b list -> 'b list) -> 'a list -> (int -> 'a -> (('c * 'c * 'c) -> 'd State.t) -> 'd State.t) -> (('b list * 'b list * 'b list) -> 'd State.t) -> 'd State.tThis function is meant to iterate a function creating binders. 'c -> 'b list -> 'b list explains which access_key to save, e.g. :: to save them all.
val fold_left_state_3 : ('c -> 'b list -> 'b list) -> 'a list -> (int -> 'a -> (('c * 'c * 'c) -> 'd State.t) -> 'd State.t) -> (('b list * 'b list * 'b list) -> 'd State.t) -> 'd State.tThis function is meant to iterate a function creating binders: int -> 'a -> ('c -> 'd t) -> 'd t. 'c -> 'b list -> 'b list explains which access_key to save, e.g. :: to save them all.
type naming_scheme = EConstr.rel_declaration -> EConstr.rel_declaration State.tval naming_id : naming_schemeIdentity namming
val naming_hd : naming_schemeName the binder using the head of the declaration's type if it Anonymous.
val naming_hd_dep : bool -> naming_schemenaming_dep if true, naming_id otherwise
val naming_hd_fresh : naming_schemeUses the next fresh names available, using the head of the declaration's type if it Anonymous.
val naming_hd_fresh_dep : bool -> naming_schemenaming_hd_fresh if true, naming_id otherwise
val add_decl : freshness -> naming_scheme -> EConstr.rel_declaration -> (access_key -> 'a State.t) -> 'a State.tAdd a declaration to the state given its freshness and a naming_scheme, for a body defined in the updated state.
val build_binder : binder -> freshness -> naming_scheme -> EConstr.rel_declaration -> (access_key -> EConstr.constr State.t) -> EConstr.constr State.tBind a declaration with binder or LetIn, given its freshness and a naming_scheme, for a body defined in the updated state.
val make_binder : binder -> naming_scheme -> Names.Name.t EConstr.binder_annot -> EConstr.types -> (access_key -> EConstr.constr State.t) -> EConstr.constr State.tCreate a new binder using a naming_scheme, for a body in the updated state. When creating a fresh binder, the type of the variable needs to type check in the current context.
val keep_binder : binder -> naming_scheme -> Names.Name.t EConstr.binder_annot -> EConstr.types -> (access_key -> EConstr.constr State.t) -> EConstr.constr State.tKeep a former binder using a naming_scheme, for a body defined in the updated state.
val build_binder_opt : binder -> freshness -> naming_scheme -> EConstr.rel_declaration -> (access_key -> EConstr.constr option State.t) -> EConstr.constr option State.tBind a declaration with binder or LetIn, given its freshness and a naming_scheme, for an optional body defined in the updated state.
val make_binder_opt : binder -> naming_scheme -> Names.Name.t EConstr.binder_annot -> EConstr.types -> (access_key -> EConstr.constr option State.t) -> EConstr.constr option State.tCreate a new binder using a naming_scheme, for an optional body in the updated state.
val keep_binder_opt : binder -> naming_scheme -> Names.Name.t EConstr.binder_annot -> EConstr.types -> (access_key -> EConstr.constr option State.t) -> EConstr.constr option State.tKeep a former binder using a naming_scheme, for an optional body in the updated state.
val add_context : freshness -> naming_scheme -> EConstr.rel_context -> (access_key list -> 'a State.t) -> 'a State.tAdd a context to the state given its freshness and a naming_scheme, for a body defined in the updated state state * access_key list -> constr.
val closure_context : binder -> freshness -> naming_scheme -> EConstr.rel_context -> (access_key list -> EConstr.constr State.t) -> EConstr.constr State.tBind a context with binder or LetIn, given its freshness and a naming_scheme, for a body defined in the updated state.
val closure_context_opt : binder -> freshness -> naming_scheme -> EConstr.rel_context -> (access_key list -> EConstr.constr option State.t) -> EConstr.constr option State.tBind a context with binder or LetIn, given its freshness and a naming_scheme, for an optional body defined in the updated state.
val add_context_sep : freshness -> naming_scheme -> EConstr.rel_context -> ((access_key list * access_key list * access_key list) -> 'a State.t) -> 'a State.tAdd a context to the state given its freshness and a naming_scheme, for a body defined in the updated state, where the access_key are split between key_vars, key_letin, key_both.
val closure_context_sep : binder -> freshness -> naming_scheme -> EConstr.rel_context -> ((access_key list * access_key list * access_key list) -> EConstr.constr State.t) -> EConstr.constr State.tBind a context with binder or LetIn, given its freshness and a naming_scheme, for a body defined in the updated state, where the access_key are split between key_vars, key_letin, key_both.
val closure_context_sep_opt : binder -> freshness -> naming_scheme -> EConstr.rel_context -> ((access_key list * access_key list * access_key list) -> EConstr.constr option State.t) -> EConstr.constr option State.tBind a context with binder or LetIn, given its freshness and a naming_scheme, for an optional body defined in the updated state, where the access_key are split between key_vars, key_letin, key_both.
val read_by_decl : EConstr.rel_context -> (EConstr.rel_declaration -> (access_key -> EConstr.constr State.t) -> EConstr.constr State.t) -> (int -> access_key -> (access_key list -> EConstr.constr State.t) -> EConstr.constr State.t) -> (int -> access_key -> (access_key list -> EConstr.constr State.t) -> EConstr.constr State.t) -> (access_key list -> EConstr.constr State.t) -> EConstr.constr State.treads cxt binder cc_letin cc_var go through a context cxt, apply binder to each context declaration decl to it, then apply cc_letin if decl is a LetIn, and cc_var otherwise.
val iterate_ctors : Declarations.mutual_inductive_body -> Declarations.one_inductive_body -> Evd.einstance -> (int -> (EConstr.rel_context * EConstr.constr array) -> ('a -> 'b State.t) -> 'b State.t) -> ('a list -> 'b State.t) -> 'b State.tIterate a binding function to each constructor or an inductive type.
val make_ind : (Names.inductive * EConstr.EInstance.t) -> access_key list -> access_key list -> access_key list -> State.state -> EConstr.constrCreate a term refering to an inductive type given the access_key for uniform paramters, non-uniform parameters, and indices.
val make_cst : (Names.inductive * EConstr.EInstance.t) -> int -> access_key list -> access_key list -> EConstr.constr list -> State.state -> EConstr.constrCreate a term refering to the constructor of an inductive type given the access_key for uniform paramters, non-uniform parameters, and indices.
val make_fix : 'a list -> int -> (int -> 'a -> int) -> (int -> 'a -> Names.Name.t EConstr.binder_annot) -> (int -> 'a -> EConstr.types State.t) -> ((access_key list * int * 'a) -> EConstr.constr State.t) -> EConstr.constr State.tCreate a term refering to an inductive type given the access_key for uniform paramters, non-uniform parameters, and indices.
val get_indices : Declarations.one_inductive_body -> Evd.einstance -> EConstr.rel_context State.tRecover the indices of an inductive block, and weaken them in the current context.
val make_case_or_projections : naming_scheme -> Declarations.mutual_inductive_body -> Names.inductive -> Declarations.one_inductive_body -> Evd.einstance -> access_key list -> access_key list -> EConstr.constr array -> EConstr.constr list -> (access_key list -> access_key -> EConstr.types State.t) -> Evd.erelevance -> EConstr.constr -> ((access_key list * access_key list * access_key list * int) -> EConstr.constr State.t) -> EConstr.constr State.tCreate a new match given:
naming_scheme for the fresh indices, and argumentsmutual_inductive_body, inductive, one_inductive_body, instance on which the match is performedconstr array, and indices constr list of the term being matchedaccess_key list -> access_key -> constr trelevance of the matchconstr