3 (* Copyright Jeremy Yallop 2007.
4 This file is free software, distributed under the MIT license.
5 See the file COPYING for details.
8 (** A type is viewed as the application of type constructors to zero
9 or more type arguments. We provide equality and ordering
10 operations on types. The ordering is unspecified, but consistent
11 within a process, i.e. sufficient for use in Map etc.
13 This might be considered to break abstraction, since it exposes
14 the fact that two types are the same, even if that fact has been
15 hidden by type abstraction (modules etc.). This is considered a
16 good thing, since it assists with the intended use, which is to
17 maximise value sharing.
23 type delayed
= unit -> t
24 val compare
: t
-> t
-> int
25 val eq
: t
-> t
-> bool
26 val mkFresh
: string -> delayed list
-> delayed
27 val mkTuple
: delayed list
-> delayed
28 val mkPolyv
: (string * delayed
option) list
-> delayed list
-> delayed
31 module StringMap
= Map.Make
(Interned
)
32 module IntMap
= Map.Make
(struct type t
= int let compare = Pervasives.compare end)
33 module StringSet
= Set.Make
(Interned
)
41 [`Variant
of (delayed
option StringMap.t
)
42 |`Gen
of Interned.t
* delayed list
] * int
44 and delayed
= unit -> t
46 let make_fresh row
: t
=
47 (* Just allocate a pointer for now. Dereference the row later *)
48 `Variant row
, fresh ()
52 type map
= int list
IntMap.t
53 let equalp : map
-> int -> int -> bool
55 try List.mem r
(IntMap.find l map
)
56 with Not_found
-> false
58 let record_equality : map
-> int -> int -> map
=
62 let vals = IntMap.find l map
63 in IntMap.add l
(r
::vals) map
66 in add (add map l r
) r l
69 let keys : 'a
StringMap.t
-> StringSet.t
=
71 StringMap.fold
(fun k _ set
-> StringSet.add k set
) m
StringSet.empty
73 let rec equal : EqualMap.map
-> t
-> t
-> bool
74 = fun equalmap
(l
,lid
) (r
,rid
) ->
75 if lid
= rid
then true
76 else if EqualMap.equalp equalmap lid rid
then true
78 | `Variant lrow
, `Variant rrow
->
79 (* distinct types. assume they're equal for now; record
80 that fact in the map, then look inside the types for
81 evidence to the contrary *)
82 equal_rows
(EqualMap.record_equality equalmap lid rid
) lrow rrow
83 | `Gen
(lname
, ls
), `Gen
(rname
, rs
) when Interned.eq lname rname
->
84 List.for_all2
(fun l r
-> equal equalmap
(l
()) (r
())) ls rs
86 and equal_rows equalmap lfields rfields
=
87 equal_names lfields rfields
90 let t'
= StringMap.find name rfields
in
94 equal equalmap
(t ()) (t'
()) && eq
98 and equal_names lmap rmap
=
99 StringSet.equal (keys lmap
) (keys rmap
)
101 let mkFresh name args
=
102 let t : t = `Gen
(Interned.intern name
, args
), fresh () in
106 mkFresh (string_of_int
(List.length args
)) args
108 let mkPolyv (args
: (string * delayed
option) list
) (extends
: delayed list
) : delayed
=
109 (* assume all extensions have to be completely known types at this
113 (fun map extension
->
114 match fst
(extension
()) with
116 StringMap.fold
StringMap.add map map'
117 | `Gen _
-> assert false)
123 (fun map
(name
, t) ->
124 StringMap.add (Interned.intern name
) t map
)
127 let fresh = make_fresh row in
129 let eq = equal IntMap.empty
131 let rec compare recargs
(lrep
,lid
as l
) (rrep
,rid
as r
) =
133 else if EqualMap.equalp recargs lid rid
then 0
134 else match lrep
, rrep
with
135 | `Gen
(lname
, ls
), `Gen
(rname
, rs
) ->
136 begin match Pervasives.compare lname rname
with
138 begin match Pervasives.compare (List.length ls
) (List.length rs
) with
143 else compare recargs
(l
()) (r
()))
149 | `Variant lrow
, `Variant rrow
->
150 compare_rows
(EqualMap.record_equality recargs lid rid
) lrow rrow
151 | `Variant _
, `Gen _
-> -1
152 | `Gen _
, `Variant _
-> 1
153 and compare_rows recargs lrow rrow
=
154 match StringSet.compare (keys lrow
) (keys rrow
) with
155 | 0 -> StringMap.compare
156 (fun l r
-> match l
, r
with
158 | Some l
, Some r
-> compare recargs
(l
()) (r
())
160 | Some _
, None
-> 1) lrow rrow
163 let compare = compare IntMap.empty
167 type dynamic
= Obj.t * TypeRep.t
168 let tagOf (_
, tag
) = tag
169 let untag (obj
, tag
) target
=
170 if TypeRep.eq tag target
174 (* Signature for type representations *)
175 module type Typeable
=
178 val type_rep
: unit -> TypeRep.t
179 val has_type
: dynamic
-> bool
180 val cast
: dynamic
-> a
option
181 val throwing_cast
: dynamic
-> a
182 val make_dynamic
: a
-> dynamic
183 val mk
: a
-> dynamic
186 exception CastFailure
of string
188 module Defaults
(T
: (sig
190 val type_rep
: unit -> TypeRep.t
192 : Typeable
with type a
= T.a
=
195 let has_type o
= tagOf o
= type_rep
()
197 match untag d
(type_rep
()) with
198 | Some
c -> Some
(Obj.obj
c)
200 let make_dynamic o
= (Obj.repr o
, type_rep
())
201 let mk = make_dynamic
202 let throwing_cast d
=
204 | None
-> (*raise (CastFailure ("cast from type "^
205 TypeRep.Show_t.show (tagOf d) ^" to type "^
206 TypeRep.Show_t.show (T.type_rep ()) ^" failed"))*)
207 raise
(CastFailure
"cast failed")
211 module Typeable_list
(A
:Typeable
) : Typeable
with type a
= A.a list
=
212 Defaults
(struct type a
= A.a list
213 let type_rep = TypeRep.mkFresh "Primitive.list" [A.type_rep]
216 module Typeable_option
(A
:Typeable
) : Typeable
with type a
= A.a
option =
217 Defaults
(struct type a
= A.a
option
218 let type_rep = TypeRep.mkFresh "Primitive.option" [A.type_rep]
221 module Primitive_typeable
(T
: sig type t val magic
: string end) : Typeable
with type a
= T.t =
222 Defaults
(struct type a
= T.t
223 let type_rep = TypeRep.mkFresh T.magic
[]
225 module Typeable_unit
= Primitive_typeable
(struct type t = unit let magic = "Primitive.unit" end)
226 module Typeable_int
= Primitive_typeable
(struct type t = int let magic = "Primitive.int" end)
227 module Typeable_num
= Primitive_typeable
(struct type t = Num.num
let magic = "Primitive.Num.num" end)
228 module Typeable_float
= Primitive_typeable
(struct type t = float let magic = "Primitive.float" end)
229 module Typeable_bool
= Primitive_typeable
(struct type t = bool let magic = "Primitive.bool" end)
230 module Typeable_string
= Primitive_typeable
(struct type t = string let magic = "Primitive.string" end)
231 module Typeable_char
= Primitive_typeable
(struct type t = char
let magic = "Primitive.char" end)
233 module Typeable_ref
(A
: Typeable
) : Typeable
with type a
= A.a
ref =
234 Defaults
(struct type a
= A.a
ref
235 let type_rep = TypeRep.mkFresh "Primitive.ref" [A.type_rep]