This module defines the internal representation of global declarations. This includes global constants/axioms, mutual inductive definitions, modules and module types
Representation of constants (Definition/Axiom)
Non-universe polymorphic mode polymorphism (Coq 8.2+): inductives and constants hiding inductives are implicitly polymorphic when applied to parameters, on the universes appearing in the whnf of their parameters and their conclusion, in a template style.
In truly universe polymorphic mode, we always use RegularArity.
type template_arity = {
template_level : Sorts.t;
}
type ('a, 'b) declaration_arity =
| RegularArity of 'a
| TemplateArity of 'b
Inlining level of parameters at functor applications. None means no inlining
A constant can have no body (axiom/parameter), or a transparent body, or an opaque one
type ('a, 'opaque) constant_def =
| Undef of inline
| Def of 'a
or a transparent global definition
| OpaqueDef of 'opaque
or an opaque global definition
| Primitive of CPrimitives.t
type typing_flags = {
check_guarded : bool;
If false
then fixed points and co-fixed points are assumed to be total.
check_positive : bool;
If false
then inductive types are assumed positive and co-inductive types are assumed productive.
check_universes : bool;
If false
universe constraints are not checked
conv_oracle : Conv_oracle.oracle;
Unfolding strategies for conversion
share_reduction : bool;
Use by-need reduction algorithm
enable_VM : bool;
If false
, all VM conversions fall back to interpreted ones
enable_native_compiler : bool;
If false
, all native conversions fall back to VM ones
indices_matter : bool;
The universe of an inductive type must be above that of its indices.
impredicative_set : bool;
Predicativity of the Set
universe.
sprop_allowed : bool;
If false
, error when encountering SProp
.
cumulative_sprop : bool;
allow_uip : bool;
Allow definitional UIP (breaks termination)
}
The typing_flags
are instructions to the type-checker which modify its behaviour. The typing flags used in the type-checking of a constant are tracked in their constant_body
so that they can be displayed to the user.
Representation of definitions/assumptions in the kernel
Representation of mutual inductive types in the kernel
Inductive I1 (params) : U1 := c11 : T11 | ... | c1p1 : T1p1
...
with In (params) : Un := cn1 : Tn1 | ... | cnpn : Tnpn
Record information: If the type is not a record, then NotRecord If the type is a non-primitive record, then FakeRecord If it is a primitive record, for every type in the block, we get:
- The identifier for the binder name of the record in primitive projections.
- The constants associated to each projection.
- The projection types (under parameters).
The kernel does not exploit the difference between NotRecord
and FakeRecord
. It is mostly used by extraction, and should be extruded from the kernel at some point.
type one_inductive_body = {
mind_typename : Names.Id.t;
mind_arity_ctxt : Constr.rel_context;
Arity context of Ii
. It includes the context of parameters, that is, it has the form paramdecls, realdecls_i
such that Ui
(see above) is forall realdecls_i, si
for some sort si
and such that Ii
has thus type forall paramdecls, forall
realdecls_i, si
. The context itself is represented internally as a list in reverse order [realdecl_i{r_i};...;realdecl_i1;paramdecl_m;...;paramdecl_1]
.
mind_arity : inductive_arity;
Arity sort and original user arity
mind_consnames : Names.Id.t array;
Names of the constructors: cij
mind_user_lc : Constr.types array;
Types of the constructors with parameters: forall params, Tij
, where the recursive occurrences of the inductive types in Tij
(i.e. in the type of the j-th constructor of the i-th types of the block a shown above) have the form Ind ((mind,0),u)
, ..., Ind ((mind,n-1),u)
for u
the canonical abstract instance associated to mind_universes
and mind
the name to which the inductive block is bound in the environment.
mind_nrealargs : int;
Number of expected real arguments of the type (no let, no params)
mind_nrealdecls : int;
Length of realargs context (with let, no params)
mind_kelim : Sorts.family;
Highest allowed elimination sort
mind_nf_lc : (Constr.rel_context * Constr.types) array;
Head normalized constructor types so that their conclusion exposes the inductive type. It includes the parameters, i.e. each component of the array has the form (decls_ij, Ii params realargs_ij)
where decls_ij
is the concatenation of the context of parameters (possibly with let-ins) and of the arguments of the constructor (possibly with let-ins). This context is internally represented as a list [cstrdecl_ij{q_ij};...;cstrdecl_ij1;paramdecl_m;...;paramdecl_1]
such that the constructor in fine has type forall paramdecls,
forall cstrdecls_ij, Ii params realargs_ij
] with params
referring to the assumptions of paramdecls
and realargs_ij
being the "indices" specific to the constructor.
mind_consnrealargs : int array;
Number of expected proper arguments of the constructors (w/o params)
mind_consnrealdecls : int array;
Length of the signature of the constructors (with let, w/o params)
mind_recargs : wf_paths;
Signature of recursive arguments in the constructors
mind_relevance : Sorts.relevance;
mind_nb_constant : int;
number of constant constructor
mind_nb_args : int;
number of no constant constructor
mind_reloc_tbl : Vmvalues.reloc_table;
}
Datas specific to a single type of a block of mutually inductive type
type recursivity_kind =
| Finite
| CoFinite
| BiFinite
= non-recursive, like in "Record" definitions
Datas associated to a full block of mutually inductive types
type mutual_inductive_body = {
mind_packets : one_inductive_body array;
The component of the mutual inductive block
mind_record : record_info;
mind_finite : recursivity_kind;
Whether the type is inductive or coinductive
mind_ntypes : int;
Number of types in the block
mind_hyps : Constr.named_context;
Section hypotheses on which the block depends
mind_univ_hyps : Univ.Instance.t;
Section polymorphic universes.
mind_nparams : int;
Number of expected parameters including non-uniform ones (i.e. length of mind_params_ctxt w/o let-in)
mind_nparams_rec : int;
Number of recursively uniform (i.e. ordinary) parameters
mind_params_ctxt : Constr.rel_context;
The context of parameters (includes let-in declaration)
mind_universes : universes;
Information about monomorphic/polymorphic/cumulative inductives and their universes
mind_template : template_universes option;
mind_variance : Univ.Variance.t array option;
Variance info, None
when non-cumulative.
mind_sec_variance : Univ.Variance.t array option;
Variance info for section polymorphic universes. None
outside sections. The final variance once all sections are discharged is mind_sec_variance ++ mind_variance
.
mind_private : bool option;
allow pattern-matching: Some true ok, Some false blocked
mind_typing_flags : typing_flags;
typing flags at the time of the inductive creation
}
Module declarations
Functor expressions are forced to be on top of other expressions
The fully-algebraic module expressions : names, applications, 'with ...'. They correspond to the user entries of non-interactive modules. They will be later expanded into module structures in Mod_typing
, and won't play any role into the kernel after that : they are kept only for short module printing and for extraction.
A component of a module structure
A module structure is a list of labeled components.
Note : we may encounter now (at most) twice the same label in a structure_body
, once for a module (SFBmodule
or SFBmodtype
) and once for an object (SFBconst
or SFBmind
)
A module signature is a structure, with possibly functors on top of it
A module expression is an algebraic expression, possibly functorized.
and module_implementation =
| Abstract
no accessible implementation
| Algebraic of module_expression
non-interactive algebraic expression
| Struct of module_signature
| FullStruct
special case of Struct
: the body is exactly mod_type
For a module, there are five possible situations:
Declare Module M : T
then mod_expr = Abstract; mod_type_alg = Some T
Module M := E
then mod_expr = Algebraic E; mod_type_alg = None
Module M : T := E
then mod_expr = Algebraic E; mod_type_alg = Some T
Module M. ... End M
then mod_expr = FullStruct; mod_type_alg = None
Module M : T. ... End M
then mod_expr = Struct; mod_type_alg = Some T
And of course, all these situations may be functors or not.
A module_type_body
is just a module_body
with no implementation and also an empty mod_retroknowledge
. Its mod_type_alg
contains the algebraic definition of this module type, or None
if it has been built interactively.
Extra invariants :
- No
MEwith
inside a mod_expr
implementation : the 'with' syntax is only supported for module types
- A module application is atomic, for instance ((M N) P) : * the head of
MEapply
can only be another MEapply
or a MEident
* the argument of MEapply
is now directly forced to be a ModPath.t
.