module TypeCore: sig .. end
This module defines the syntax of types, as manipulated by the
type-checker.
This module defines the syntax of types, as manipulated by the
type-checker.
Various useful modules
module DataconMap: MzMap.S with type key = Module.name * Datacon.name
module Field: module type of Variable with type name = SurfaceSyntax.Field.name
The definition of types
Auxiliary definitions
type name =
| |
User of Module.name * Variable.name |
| |
Auto of Variable.name |
The type of user-generated or auto-generated names.
type location = Lexing.position * Lexing.position
Our locations are made up of ranges.
type type_binding = name * Kind.kind * location
A type binding defines a type variable bound in a type.
type flavor = SurfaceSyntax.binding_flavor =
| |
CanInstantiate |
| |
CannotInstantiate |
A type binding can be either user-provided, through a universal
quantification for instance, or auto-generated, by the desugaring pass for
instance.
type db_index = int
In the surface syntax, variables are named. Here, variables are
represented as de Bruijn indices. We keep a variable name at each
binding site as a pretty-printing hint.
type var
We adopt a locally nameless style; therefore, variables can be opened.
This is the type of open variales; it's abstract, because we provide a set
of wrappers and want to prevent mistakes in client code.
The type of types
type data_field_def =
| |
FieldValue of (Field.name * typ) |
| |
FieldPermission of typ |
A field in a data type
type typ =
The type of types.
type resolved_datacon = typ * Datacon.name
Since data constructors are now properly scoped, they are resolved, that is,
they are either attached to a point, or a De Bruijn index, which will later
resolve to a point when we open the corresponding type definition. That way,
we can easily jump from a data constructor to the corresponding type
definition.
type mode_constraint = Mode.mode * typ
Type definitions
type ('flavor, 'datacon) data_type_def_branch = {
|
branch_flavor :'flavor; |
|
branch_datacon :'datacon; |
|
branch_fields :data_field_def list; |
|
branch_adopts :typ; |
}
type resolved_branch = (unit, resolved_datacon) data_type_def_branch
type unresolved_branch = (DataTypeFlavor.flavor, Datacon.name) data_type_def_branch
type data_type_def = unresolved_branch list
type variance = SurfaceSyntax.variance =
| |
Invariant |
| |
Covariant |
| |
Contravariant |
| |
Bivariant |
Our data constructors have the standard variance.
type type_def = data_type_def option * variance list
type data_type_group = (Variable.name * location * type_def * Fact.fact *
Kind.kind)
list
Program-wide environment
type env
This is the environment that we use throughout Mezzo.
val empty_env : env
The empty environment.
val locate : env -> location -> env
Refresh the location of an environment.
val location : env -> location
Get the current location in the environment.
val module_name : env -> Module.name
Get the current module name.
val set_module_name : env -> Module.name -> env
Set the current module name.
val is_inconsistent : env -> bool
Is the current environment inconsistent?
val mark_inconsistent : env -> env
Mark the environment as being inconsistent.
Flexible variables
A client of this module, in order to properly deal with flexible variables,
must use the wrappers below.
val is_flexible : env -> var -> bool
Is this variable a flexible type variable or not?
val is_rigid : env -> var -> bool
val instantiate_flexible : env -> var -> typ -> env option
instantiate env var t tries to instantiate the flexible variable var
with t. However, because of various reasons (e.g. levels) this
instantiation may or may not be possible directly.
val modulo_flex_v : env -> var -> typ
Make sure we're dealing with the real representation of a variable. Any
function wishing to examine either a type or a variable should call these two
functions; then, whenever they encounter a TyOpen, they need not worry
about it having a structure (because it won't).
val modulo_flex : env -> typ -> typ
val import_flex_instanciations : env -> env -> env
import_flex_instanciations env sub_env brings into env all the flexible
variable instanciations that happened in sub_env without modifying the rest
of env.
Low-level operations
val same : env -> var -> var -> bool
Are these two variables the same? This is a low-level operation and you
probably want to use equal instead.
val merge_left : env -> var -> var -> env option
Merge two variables while keeping the information about the left one. You
must make sure that both variables have been run through
modulo_flex_v
first. This is a low-level operation and you probably want to use
Permissions.unify instead.
val get_floating_permissions : env -> typ list
Get the list of permissions that are floating in this environment.
val set_floating_permissions : env -> typ list -> env
Set the list of permissions that are floating in this environment.
Playing with variables
val get_names : env -> var -> name list
Get the names associated to a variable.
val get_name : env -> var -> name
val get_kind : env -> var -> Kind.kind
Get the kind of any given variable.
val get_fact : env -> var -> Fact.fact
Get a fact
val get_locations : env -> var -> location list
Get the locations
val get_definition : env -> var -> type_def option
Get the definition, if any.
Low-level variable manipulation functions.
val add_location : env -> var -> location -> env
Low-level permissions manipulation functions.
If you're considering playing with the list of permissions available for a
given variable, you should consider using Permissions.add and
Permissions.sub instead of these low-level, potentially dangerous
functions.
val get_permissions : env -> var -> typ list
Get the permissions of a term variable.
val set_permissions : env -> var -> typ list -> env
Set the permissions of a term variable.
val reset_permissions : env -> var -> env
Reset the permissions of a term variable.
Low-level setters
These functions should only be used during the very first few stages of
type-checking.
val set_fact : env -> var -> Fact.fact -> env
Set a fact
val update_definition : env ->
var -> (type_def -> type_def) -> env
Update a definition. This asserts that there used to be a definition before.
val set_definition : env -> var -> type_def -> env
Set a definition. This asserts that there was no definition before.
Fun with sub-environments
exception UnboundPoint
val clean : env -> env -> typ -> typ
clean env sub_env t tries to clean up t, found in sub_env, so that it
makes sense in env, and throws UnboundPoint otherwise
val equal : env -> typ -> typ -> bool
equal env t1 t2 tells whether t1 and t2 can be determined to be equal
in environment env; it raises UnboundPoint is any of these two types
doesn't make sense in env.
val resolved_datacons_equal : env ->
resolved_datacon -> resolved_datacon -> bool
Equality function on resolved data constructors.
Binding
val bind_rigid : env -> type_binding -> env * var
Bind a rigid type variable.
val bind_flexible : env -> type_binding -> env * var
Bind a flexible type variable.
Exports
val get_exports : env ->
Module.name -> (Variable.name * Kind.kind * var) list
get_exports env mname lists the names exported by module mname in env.
mname can be either the current module name, or some other module name.
val point_by_name : env -> ?mname:Module.name -> Variable.name -> var
point_by_name env ?mname x finds name x as exported by module mname
(default: module_name env) in env.
Iterating on the bindings
We provide a set of fold/map operations on variables defined in the
environment. Existential variables are not folded over, as they only serve as
placeholders; only rigid variables are consider when performing the various
fold operations.
Of course, we only fold over variables that have been opened in the current
environment.
val fold_definitions : env ->
('acc -> var -> type_def -> 'acc) -> 'acc -> 'acc
Fold over all opened types definitions.
val fold_terms : env ->
('acc -> var -> typ list -> 'acc) -> 'acc -> 'acc
Fold over all opened terms, providing the corresponding var and
permissions.
val fold : env -> ('acc -> var -> 'acc) -> 'acc -> 'acc
General fold operation.
val map : env -> (var -> 'a) -> 'a list
General map operation.
Marks
val is_marked : env -> var -> bool
val mark : env -> var -> env
val refresh_mark : env -> env
module VarMap: MzMap.S with type key = var
This module provides a clean way to map a variable to any given piece of
data.
module IVarMap: Fix.IMPERATIVE_MAPS with type key = var
This is an imperative version of VarMap, in the form expected by Fix.
Visitors for the internal syntax of types
A generic visitor.
class virtual [['env, 'result]] visitor : object .. end
A map specialization of the visitor.
class ['env] map : object .. end
An iter specialization of the visitor.
class ['env] iter : object .. end