Import Upstream version 20180207
[hcoop/debian/mlton.git] / mlton / atoms / hash-type.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2017 Matthew Fluet.
2 * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
5 *
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
8 *)
9
10functor HashType (S: HASH_TYPE_STRUCTS): HASH_TYPE =
11struct
12
13open S
14
15structure Type =
16 struct
17 datatype t =
18 T of {
19 hash: Word.t,
20 plist: PropertyList.t,
21 tree: tree
22 }
23 and tree =
24 Var of Tyvar.t
25 | Con of Tycon.t * t vector
26
27 local
28 fun make f (T r) = f r
29 in
30 val hash = make #hash
31 val plist = make #plist
32 val tree = make #tree
33 end
34
35 local
36 open Layout
37 in
38 val rec layoutTree =
39 fn Var a => Tyvar.layout a
40 | Con (c, ts) =>
41 seq [Tycon.layout c,
42 Vector.layout (layoutTree o tree) ts]
43 end
44
45 structure Dest =
46 struct
47 datatype dest = datatype tree
48 val dest = tree
49 end
50 open Dest
51
52 fun deConOpt t =
53 case dest t of
54 Con x => SOME x
55 | _ => NONE
56
57 fun makeHom {con, var} =
58 let
59 val {get, destroy, ...} =
60 Property.destGet
61 (plist,
62 Property.initRec
63 (fn (t, get) =>
64 case dest t of
65 Var a => var (t, a)
66 | Con (c, ts) => con (t, c, Vector.map (ts, get))))
67 in {hom = get, destroy = destroy}
68 end
69
70 fun hom {ty, var, con} =
71 let
72 val {hom, destroy} = makeHom {var = var o #2,
73 con = fn (_, c, xs) => con (c, xs)}
74 val res = hom ty
75 val _ = destroy ()
76 in res
77 end
78
79 fun makeMonoHom {con} =
80 makeHom {var = fn _ => Error.bug "HashType.Type.makeMonoHom: type variable",
81 con = con}
82
83 fun equals (t, t'): bool = PropertyList.equals (plist t, plist t')
84
85 fun layoutPretty (ty: t): Layout.t =
86 #1 (hom {con = fn (c, ts) => (Tycon.layoutAppPretty
87 (c, ts, {layoutPretty = Tycon.layout})),
88 ty = ty,
89 var = fn a => LayoutPretty.simple (Tyvar.layout a)})
90
91 fun layout (ty: t): Layout.t =
92 hom {con = Tycon.layoutApp,
93 ty = ty,
94 var = Tyvar.layout}
95
96 local
97 val same: tree * tree -> bool =
98 fn (Var a, Var a') => Tyvar.equals (a, a')
99 | (Con (c, ts), Con (c', ts')) =>
100 Tycon.equals (c, c')
101 andalso Vector.equals (ts, ts', equals)
102 | _ => false
103 val same =
104 Trace.trace2 ("HashType.Type.same", layoutTree, layoutTree, Bool.layout)
105 same
106 val table: t HashSet.t = HashSet.new {hash = hash}
107 in
108 fun lookup (hash, tr) =
109 HashSet.lookupOrInsert (table, hash,
110 fn t => same (tr, tree t),
111 fn () => T {hash = hash,
112 plist = PropertyList.new (),
113 tree = tr})
114
115 fun stats () =
116 let open Layout
117 in align [seq [str "num types in hash table = ",
118 Int.layout (HashSet.size table)],
119 Control.sizeMessage ("types hash table", table)]
120 end
121 end
122
123 fun var a = lookup (Tyvar.hash a, Var a)
124
125 local
126 val generator: Word.t = 0wx5555
127 in
128 fun con (c, ts) =
129 lookup (Vector.fold (ts, Tycon.hash c, fn (t, w) =>
130 Word.xorb (w * generator, hash t)),
131 Con (c, ts))
132 val con = Trace.trace2 ("HashType.Type.con",
133 Tycon.layout,
134 Vector.layout layout,
135 layout) con
136 end
137 end
138structure Ops = TypeOps (structure Tycon = Tycon
139 open Type)
140open Type Ops
141
142val string = word8Vector
143
144fun ofConst c =
145 let
146 datatype z = datatype Const.t
147 in
148 case c of
149 IntInf _ => intInf
150 | Null => cpointer
151 | Real r => real (RealX.size r)
152 | Word w => word (WordX.size w)
153 | WordVector v => vector (word (WordXVector.elementSize v))
154 end
155
156fun isUnit t =
157 case dest t of
158 Con (c, ts) => Vector.isEmpty ts andalso Tycon.equals (c, Tycon.tuple)
159 | _ => false
160
161fun substitute (ty, v) =
162 if Vector.isEmpty v
163 then ty (* This optimization is important so that monotypes
164 * are not substituted inside of.
165 *)
166 else
167 hom {ty = ty,
168 var = fn a => (case Vector.peek (v, fn (a', _) =>
169 Tyvar.equals (a, a')) of
170 NONE => var a
171 | SOME (_, ty) => ty),
172 con = con}
173
174val substitute =
175 Trace.trace2
176 ("HashType.substitute",
177 layout,
178 Vector.layout (Layout.tuple2 (Tyvar.layout, Type.layout)),
179 layout)
180 substitute
181
182(* fun equalss (ts: t list): t option =
183 * case ts of
184 * t :: ts =>
185 * let fun loop [] = SOME t
186 * | loop (t' :: ts) = if equals (t, t') then loop ts else NONE
187 * in loop ts
188 * end
189 * | [] => Error.bug "HashType.equals"
190 *)
191
192local
193 val out = Out.error
194 val print = Out.outputc out
195 exception TypeError
196in
197 fun error (msg, lay) =
198 (print (concat ["Type error: ", msg, "\n"])
199 ; Layout.output (lay, out)
200 ; print "\n"
201 ; raise TypeError)
202end
203
204fun tycon t =
205 case dest t of
206 Con (c, _) => c
207 | _ => Error.bug "HashType.tycon: type variable"
208
209fun containsTycon (ty, tycon) =
210 hom {ty = ty,
211 var = fn _ => false,
212 con = fn (tycon', bs) => (Tycon.equals (tycon, tycon')
213 orelse Vector.exists (bs, fn b => b))}
214
215fun checkPrimApp {args, prim, result, targs}: bool =
216 Prim.checkApp (prim,
217 {args = args,
218 result = result,
219 targs = targs,
220 typeOps = {array = array,
221 arrow = arrow,
222 bool = bool,
223 cpointer = cpointer,
224 equals = equals,
225 exn = exn,
226 intInf = intInf,
227 real = real,
228 reff = reff,
229 thread = thread,
230 unit = unit,
231 vector = vector,
232 weak = weak,
233 word = word}})
234end