123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354(******************************************************************************)(* *)(* Fix *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the GNU Library General Public License version 2, with a *)(* special exception on linking, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(**A type alone. *)moduletypeTYPE=sigtypetend(* -------------------------------------------------------------------------- *)(**An ordered type. A hashed type. These are standard notions. *)moduletypeOrderedType=Map.OrderedTypemoduletypeHashedType=Hashtbl.HashedType(* -------------------------------------------------------------------------- *)(**A type whose elements can be enumerated. *)moduletypeFINITE_TYPE=sigtypetvalforeach:(t->unit)->unitend(* -------------------------------------------------------------------------- *)(**Association maps. *)(**Following the convention of the ocaml standard library, [find] raises the
exception [Not_found] when the key is not in the domain of the map. In
contrast, [get] returns an option. *)(**Persistent maps. The empty map is a constant. Insertion creates a new map. *)(**This is a fragment of the standard signature [Map.S]. *)moduletypePERSISTENT_MAPS=sigtypekeytype'datatvalempty:'datatvaladd:key->'data->'datat->'datatvalfind:key->'datat->'datavaliter:(key->'data->unit)->'datat->unitend(**Imperative maps. A fresh empty map is produced by [create].
Insertion updates a map in place.
[clear] empties an existing map. *)(**The order of the arguments to [add] and [find] is consistent with the order
used in [PERSISTENT_MAPS] above. Thus, it departs from the convention used
in OCaml's [Hashtbl] module. *)moduletypeMINIMAL_IMPERATIVE_MAPS=sigtypekeytype'datatvalcreate:unit->'datatvaladd:key->'data->'datat->unitvalfind:key->'datat->'dataendmoduletypeIMPERATIVE_MAPS=sigincludeMINIMAL_IMPERATIVE_MAPSvalclear:'datat->unitvaliter:(key->'data->unit)->'datat->unitend(**An instance of the signature [ARRAY] represents one mutable map.
There is no type ['data t] and no [create] operation; there exists
just one map. Furthermore, the type [value], which corresponds to
['data] in the previous signatures, is fixed.
The domain of the map never changes:
- [set] does not extend the map,
- [get] cannot raise [Not_found]. *)moduletypeARRAY=sigtypekeytypevaluevalget:key->valuevalset:key->value->unitend(* -------------------------------------------------------------------------- *)(**The signature [PROPERTY] is used by [Fix.Make], the least fixed point
computation algorithm. *)(**The type [property] must form a partial order. It must be equipped with a
least element [bottom] and with an equality test [equal]. (In the function
call [equal p q], it is permitted to assume that [p <= q] holds.) We do not
require an ordering test [leq]. We do not require a join operation [lub].
We do require the ascending chain condition: every monotone sequence must
eventually stabilize. *)(**The function [is_maximal] determines whether a property [p] is maximal with
respect to the partial order. Only a conservative check is required: in any
event, it is permitted for [is_maximal p] to be [false]. If [is_maximal p]
is [true], then [p] must have no strict upper bound. In particular, in the
case where properties form a lattice, this means that [p] must be the top
element. *)moduletypePROPERTY=sigtypepropertyvalbottom:propertyvalequal:property->property->boolvalis_maximal:property->boolend(* -------------------------------------------------------------------------- *)(**The signature [SEMI_LATTICE] offers separate [leq] and [join] functions.
The functor [Glue.MinimalSemiLattice] can be used, if necessary, to convert
this signature to [MINIMAL_SEMI_LATTICE]. *)moduletypeSEMI_LATTICE=sigtypepropertyvalleq:property->property->boolvaljoin:property->property->propertyend(**The signature [MINIMAL_SEMI_LATTICE] is used by [Fix.DataFlow]. *)moduletypeMINIMAL_SEMI_LATTICE=sigtypeproperty(** [leq_join p q] must compute the join of [p] and [q]. If the result
is logically equal to [q], then [q] itself must be returned. Thus,
we have [leq_join p q == q] if and only if [leq p q] holds. *)valleq_join:property->property->propertyend(* -------------------------------------------------------------------------- *)(**The type of a fixed point combinator that constructs a value of
type ['a]. *)type'afix=('a->'a)->'a(* -------------------------------------------------------------------------- *)(**Memoizers -- higher-order functions that construct memoizing functions. *)moduletypeMEMOIZER=sig(**A type of keys. *)typekey(**A memoization combinator for this type. *)valmemoize:(key->'a)->(key->'a)(**A memoization combinator where the memoization table is exposed. *)type'atvalvisibly_memoize:(key->'a)->(key->'a)*'at(**A recursive memoization combinator. *)valfix:(key->'a)fix(**[defensive_fix] works like [fix], except it additionally detects circular
dependencies, which can arise if the second-order function supplied by
the user does not follow a well-founded recursion pattern. When the user
invokes [f x], where [f] is the function returned by [defensive_fix], if
a cyclic dependency is detected, then [Cycle (zs, z)] is raised, where
the list [zs] begins with [z] and continues with a series of intermediate
keys, leading back to [z]. Note that undetected divergence remains
possible; this corresponds to an infinite dependency chain, without a
cycle. *)exceptionCycleofkeylist*keyvaldefensive_fix:(key->'a)fix(**This combinator can be used to obtain a curried version of [fix] or
[defensive_fix] in a concrete instance where the type [key] is a
product type. *)valcurried:('a*'b->'c)fix->('a->'b->'c)fixend(* -------------------------------------------------------------------------- *)(**Tabulators: higher-order functions that construct tabulated functions. *)(**Like memoization, tabulation guarantees that, for every key [x], the image
[f x] is computed at most once. Unlike memoization, where this computation
takes place on demand, in the case of tabulation, the computation of every
[f x] takes place immediately, when [tabulate] is invoked. The graph of the
function [f], a table, is constructed and held in memory. *)moduletypeTABULATOR=sig(**A type of keys. *)typekey(**A tabulation combinator for this type. *)valtabulate:(key->'a)->(key->'a)end(* -------------------------------------------------------------------------- *)(**Solvers: higher-order functions that compute the least solution of a
monotone system of equations. *)moduletypeSOLVER=sigtypevariabletypeproperty(**A valuation is a mapping of variables to properties. *)typevaluation=variable->property(**A right-hand side, when supplied with a valuation that gives
meaning to its free variables, evaluates to a property. More
precisely, a right-hand side is a monotone function of
valuations to properties. *)typerhs=valuation->property(**A system of equations is a mapping of variables to right-hand
sides. *)typeequations=variable->rhs(**[lfp eqs] produces the least solution of the system of monotone
equations [eqs]. *)(**It is guaranteed that, for each variable [v], the application [eqs v] is
performed at most once (whereas the right-hand side produced by this
application is, in general, evaluated multiple times). This guarantee can
be used to perform costly pre-computation, or memory allocation, when [eqs]
is applied to its first argument. *)(**When [lfp] is applied to a system of equations [eqs], it performs no
actual computation. It produces a valuation, [get], which represents
the least solution of the system of equations. The actual fixed point
computation takes place, on demand, when [get] is applied. *)vallfp:equations->valuationend(* -------------------------------------------------------------------------- *)(**The signature [SOLUTION] is used to describe the result of
[Fix.DataFlow]. *)moduletypeSOLUTION=sigtypevariabletypepropertyvalsolution:variable->propertyend(* -------------------------------------------------------------------------- *)(**Directed, rooted graphs. *)moduletypeGRAPH=sigtypetvalforeach_root:(t->unit)->unitvalforeach_successor:t->(t->unit)->unitend(* -------------------------------------------------------------------------- *)(**The signature [DATA_FLOW_GRAPH] is used to describe a data flow analysis
problem. It is used to describe the input to [Fix.DataFlow]. *)(**The function [foreach_root] describes the root nodes of the data flow graph
as well as the properties associated with them. [foreach_call contribute]
is expected to call [contribute x p] to indicate that [x] is a root and
that [p] is a lower bound on the solution at [x]. It is permitted to call
[contribute x _] several times at a root [x]. *)(**The function [foreach_successor] describes the edges of the data flow graph
as well as the manner in which a property at the source of an edge is
transformed into a property at the target. The property at the target
must of course be a monotonic function of the property at the source. *)moduletypeDATA_FLOW_GRAPH=sigtypevariabletypepropertyvalforeach_root:(variable->property->unit)->unitvalforeach_successor:variable->property->(variable->property->unit)->unitend(* -------------------------------------------------------------------------- *)(**Numberings. *)(**An ongoing numbering of (a subset of) a type [t] offers a function [encode]
which maps a value of type [t] to a unique integer code. If applied twice
to the same value, [encode] returns the same code; if applied to a value
that has never been encountered, it returns a fresh code. The function
[current] returns the next available code, which is also the number of
values that have been encoded so far. The function [has_been_encoded] tests
whether a value has been encoded already. *)moduletypeONGOING_NUMBERING=sigtypetvalencode:t->intvalcurrent:unit->intvalhas_been_encoded:t->boolend(**A numbering of (a subset of) a type [t] is a triple of an integer [n] and
two functions [encode] and [decode] which represent an isomorphism between
this subset of [t] and the interval [\[0..n)]. *)moduletypeNUMBERING=sigtypetvaln:intvalencode:t->intvaldecode:int->tend(**A combination of the above two signatures. According to this signature, a
numbering process is organized in two phases. During the first phase, the
numbering is ongoing; one can encode keys, but not decode. Applying the
functor [Done()] ends the first phase. A fixed numbering then becomes
available, which gives access to the total number [n] of encoded keys and
to both [encode] and [decode] functions. *)moduletypeTWO_PHASE_NUMBERING=sigincludeONGOING_NUMBERINGmoduleDone():NUMBERINGwithtypet=tend(* -------------------------------------------------------------------------- *)(**Injections. *)(**An injection of [t] into [u] is an injective function of type [t -> u].
Because [encode] is injective, [encode x] can be thought of as the identity
of the object [x]. *)moduletypeINJECTION=sigtypettypeuvalencode:t->uend