123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382(******************************************************************************)(* *)(* Inferno *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the MIT License, as described in the file LICENSE. *)(* *)(******************************************************************************)(* This file defines the input and output signatures of several functors. *)(* We use [include] directives to avoid redundancy, but annotate them with
@inline so as to hide them in the generated documentation. This also
allows us to hide the names of these signatures, which are difficult
to remember, due to the many variants that are needed. *)(* -------------------------------------------------------------------------- *)(**Every equivalence class (of unification variables) carries a unique
identifier. This is used for several purposes, including constructing
dictionaries (hash tables) whose keys are equivalence classes and mapping
equivalence classes to decoded type variables. One must be aware that these
identifiers are stable only while the unifier is inactive. So, a hash table
whose keys are equivalence should not persist across a call to [unify]. *)typeid=int(* -------------------------------------------------------------------------- *)(* [SSTRUCTURE] describes just the type ['a structure]. *)moduletypeSSTRUCTURE=sig(**A structure is a piece of information that the unifier attaches to a
variable (or, more accurately, to an equivalence class of variables).
In some contexts, a structure represents a logical constraint that bears
on a variable. A structure of type ['a structure] may itself contain
variables, which are represented as values of type ['a]. We refer to
these values as the children of this structure.
In some contexts, a structure may record not only a logical constraint,
but also other kinds of meta-information, such as the unique identifier
of this equivalence class, where and how it is bound (its rank; whether
it is rigid or flexible; etc.).
For example, in the case of first-order unification, a structure might
be an optional shallow term: that is,
- either [None], which indicates the absence of a constraint;
- or [Some term], where [term] is a shallow term
(a term of depth 1 whose leaves are variables of type ['a]),
which indicates the presence of an equality constraint. *)type'astructureend(* [USTRUCTURE] describes an input of [Unifier.Make]. *)moduletypeUSTRUCTURE=sig(** @inline *)includeSSTRUCTURE(**[InconsistentConjunction] is raised by {!conjunction}. *)exceptionInconsistentConjunction(**[conjunction equate s1 s2] computes the logical conjunction [s] of the
structures [s1] and [s2]. If these structures are logically inconsistent
with one another (that is, if their conjunction implies a logical
contradiction), then the exception {!InconsistentConjunction} is raised.
[conjunction] invokes [equate] to emit auxiliary equality constraints
that are necessary and sufficient for [s] to actually represent the
conjunction of [s1] and [s2].
For example, in the case of first-order unification, assuming that a
structure is an optional shallow term:
- the conjunction of [None] and [s] would be [s];
- the conjunction of [s] and [None] would be [s];
- the conjunction of [Some term1] and [Some term2], where the shallow
terms [term1] and [term2] have the same head constructor,
would be [Some term1] or [Some term2] (it does not matter which!),
and [equate] would be invoked to equate the leaves of [term1] and
[term2];
- the conjunction of [Some term1] and [Some term2], where the shallow
terms [term1] and [term2] have distinct head constructors,
would raise {!InconsistentConjunction}. *)valconjunction:('a->'a->unit)->'astructure->'astructure->'astructureend(* [OCSTRUCTURE] describes an input of [OccursCheck.Make]. *)moduletypeOCSTRUCTURE=sig(** @inline *)includeSSTRUCTURE(**[iter] applies an action to every child of a structure. *)valiter:('a->unit)->'astructure->unit(**[id] extracts the unique identifier of a structure. *)valid:'astructure->idend(* [OSTRUCTURE] describes an input of [Decoder.Make]. *)moduletypeOSTRUCTURE=sig(** @inline *)includeOCSTRUCTURE(**[map] applies a transformation to the children of a structure,
while preserving the shape of the structure. *)valmap:('a->'b)->'astructure->'bstructure(**[is_leaf s] determines whether the structure [s] is a leaf, that is,
whether it represents the absence of a logical constraint. This function
is typically used by a decoder to determine which equivalence classes
should be translated to "type variables" in a decoded type. *)valis_leaf:'astructure->boolend(* [GSTRUCTURE] describes an input of [Structure.Option],
and also describes part of its output. *)moduletypeGSTRUCTURE=sig(** @inline *)includeUSTRUCTURE(**[iter] applies an action to every child of a structure. *)valiter:('a->unit)->'astructure->unit(**[fold] applies an action to every child of a structure,
and carries an accumulator. *)valfold:('a->'b->'b)->'astructure->'b->'b(**[map] applies a transformation to the children of a structure,
while preserving the shape of the structure. *)valmap:('a->'b)->'astructure->'bstructureend(* [STRUCTURE_LEAF] describes the output of [Structure.Option] and
an input of [Generalization.Make]. *)moduletypeSTRUCTURE_LEAF=sig(** @inline *)includeGSTRUCTURE(**The constant [leaf] is a structure that represents the absence of a
logical constraint. It is typically used when a variable is created
fresh. *)valleaf:'astructure(**[is_leaf s] determines whether the structure [s] is a leaf, that is,
whether it represents the absence of a logical constraint. This function
is typically used by a decoder to determine which equivalence classes
should be translated to "type variables" in a decoded type. *)valis_leaf:'astructure->boolend(* [HSTRUCTURE] describes an input of [Solver.Make]. *)moduletypeHSTRUCTURE=sig(** @inline *)includeGSTRUCTURE(**[pprint] is a structure printer, parameterized over a child printer.
It is used for debugging purposes only. *)valpprint:('a->PPrint.document)->'astructure->PPrint.documentend(* -------------------------------------------------------------------------- *)(* [MUNIFIER] describes a fragment of the functionality offered by the
unifier. This fragment provides read access to the unifier's data
structures. This signature serves as an input of [OccursCheck.Make] and
[Decoder.Make]. *)moduletypeMUNIFIER=sig(**A unifier maintains a graph whose vertices are equivalence classes of
variables. With each equivalence class, a piece of information of type
{!data} is attached. *)typevariable(**The type ['a structure] describes the information that is attached with
each class. It is parameterized over a type ['a] of children. In the
definition of the type {!data}, ['a] is instantiated with [variable]. *)type'astructure(**By definition, [data] is a synonym for [variable structure]. So, the data
attached with an equivalence class of variables is a structure whose
children are variables. *)typedata=variablestructure(**[get v] is the structure currently attached with the (equivalence class
of the) variable [v]. The structure that is attached with a class can
change when the unifier is invoked. *)valget:variable->dataend(* [GUNIFIER] describes the unifier that is embedded in the output of
[Generalization.Make]. Some functions, especially [fresh], are removed.
Exposing [fresh] would be undesirable: we want to hide the unifier's
[fresh] function, because [Generalization.Make] overrides it with its own
[fresh] function. *)moduletypeGUNIFIER=sig(** @inline *)includeMUNIFIER(**This exception is raised by {!unify}. *)exceptionUnifyofvariable*variable(**[unify v1 v2] equates the two variables [v1] and [v2]. These variables
become part of the same equivalence class. The structures carried by [v1]
and [v2] are combined by invoking the [conjunction] function supplied by
the user as an argument to [Unifier.Make]. [conjunction] itself is given
access to an [equate] function which submits an equality constraint to
the unifier.
If a logical inconsistency is detected, [Unify (v1, v2)] is raised, and
the state of the unifier is unaffected. (The unifier undoes any updates
that it may have performed.) For this undo machinery to work correctly,
the [conjunction] function provided by the user {i must not perform any
side effect}.
Unification can create cycles in the graph maintained by the unifier. By
default, the unifier tolerates these cycles. An occurs check, which
detects these cycles, is provided separately: see {!OccursCheck.Make}.
Because cycles are permitted, the variables [v1] and [v2] carried by the
exception {!Unify} can participate in cycles. When reporting a unification
error, a cyclic decoder should be used: see {!Decoder.Make}. *)valunify:variable->variable->unitend(* [UNIFIER] describes the output of [Unifier.Make]. *)moduletypeUNIFIER=sig(** @inline *)includeGUNIFIER(**[is_representative v] determines whether the variable [v] is currently
the representative element of its equivalence class. *)valis_representative:variable->bool(**[fresh s] creates a new variable whose structure is [s]. This variable
forms an equivalence class of its own. *)valfresh:data->variableend(* -------------------------------------------------------------------------- *)(* [OCCURS_CHECK] describes the output of [OccursCheck.Make]. *)moduletypeOCCURS_CHECK=sigtypevariabletypedata(**[Cycle v] is raised by the occurs check. *)exceptionCycleofvariable(**[new_occurs_check is_young] initiates a cycle detection phase. It
produces a function [check] that can be applied to a number of
roots. The function [check] visits the vertices that are reachable from
some root and that satisfy the user-supplied predicate [is_young]. If a
cycle is detected, then [Cycle v] is raised, where [v] is a vertex that
participates in the cycle.
The function [check] has internal state and records the vertices that it
has visited, so no vertex is visited twice: the complexity of the occurs
check is linear in the size of the graph fragment that is visited. *)valnew_occurs_check:(data->bool)->(variable->unit)end(* -------------------------------------------------------------------------- *)(* [OUTPUT] describes an input of [Decoder.Make] and [Solver.Make]. *)moduletypeOUTPUT=sig(** @inline *)includeSSTRUCTURE(**A representation of decoded type variables. *)typetyvar(**A representation of decoded types. *)typety(**[inject] provides an injection of unique integer identifiers into
decoded type variables. *)valinject:id->tyvar(**[variable v] is a representation of the type variable [v] as a decoded
type. *)valvariable:tyvar->ty(**[structure s] turns [s], a structure whose children are decoded types,
into a decoded type. *)valstructure:tystructure->ty(**If [v] is a type variable and [t] is a decoded type, then [mu v t] is a
representation of the recursive type [mu v.t]. The function [mu] is used
only by the cyclic decoder. *)valmu:tyvar->ty->tyend(* -------------------------------------------------------------------------- *)(* [DECODER] describes the output of [Decoder.Make]. *)moduletypeDECODER=sigtypevariabletypetyvartypety(**[decode_variable v] decodes the variable [v]. *)valdecode_variable:variable->tyvar(**[new_acyclic_decoder()] initiates a new decoding phase. It returns a
decoding function [decode], which can be used as many as times as one
wishes. Decoding requires the graph to be acyclic: it is a bottom-up
computation. [decode] internally performs memoization, so even if the
decoder is called many times, the total cost of decoding is linear in the
size of the graph fragment that is decoded.
As a caveat that one must bear in mind, when the type [ty] of decoded
types is a type of abstract syntax {i trees}, then the decoder actually
produces a {i DAG} of type [ty]. Traversing this DAG in a naive way,
without paying attention to the fact that some subtrees may be shared,
can result in a traversal whose complexity is exponential. *)valnew_acyclic_decoder:unit->(variable->ty)(**[new_cyclic_decoder] is analogous to {!new_acyclic_decoder}, but
tolerates cyclic graphs. The decoder detects cycles and uses the function
[mu] to decode them into equirecursive types. The decoder performs
memoization only at the vertices that do {i not} participate in a cycle.
This makes the complexity of decoding higher than the acyclic case, but
we expect it to remain linear in practice. *)valnew_cyclic_decoder:unit->(variable->ty)end(* -------------------------------------------------------------------------- *)(* [TEVAR] describes an input of [Solver.Make]. *)moduletypeTEVAR=sig(**A type of variables. *)typet(** @inline *)includeHashtbl.HashedTypewithtypet:=t(**A conversion of variables to strings. This function is used for
debugging purposes only. *)valto_string:t->stringend