adamc@81
|
1 (* Copyright (c) 2008, Adam Chlipala
|
adamc@81
|
2 * All rights reserved.
|
adamc@81
|
3 *
|
adamc@81
|
4 * Redistribution and use in source and binary forms, with or without
|
adamc@81
|
5 * modification, are permitted provided that the following conditions are met:
|
adamc@81
|
6 *
|
adamc@81
|
7 * - Redistributions of source code must retain the above copyright notice,
|
adamc@81
|
8 * this list of conditions and the following disclaimer.
|
adamc@81
|
9 * - Redistributions in binary form must reproduce the above copyright notice,
|
adamc@81
|
10 * this list of conditions and the following disclaimer in the documentation
|
adamc@81
|
11 * and/or other materials provided with the distribution.
|
adamc@81
|
12 * - The names of contributors may not be used to endorse or promote products
|
adamc@81
|
13 * derived from this software without specific prior written permission.
|
adamc@81
|
14 *
|
adamc@81
|
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
adamc@81
|
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
adamc@81
|
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
adamc@81
|
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
adamc@81
|
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
adamc@81
|
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
adamc@81
|
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
adamc@81
|
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
adamc@81
|
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
adamc@81
|
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
adamc@81
|
25 * POSSIBILITY OF SUCH DAMAGE.
|
adamc@81
|
26 *)
|
adamc@81
|
27
|
adamc@81
|
28 structure ElabOps :> ELAB_OPS = struct
|
adamc@81
|
29
|
adamc@81
|
30 open Elab
|
adamc@81
|
31
|
adamc@81
|
32 structure E = ElabEnv
|
adamc@81
|
33 structure U = ElabUtil
|
adamc@81
|
34
|
adamc@81
|
35 val liftConInCon = E.liftConInCon
|
adamc@81
|
36
|
adamc@81
|
37 val subConInCon =
|
adamc@81
|
38 U.Con.mapB {kind = fn k => k,
|
adamc@81
|
39 con = fn (xn, rep) => fn c =>
|
adamc@81
|
40 case c of
|
adamc@81
|
41 CRel xn' =>
|
adamc@81
|
42 (case Int.compare (xn', xn) of
|
adamc@81
|
43 EQUAL => #1 rep
|
adamc@81
|
44 | GREATER => CRel (xn' - 1)
|
adamc@81
|
45 | LESS => c)
|
adamc@81
|
46 (*| CUnif _ => raise SynUnif*)
|
adamc@81
|
47 | _ => c,
|
adamc@81
|
48 bind = fn ((xn, rep), U.Con.Rel _) => (xn+1, liftConInCon 0 rep)
|
adamc@81
|
49 | (ctx, _) => ctx}
|
adamc@81
|
50
|
adamc@81
|
51 fun subStrInSgn (m1, m2) =
|
adamc@81
|
52 U.Sgn.map {kind = fn k => k,
|
adamc@81
|
53 con = fn c as CModProj (m1', ms, x) =>
|
adamc@81
|
54 if m1 = m1' then
|
adamc@81
|
55 CModProj (m2, ms, x)
|
adamc@81
|
56 else
|
adamc@81
|
57 c
|
adamc@81
|
58 | c => c,
|
adamc@81
|
59 sgn_item = fn sgi => sgi,
|
adamc@81
|
60 sgn = fn sgn => sgn}
|
adamc@81
|
61
|
adamc@81
|
62
|
adamc@81
|
63 fun hnormCon env (cAll as (c, loc)) =
|
adamc@81
|
64 case c of
|
adamc@81
|
65 CUnif (_, _, _, ref (SOME c)) => hnormCon env c
|
adamc@81
|
66
|
adamc@81
|
67 | CNamed xn =>
|
adamc@81
|
68 (case E.lookupCNamed env xn of
|
adamc@81
|
69 (_, _, SOME c') => hnormCon env c'
|
adamc@81
|
70 | _ => cAll)
|
adamc@81
|
71
|
adamc@81
|
72 | CModProj (n, ms, x) =>
|
adamc@81
|
73 let
|
adamc@81
|
74 val (_, sgn) = E.lookupStrNamed env n
|
adamc@81
|
75 val (str, sgn) = foldl (fn (m, (str, sgn)) =>
|
adamc@81
|
76 case E.projectStr env {sgn = sgn, str = str, field = m} of
|
adamc@81
|
77 NONE => raise Fail "hnormCon: Unknown substructure"
|
adamc@81
|
78 | SOME sgn => ((StrProj (str, m), loc), sgn))
|
adamc@81
|
79 ((StrVar n, loc), sgn) ms
|
adamc@81
|
80 in
|
adamc@81
|
81 case E.projectCon env {sgn = sgn, str = str, field = x} of
|
adamc@81
|
82 NONE => raise Fail "kindof: Unknown con in structure"
|
adamc@81
|
83 | SOME (_, NONE) => cAll
|
adamc@81
|
84 | SOME (_, SOME c) => hnormCon env c
|
adamc@81
|
85 end
|
adamc@81
|
86
|
adamc@81
|
87 | CApp (c1, c2) =>
|
adamc@81
|
88 (case #1 (hnormCon env c1) of
|
adamc@81
|
89 CAbs (x, k, cb) =>
|
adamc@81
|
90 let
|
adamc@81
|
91 val sc = (hnormCon env (subConInCon (0, c2) cb))
|
adamc@81
|
92 handle SynUnif => cAll
|
adamc@81
|
93 (*val env' = E.pushCRel env x k*)
|
adamc@81
|
94 in
|
adamc@328
|
95 (*Print.eprefaces "Subst" [("x", Print.PD.string x),
|
adamc@328
|
96 ("cb", ElabPrint.p_con env' cb),
|
adamc@328
|
97 ("c2", ElabPrint.p_con env c2),
|
adamc@328
|
98 ("sc", ElabPrint.p_con env sc)];*)
|
adamc@81
|
99 sc
|
adamc@81
|
100 end
|
adamc@326
|
101 | c1' as CApp (c', i) =>
|
adamc@326
|
102 let
|
adamc@326
|
103 fun default () = (CApp ((c1', loc), hnormCon env c2), loc)
|
adamc@326
|
104 in
|
adamc@326
|
105 case #1 (hnormCon env c') of
|
adamc@326
|
106 CApp (c', f) =>
|
adamc@326
|
107 (case #1 (hnormCon env c') of
|
adamc@326
|
108 CFold ks =>
|
adamc@326
|
109 (case #1 (hnormCon env c2) of
|
adamc@326
|
110 CRecord (_, []) => hnormCon env i
|
adamc@326
|
111 | CRecord (k, (x, c) :: rest) =>
|
adamc@326
|
112 hnormCon env
|
adamc@326
|
113 (CApp ((CApp ((CApp (f, x), loc), c), loc),
|
adamc@81
|
114 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
|
adamc@326
|
115 (CRecord (k, rest), loc)), loc)), loc)
|
adamc@326
|
116 | CConcat ((CRecord (k, (x, c) :: rest), _), rest') =>
|
adamc@326
|
117 let
|
adamc@326
|
118 val rest'' = (CConcat ((CRecord (k, rest), loc), rest'), loc)
|
adamc@81
|
119
|
adamc@326
|
120 (*val ccc = (CApp ((CApp ((CApp (f, x), loc), c), loc),
|
adamc@326
|
121 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
|
adamc@326
|
122 rest''), loc)), loc)*)
|
adamc@326
|
123 in
|
adamc@326
|
124 (*eprefaces "Red to" [("ccc", p_con env ccc), ("ccc'", p_con env (hnormCon env ccc))];*)
|
adamc@326
|
125 hnormCon env
|
adamc@326
|
126 (CApp ((CApp ((CApp (f, x), loc), c), loc),
|
adamc@81
|
127 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
|
adamc@326
|
128 rest''), loc)), loc)
|
adamc@326
|
129 end
|
adamc@329
|
130 | _ =>
|
adamc@329
|
131 let
|
adamc@329
|
132 fun cunif () =
|
adamc@329
|
133 let
|
adamc@329
|
134 val r = ref NONE
|
adamc@329
|
135 in
|
adamc@329
|
136 (r, (CUnif (loc, (KType, loc), "_", r), loc))
|
adamc@329
|
137 end
|
adamc@329
|
138
|
adamc@329
|
139 val (nmR, nm) = cunif ()
|
adamc@329
|
140 val (vR, v) = cunif ()
|
adamc@329
|
141 val (rR, r) = cunif ()
|
adamc@329
|
142
|
adamc@329
|
143 val c = f
|
adamc@329
|
144 val c = (CApp (c, nm), loc)
|
adamc@329
|
145 val c = (CApp (c, v), loc)
|
adamc@329
|
146 val c = (CApp (c, r), loc)
|
adamc@329
|
147 fun unconstraint c =
|
adamc@329
|
148 case hnormCon env c of
|
adamc@345
|
149 (CDisjoint (_, _, _, c), _) => unconstraint c
|
adamc@329
|
150 | c => c
|
adamc@329
|
151 val c = unconstraint c
|
adamc@339
|
152
|
adamc@494
|
153 fun tryDistributivity () =
|
adamc@494
|
154 let
|
adamc@494
|
155 fun distribute (c1, c2) =
|
adamc@494
|
156 let
|
adamc@494
|
157 val c = (CFold ks, loc)
|
adamc@494
|
158 val c = (CApp (c, f), loc)
|
adamc@494
|
159 val c = (CApp (c, i), loc)
|
adamc@494
|
160
|
adamc@494
|
161 val c1 = (CApp (c, c1), loc)
|
adamc@494
|
162 val c2 = (CApp (c, c2), loc)
|
adamc@494
|
163 val c = (CConcat (c1, c2), loc)
|
adamc@494
|
164 in
|
adamc@494
|
165 hnormCon env c
|
adamc@494
|
166 end
|
adamc@494
|
167 in
|
adamc@494
|
168 case (hnormCon env i, hnormCon env c2, hnormCon env c) of
|
adamc@494
|
169 ((CRecord (_, []), _),
|
adamc@494
|
170 (CConcat (arg1, arg2), _),
|
adamc@494
|
171 (CConcat (c1, c2'), _)) =>
|
adamc@494
|
172 (case (hnormCon env c1, hnormCon env c2') of
|
adamc@494
|
173 ((CRecord (_, [(nm', v')]), _),
|
adamc@494
|
174 (CUnif (_, _, _, rR'), _)) =>
|
adamc@494
|
175 (case hnormCon env nm' of
|
adamc@494
|
176 (CUnif (_, _, _, nmR'), _) =>
|
adamc@494
|
177 if nmR' = nmR andalso rR' = rR then
|
adamc@494
|
178 distribute (arg1, arg2)
|
adamc@494
|
179 else
|
adamc@494
|
180 default ()
|
adamc@494
|
181 | _ => default ())
|
adamc@494
|
182 | _ => default ())
|
adamc@494
|
183 | _ => default ()
|
adamc@494
|
184 end
|
adamc@494
|
185
|
adamc@339
|
186 fun tryFusion () =
|
adamc@339
|
187 let
|
adamc@339
|
188 fun fuse (dom, new_v, r') =
|
adamc@339
|
189 let
|
adamc@339
|
190 val ran = #2 ks
|
adamc@339
|
191
|
adamc@339
|
192 val f = (CApp (f, (CRel 2, loc)), loc)
|
adamc@339
|
193 val f = (CApp (f, new_v), loc)
|
adamc@339
|
194 val f = (CApp (f, (CRel 0, loc)), loc)
|
adamc@339
|
195 val f = (CAbs ("acc", ran, f), loc)
|
adamc@339
|
196 val f = (CAbs ("v", dom, f), loc)
|
adamc@339
|
197 val f = (CAbs ("nm", (KName, loc), f), loc)
|
adamc@339
|
198
|
adamc@339
|
199 val c = (CFold (dom, ran), loc)
|
adamc@339
|
200 val c = (CApp (c, f), loc)
|
adamc@339
|
201 val c = (CApp (c, i), loc)
|
adamc@339
|
202 val c = (CApp (c, r'), loc)
|
adamc@339
|
203 in
|
adamc@339
|
204 hnormCon env c
|
adamc@339
|
205 end
|
adamc@339
|
206 in
|
adamc@339
|
207 case #1 (hnormCon env c2) of
|
adamc@339
|
208 CApp (f, r') =>
|
adamc@339
|
209 (case #1 (hnormCon env f) of
|
adamc@339
|
210 CApp (f, inner_i) =>
|
adamc@339
|
211 (case (#1 (hnormCon env f), #1 (hnormCon env inner_i)) of
|
adamc@339
|
212 (CApp (f, inner_f), CRecord (_, [])) =>
|
adamc@339
|
213 (case #1 (hnormCon env f) of
|
adamc@339
|
214 CFold (dom, _) =>
|
adamc@339
|
215 let
|
adamc@339
|
216 val c = inner_f
|
adamc@339
|
217 val c = (CApp (c, nm), loc)
|
adamc@339
|
218 val c = (CApp (c, v), loc)
|
adamc@339
|
219 val c = (CApp (c, r), loc)
|
adamc@339
|
220 val c = unconstraint c
|
adamc@339
|
221
|
adamc@339
|
222 (*val () = Print.prefaces "Onto something!"
|
adamc@339
|
223 [("c", ElabPrint.p_con env cAll),
|
adamc@339
|
224 ("c'", ElabPrint.p_con env c)]*)
|
adamc@339
|
225
|
adamc@339
|
226 in
|
adamc@339
|
227 case #1 (hnormCon env c) of
|
adamc@339
|
228 CConcat (first, rest) =>
|
adamc@339
|
229 (case (#1 (hnormCon env first),
|
adamc@339
|
230 #1 (hnormCon env rest)) of
|
adamc@339
|
231 (CRecord (_, [(nm', v')]),
|
adamc@339
|
232 CUnif (_, _, _, rR')) =>
|
adamc@339
|
233 (case #1 (hnormCon env nm') of
|
adamc@339
|
234 CUnif (_, _, _, nmR') =>
|
adamc@339
|
235 if rR' = rR andalso nmR' = nmR then
|
adamc@339
|
236 (nmR := SOME (CRel 2, loc);
|
adamc@339
|
237 vR := SOME (CRel 1, loc);
|
adamc@339
|
238 rR := SOME (CError, loc);
|
adamc@339
|
239 fuse (dom, v', r'))
|
adamc@339
|
240 else
|
adamc@494
|
241 tryDistributivity ()
|
adamc@494
|
242 | _ => tryDistributivity ())
|
adamc@494
|
243 | _ => tryDistributivity ())
|
adamc@494
|
244 | _ => tryDistributivity ()
|
adamc@339
|
245 end
|
adamc@494
|
246 | _ => tryDistributivity ())
|
adamc@494
|
247 | _ => tryDistributivity ())
|
adamc@494
|
248 | _ => tryDistributivity ())
|
adamc@494
|
249 | _ => tryDistributivity ()
|
adamc@339
|
250 end
|
adamc@494
|
251
|
adamc@329
|
252 in
|
adamc@329
|
253 (*Print.prefaces "Consider" [("c", ElabPrint.p_con env c)];*)
|
adamc@329
|
254 case (hnormCon env i, unconstraint c) of
|
adamc@329
|
255 ((CRecord (_, []), _),
|
adamc@329
|
256 (CConcat (c1, c2'), _)) =>
|
adamc@329
|
257 (case (hnormCon env c1, hnormCon env c2') of
|
adamc@329
|
258 ((CRecord (_, [(nm', v')]), _),
|
adamc@329
|
259 (CUnif (_, _, _, rR'), _)) =>
|
adamc@329
|
260 (case (hnormCon env nm', hnormCon env v') of
|
adamc@329
|
261 ((CUnif (_, _, _, nmR'), _),
|
adamc@329
|
262 (CUnif (_, _, _, vR'), _)) =>
|
adamc@329
|
263 if nmR' = nmR andalso vR' = vR andalso rR' = rR then
|
adamc@329
|
264 hnormCon env c2
|
adamc@329
|
265 else
|
adamc@339
|
266 tryFusion ()
|
adamc@339
|
267 | _ => tryFusion ())
|
adamc@339
|
268 | _ => tryFusion ())
|
adamc@339
|
269 | _ => tryFusion ()
|
adamc@329
|
270 end)
|
adamc@326
|
271 | _ => default ())
|
adamc@326
|
272 | _ => default ()
|
adamc@326
|
273 end
|
adamc@326
|
274 | c1' => (CApp ((c1', loc), hnormCon env c2), loc))
|
adamc@81
|
275
|
adamc@81
|
276 | CConcat (c1, c2) =>
|
adamc@81
|
277 (case (hnormCon env c1, hnormCon env c2) of
|
adamc@81
|
278 ((CRecord (k, xcs1), loc), (CRecord (_, xcs2), _)) =>
|
adamc@81
|
279 (CRecord (k, xcs1 @ xcs2), loc)
|
adamc@81
|
280 | ((CRecord (_, []), _), c2') => c2'
|
adamc@81
|
281 | ((CConcat (c11, c12), loc), c2') =>
|
adamc@81
|
282 hnormCon env (CConcat (c11, (CConcat (c12, c2'), loc)), loc)
|
adamc@209
|
283 | (c1', (CRecord (_, []), _)) => c1'
|
adamc@329
|
284 | (c1', c2') => (CConcat (c1', c2'), loc))
|
adamc@81
|
285
|
adamc@207
|
286 | CProj (c, n) =>
|
adamc@207
|
287 (case hnormCon env c of
|
adamc@207
|
288 (CTuple cs, _) => hnormCon env (List.nth (cs, n - 1))
|
adamc@207
|
289 | _ => cAll)
|
adamc@207
|
290
|
adamc@81
|
291 | _ => cAll
|
adamc@81
|
292
|
adamc@81
|
293 end
|