|
|
|
@ -73,6 +73,24 @@ let base_rank =
|
|
|
|
|
|
|
|
|
|
type status = Rigid | Flexible | Generic
|
|
|
|
|
|
|
|
|
|
type rigidity = Rigid_ | Flexible_
|
|
|
|
|
|
|
|
|
|
let rigidity_of_status status =
|
|
|
|
|
match status with
|
|
|
|
|
| Generic ->
|
|
|
|
|
assert false
|
|
|
|
|
| Flexible ->
|
|
|
|
|
Flexible_
|
|
|
|
|
| Rigid ->
|
|
|
|
|
Rigid_
|
|
|
|
|
|
|
|
|
|
let status_of_rigidity rigidity =
|
|
|
|
|
match rigidity with
|
|
|
|
|
| Flexible_ ->
|
|
|
|
|
Flexible
|
|
|
|
|
| Rigid_ ->
|
|
|
|
|
Rigid
|
|
|
|
|
|
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
|
|
|
|
|
|
(* We let each equivalence class carry a mutable integer mark. This [mark]
|
|
|
|
@ -180,22 +198,21 @@ module Data = struct
|
|
|
|
|
let rank = min data1.rank data2.rank in
|
|
|
|
|
let fail () = raise InconsistentConjunction in
|
|
|
|
|
(* If either variables is rigid, the conjunction is also rigid. *)
|
|
|
|
|
let status = match data1.status, data2.status with
|
|
|
|
|
| Generic, _ | _, Generic ->
|
|
|
|
|
(* The unifier never acts on generic variables. *)
|
|
|
|
|
assert false
|
|
|
|
|
| Flexible, Flexible ->
|
|
|
|
|
let status =
|
|
|
|
|
match rigidity_of_status data1.status,
|
|
|
|
|
rigidity_of_status data2.status with
|
|
|
|
|
| Flexible_, Flexible_ ->
|
|
|
|
|
Flexible
|
|
|
|
|
(* One cannot unify two rigid variables, *)
|
|
|
|
|
| Rigid, Rigid ->
|
|
|
|
|
| Rigid_, Rigid_ ->
|
|
|
|
|
fail ()
|
|
|
|
|
(* ... or lower the rank of a rigid variable, *)
|
|
|
|
|
| Rigid, Flexible ->
|
|
|
|
|
| Rigid_, Flexible_ ->
|
|
|
|
|
if (rank < data1.rank) then fail ();
|
|
|
|
|
(* ... or give it a non-leaf structure. *)
|
|
|
|
|
if not (S.is_leaf structure) then fail ();
|
|
|
|
|
Rigid
|
|
|
|
|
| Flexible, Rigid ->
|
|
|
|
|
| Flexible_, Rigid_ ->
|
|
|
|
|
if (rank < data2.rank) then fail ();
|
|
|
|
|
(* ... or give it a non-leaf structure. *)
|
|
|
|
|
if not (S.is_leaf structure) then fail ();
|
|
|
|
@ -304,11 +321,11 @@ let register v r =
|
|
|
|
|
(* When a fresh unification variable is created, it receives the current rank,
|
|
|
|
|
and it is immediately registered at this rank. *)
|
|
|
|
|
|
|
|
|
|
let fresh status structure =
|
|
|
|
|
let fresh rigidity structure =
|
|
|
|
|
let r = state.young in
|
|
|
|
|
if status = Rigid then
|
|
|
|
|
if rigidity = Rigid_ then
|
|
|
|
|
assert (S.is_leaf structure);
|
|
|
|
|
let v = U.fresh (Data.make structure r status) in
|
|
|
|
|
let v = U.fresh (Data.make structure r (status_of_rigidity rigidity)) in
|
|
|
|
|
register v r;
|
|
|
|
|
v
|
|
|
|
|
|
|
|
|
@ -718,7 +735,7 @@ let instantiate { generics; quantifiers; root } =
|
|
|
|
|
let data = get v in
|
|
|
|
|
assert (data.status = Generic);
|
|
|
|
|
data.mark <- i;
|
|
|
|
|
fresh Flexible S.leaf
|
|
|
|
|
fresh Flexible_ S.leaf
|
|
|
|
|
)
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|