open EcIdent
open EcSymbols
open EcUtils
open EcMaps
module rec PATH :
sig
type path = private {
p_node : path_node;
p_tag : int
}
and path_node =
| Psymbol of symbol
| Pqname of path * symbol
val p_equal : path -> path -> bool
val p_hash : path -> int
val p_compare : path -> path -> int
val p_ntr_compare : path -> path -> int
val mk_path : path_node -> path
module Mp : Map.S with type key = path
module Hp : EcMaps.EHashtbl.S with type key = path
module Sp : sig
include Set.S with module M = Map.MakeBase(Mp)
val ntr_elements : t -> elt list
end
type mpath = {
m_top : mpath_top;
(* m_targs : TYPES.ty list; *)
m_args : mpath list;
m_tag : int;
}
and mpath_top =
[ | `Local of ident
| `Concrete of path * path option ]
val m_equal : mpath -> mpath -> bool
val mt_equal : mpath_top -> mpath_top -> bool
val m_hash : mpath -> int
val m_compare : mpath -> mpath -> int
val m_ntr_compare : mpath -> mpath -> int
val mpath : mpath_top -> mpath list -> mpath
module Mm : Map.S with type key = mpath
module Hm : EcMaps.EHashtbl.S with type key = mpath
module Sm : sig
include Set.S with module M = Map.MakeBase(Mm)
val ntr_elements : t -> elt list
end
val m_fv : int EcIdent.Mid.t -> mpath -> int EcIdent.Mid.t
end
=
struct
(* ------------------------------------------------------------------------- *)
(* path *)
type path = {
p_node : path_node;
p_tag : int
}
and path_node =
| Psymbol of symbol
| Pqname of path * symbol
let p_equal = ((==) : path -> path -> bool)
let p_hash = fun p -> p.p_tag
let p_compare = fun p1 p2 -> p_hash p1 - p_hash p2
module Hspath = Why3.Hashcons.Make(
struct
type t = path
let equal_node p1 p2 =
match p1, p2 with
| Psymbol id1, Psymbol id2 ->
sym_equal id1 id2
| Pqname (p1, id1), Pqname(p2, id2) ->
sym_equal id1 id2 && p_equal p1 p2
| _ -> false
let equal p1 p2 = equal_node p1.p_node p2.p_node
let hash p =
match p.p_node with
| Psymbol id -> Hashtbl.hash id
| Pqname (p,id) -> Why3.Hashcons.combine p.p_tag (Hashtbl.hash id)
let tag n p = { p with p_tag = n }
end)
let mk_path node =
Hspath.hashcons { p_node = node; p_tag = -1; }
(* -------------------------------------------------------------------- *)
module Path = MakeMSH (
struct
type t = path
let tag = p_hash
end)
let rec p_ntr_compare (p1 : path) (p2 : path) =
match p1.p_node, p2.p_node with
| Psymbol _, Pqname _ -> -1
| Pqname _, Psymbol _ -> +1
| Psymbol x1, Psymbol x2 ->
String.compare x1 x2
| Pqname (p1, x1), Pqname (p2, x2) -> begin
match p_ntr_compare p1 p2 with
| 0 -> String.compare x1 x2
| n -> n
end
module Mp = Path.M
module Hp = Path.H
module Sp = struct
include Path.S
let ntr_elements s =
List.ksort ~key:identity ~cmp:p_ntr_compare (elements s)
end
(* ------------------------------------------------------------------------- *)
(* mpath *)
type mpath = {
m_top : mpath_top;
m_args : mpath list;
m_tag : int;
}
and mpath_top =
[ | `Local of ident
| `Concrete of path * path option ]
let m_equal = ((==) : mpath -> mpath -> bool)
let m_hash = fun p -> p.m_tag
let m_compare = fun p1 p2 -> m_hash p1 - m_hash p2
let rec m_fv fv mp =
let fv =
match mp.m_top with
| `Local id -> EcIdent.fv_add id fv
| `Concrete _ -> fv in
List.fold_left m_fv fv mp.m_args
let mt_equal mt1 mt2 =
match mt1, mt2 with
| `Local id1, `Local id2 -> EcIdent.id_equal id1 id2
| `Concrete(p1, o1), `Concrete(p2, o2) ->
p_equal p1 p2 && oall2 p_equal o1 o2
| _, _ -> false
module Hsmpath = Why3.Hashcons.Make (struct
type t = mpath
let equal m1 m2 =
mt_equal m1.m_top m2.m_top && List.all2 m_equal m1.m_args m2.m_args
let hash m =
let hash =
match m.m_top with
| `Local id -> EcIdent.id_hash id
| `Concrete(p, o) ->
o |> ofold
(fun s h -> Why3.Hashcons.combine h (p_hash s))
(p_hash p)
in
Why3.Hashcons.combine_list m_hash hash m.m_args
let tag n p = { p with m_tag = n }
end)
let mpath p args =
Hsmpath.hashcons { m_top = p; m_args = args; m_tag = -1; }
(* -------------------------------------------------------------------- *)
module MPath = MakeMSH (struct
type t = mpath
let tag = m_hash
end)
let m_top_ntr_compare (mt1 : mpath_top) (mt2 : mpath_top) =
match mt1, mt2 with
| `Local _, `Concrete _ -> -1
| `Concrete _, `Local _ -> +1
| `Local id1, `Local id2 ->
id_ntr_compare id1 id2
| `Concrete (p1, op1), `Concrete (p2, op2) -> begin
match p_ntr_compare p1 p2 with
| 0 -> ocompare p_ntr_compare op1 op2
| n -> n
end
let rec m_ntr_compare (m1 : mpath) (m2 : mpath) =
match m_top_ntr_compare m1.m_top m2.m_top with
| 0 -> List.compare m_ntr_compare m1.m_args m2.m_args
| n -> n
module Mm = MPath.M
module Hm = MPath.H
module Sm = struct
include MPath.S
let ntr_elements s =
List.ksort ~key:identity ~cmp:m_ntr_compare (elements s)
end
end
and TYPES : sig
type ty = {
ty_node : ty_node;
ty_fv : int Mid.t;
ty_tag : int;
}
and ty_node =
| Tglob of PATH.mpath (* The tuple of global variable of the module *)
| Tunivar of EcUid.uid
| Tvar of EcIdent.t
| Ttuple of ty list
| Tconstr of PATH.path * ty list
| Tfun of ty * ty
val ty_equal : ty -> ty -> bool
val ty_hash : ty -> int
val mk_ty : ty_node -> ty
module Mty : Map.S with type key = ty
module Sty : Set.S with module M = Map.MakeBase(Mty)
module Hty : EcMaps.EHashtbl.S with type key = ty
end
=
struct
type ty = {
ty_node : ty_node;
ty_fv : int Mid.t;
ty_tag : int;
}
and ty_node =
| Tglob of PATH.mpath (* The tuple of global variable of the module *)
| Tunivar of EcUid.uid
| Tvar of EcIdent.t
| Ttuple of ty list
| Tconstr of PATH.path * ty list
| Tfun of ty * ty
let ty_equal : ty -> ty -> bool = (==)
let ty_hash ty = ty.ty_tag
module Hsty = Why3.Hashcons.Make (struct
type t = ty
let equal ty1 ty2 =
match ty1.ty_node, ty2.ty_node with
| Tglob m1, Tglob m2 ->
PATH.m_equal m1 m2
| Tunivar u1, Tunivar u2 ->
EcUid.uid_equal u1 u2
| Tvar v1, Tvar v2 ->
id_equal v1 v2
| Ttuple lt1, Ttuple lt2 ->
List.all2 ty_equal lt1 lt2
| Tconstr (p1, lt1), Tconstr (p2, lt2) ->
PATH.p_equal p1 p2 && List.all2 ty_equal lt1 lt2
| Tfun (d1, c1), Tfun (d2, c2)->
ty_equal d1 d2 && ty_equal c1 c2
| _, _ -> false
let hash ty =
match ty.ty_node with
| Tglob m -> PATH.m_hash m
| Tunivar u -> u
| Tvar id -> EcIdent.tag id
| Ttuple tl -> Why3.Hashcons.combine_list ty_hash 0 tl
| Tconstr (p, tl) -> Why3.Hashcons.combine_list ty_hash p.p_tag tl
| Tfun (t1, t2) -> Why3.Hashcons.combine (ty_hash t1) (ty_hash t2)
let fv ty =
let union ex =
List.fold_left (fun s a -> fv_union s (ex a)) Mid.empty in
match ty with
| Tglob m -> PATH.m_fv Mid.empty m
| Tunivar _ -> Mid.empty
| Tvar _ -> Mid.empty
| Ttuple tys -> union (fun a -> a.ty_fv) tys
| Tconstr (_, tys) -> union (fun a -> a.ty_fv) tys
| Tfun (t1, t2) -> union (fun a -> a.ty_fv) [t1; t2]
let tag n ty = { ty with ty_tag = n; ty_fv = fv ty.ty_node; }
end)
let mk_ty node =
Hsty.hashcons { ty_node = node; ty_tag = -1; ty_fv = Mid.empty }
module MSHty = EcMaps.MakeMSH(struct
type t = ty
let tag t = t.ty_tag
end)
module Mty = MSHty.M
module Sty = MSHty.S
module Hty = MSHty.H
end