adamc@20
|
1 (* Copyright (c) 2008, Adam Chlipala
|
adamc@20
|
2 * All rights reserved.
|
adamc@20
|
3 *
|
adamc@20
|
4 * Redistribution and use in source and binary forms, with or without
|
adamc@20
|
5 * modification, are permitted provided that the following conditions are met:
|
adamc@20
|
6 *
|
adamc@20
|
7 * - Redistributions of source code must retain the above copyright notice,
|
adamc@20
|
8 * this list of conditions and the following disclaimer.
|
adamc@20
|
9 * - Redistributions in binary form must reproduce the above copyright notice,
|
adamc@20
|
10 * this list of conditions and the following disclaimer in the documentation
|
adamc@20
|
11 * and/or other materials provided with the distribution.
|
adamc@20
|
12 * - The names of contributors may not be used to endorse or promote products
|
adamc@20
|
13 * derived from this software without specific prior written permission.
|
adamc@20
|
14 *
|
adamc@20
|
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
adamc@20
|
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
adamc@20
|
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
adamc@20
|
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
adamc@20
|
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
adamc@20
|
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
adamc@20
|
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
adamc@20
|
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
adamc@20
|
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
adamc@20
|
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
adamc@20
|
25 * POSSIBILITY OF SUCH DAMAGE.
|
adamc@20
|
26 *)
|
adamc@20
|
27
|
adamc@20
|
28 (* Simplify a Core program algebraically *)
|
adamc@20
|
29
|
adamc@20
|
30 structure Reduce :> REDUCE = struct
|
adamc@20
|
31
|
adamc@20
|
32 open Core
|
adamc@20
|
33
|
adamc@20
|
34 structure E = CoreEnv
|
adamc@20
|
35 structure U = CoreUtil
|
adamc@20
|
36
|
adamc@20
|
37 val liftConInCon = E.liftConInCon
|
adamc@193
|
38 val subConInCon = E.subConInCon
|
adamc@20
|
39
|
adamc@21
|
40 val liftExpInExp =
|
adamc@21
|
41 U.Exp.mapB {kind = fn k => k,
|
adamc@21
|
42 con = fn _ => fn c => c,
|
adamc@21
|
43 exp = fn bound => fn e =>
|
adamc@21
|
44 case e of
|
adamc@21
|
45 ERel xn =>
|
adamc@21
|
46 if xn < bound then
|
adamc@21
|
47 e
|
adamc@21
|
48 else
|
adamc@21
|
49 ERel (xn + 1)
|
adamc@21
|
50 | _ => e,
|
adamc@21
|
51 bind = fn (bound, U.Exp.RelE _) => bound + 1
|
adamc@21
|
52 | (bound, _) => bound}
|
adamc@21
|
53
|
adamc@21
|
54 val subExpInExp =
|
adamc@21
|
55 U.Exp.mapB {kind = fn k => k,
|
adamc@21
|
56 con = fn _ => fn c => c,
|
adamc@21
|
57 exp = fn (xn, rep) => fn e =>
|
adamc@21
|
58 case e of
|
adamc@21
|
59 ERel xn' =>
|
adamc@74
|
60 (case Int.compare (xn', xn) of
|
adamc@74
|
61 EQUAL => #1 rep
|
adamc@74
|
62 | GREATER=> ERel (xn' - 1)
|
adamc@74
|
63 | LESS => e)
|
adamc@21
|
64 | _ => e,
|
adamc@21
|
65 bind = fn ((xn, rep), U.Exp.RelE _) => (xn+1, liftExpInExp 0 rep)
|
adamc@21
|
66 | (ctx, _) => ctx}
|
adamc@21
|
67
|
adamc@315
|
68 val liftConInExp = E.liftConInExp
|
adamc@315
|
69 val subConInExp = E.subConInExp
|
adamc@21
|
70
|
adamc@20
|
71 fun bindC (env, b) =
|
adamc@20
|
72 case b of
|
adamc@20
|
73 U.Con.Rel (x, k) => E.pushCRel env x k
|
adamc@20
|
74 | U.Con.Named (x, n, k, co) => E.pushCNamed env x n k co
|
adamc@20
|
75
|
adamc@20
|
76 fun bind (env, b) =
|
adamc@20
|
77 case b of
|
adamc@20
|
78 U.Decl.RelC (x, k) => E.pushCRel env x k
|
adamc@20
|
79 | U.Decl.NamedC (x, n, k, co) => E.pushCNamed env x n k co
|
adamc@20
|
80 | U.Decl.RelE (x, t) => E.pushERel env x t
|
adamc@109
|
81 | U.Decl.NamedE (x, n, t, eo, s) => E.pushENamed env x n t eo s
|
adamc@20
|
82
|
adamc@20
|
83 fun kind k = k
|
adamc@20
|
84
|
adamc@20
|
85 fun con env c =
|
adamc@20
|
86 case c of
|
adamc@70
|
87 CApp ((CApp ((CApp ((CFold ks, _), f), _), i), loc), (CRecord (k, xcs), _)) =>
|
adamc@70
|
88 (case xcs of
|
adamc@70
|
89 [] => #1 i
|
adamc@70
|
90 | (n, v) :: rest =>
|
adamc@70
|
91 #1 (reduceCon env (CApp ((CApp ((CApp (f, n), loc), v), loc),
|
adamc@70
|
92 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
|
adamc@70
|
93 (CRecord (k, rest), loc)), loc)), loc)))
|
adamc@70
|
94 | CApp ((CAbs (_, _, c1), loc), c2) =>
|
adamc@20
|
95 #1 (reduceCon env (subConInCon (0, c2) c1))
|
adamc@20
|
96 | CNamed n =>
|
adamc@20
|
97 (case E.lookupCNamed env n of
|
adamc@20
|
98 (_, _, SOME c') => #1 c'
|
adamc@20
|
99 | _ => c)
|
adamc@20
|
100 | CConcat ((CRecord (k, xcs1), loc), (CRecord (_, xcs2), _)) => CRecord (k, xcs1 @ xcs2)
|
adamc@215
|
101
|
adamc@215
|
102 | CProj ((CTuple cs, _), n) => #1 (List.nth (cs, n - 1))
|
adamc@215
|
103
|
adamc@20
|
104 | _ => c
|
adamc@20
|
105
|
adamc@20
|
106 and reduceCon env = U.Con.mapB {kind = kind, con = con, bind = bindC} env
|
adamc@20
|
107
|
adamc@21
|
108 fun exp env e =
|
adamc@21
|
109 case e of
|
adamc@21
|
110 ENamed n =>
|
adamc@21
|
111 (case E.lookupENamed env n of
|
adamc@109
|
112 (_, _, SOME e', _) => #1 e'
|
adamc@21
|
113 | _ => e)
|
adamc@21
|
114
|
adamc@74
|
115 | ECApp ((EApp ((EApp ((ECApp ((EFold ks, _), ran), _), f), _), i), _), (CRecord (k, xcs), loc)) =>
|
adamc@74
|
116 (case xcs of
|
adamc@74
|
117 [] => #1 i
|
adamc@74
|
118 | (n, v) :: rest =>
|
adamc@74
|
119 #1 (reduceExp env (EApp ((ECApp ((ECApp ((ECApp (f, n), loc), v), loc), (CRecord (k, rest), loc)), loc),
|
adamc@74
|
120 (ECApp ((EApp ((EApp ((ECApp ((EFold ks, loc), ran), loc), f), loc), i), loc),
|
adamc@74
|
121 (CRecord (k, rest), loc)), loc)), loc)))
|
adamc@74
|
122
|
adamc@26
|
123 | EApp ((EAbs (_, _, _, e1), loc), e2) =>
|
adamc@21
|
124 #1 (reduceExp env (subExpInExp (0, e2) e1))
|
adamc@21
|
125 | ECApp ((ECAbs (_, _, e1), loc), c) =>
|
adamc@21
|
126 #1 (reduceExp env (subConInExp (0, c) e1))
|
adamc@21
|
127
|
adamc@22
|
128 | EField ((ERecord xes, _), (CName x, _), _) =>
|
adamc@29
|
129 (case List.find (fn ((CName x', _), _, _) => x' = x
|
adamc@22
|
130 | _ => false) xes of
|
adamc@29
|
131 SOME (_, e, _) => #1 e
|
adamc@22
|
132 | NONE => e)
|
adamc@339
|
133 | EWith (r as (_, loc), x, e, {rest = (CRecord (k, xts), _), field}) =>
|
adamc@339
|
134 let
|
adamc@339
|
135 fun fields (remaining, passed) =
|
adamc@339
|
136 case remaining of
|
adamc@339
|
137 [] => []
|
adamc@339
|
138 | (x, t) :: rest =>
|
adamc@339
|
139 (x,
|
adamc@339
|
140 (EField (r, x, {field = t,
|
adamc@339
|
141 rest = (CRecord (k, List.revAppend (passed, rest)), loc)}), loc),
|
adamc@339
|
142 t) :: fields (rest, (x, t) :: passed)
|
adamc@339
|
143 in
|
adamc@339
|
144 #1 (reduceExp env (ERecord ((x, e, field) :: fields (xts, [])), loc))
|
adamc@339
|
145 end
|
adamc@149
|
146 | ECut (r as (_, loc), _, {rest = (CRecord (k, xts), _), ...}) =>
|
adamc@149
|
147 let
|
adamc@149
|
148 fun fields (remaining, passed) =
|
adamc@149
|
149 case remaining of
|
adamc@149
|
150 [] => []
|
adamc@149
|
151 | (x, t) :: rest =>
|
adamc@149
|
152 (x,
|
adamc@149
|
153 (EField (r, x, {field = t,
|
adamc@149
|
154 rest = (CRecord (k, List.revAppend (passed, rest)), loc)}), loc),
|
adamc@149
|
155 t) :: fields (rest, (x, t) :: passed)
|
adamc@149
|
156 in
|
adamc@149
|
157 #1 (reduceExp env (ERecord (fields (xts, [])), loc))
|
adamc@149
|
158 end
|
adamc@22
|
159
|
adamc@21
|
160 | _ => e
|
adamc@21
|
161
|
adamc@21
|
162 and reduceExp env = U.Exp.mapB {kind = kind, con = con, exp = exp, bind = bind} env
|
adamc@20
|
163
|
adamc@330
|
164 fun decl env d =
|
adamc@330
|
165 case d of
|
adamc@330
|
166 DValRec [vi as (_, n, _, e, _)] =>
|
adamc@330
|
167 let
|
adamc@330
|
168 fun kind _ = false
|
adamc@330
|
169 fun con _ = false
|
adamc@330
|
170 fun exp e =
|
adamc@330
|
171 case e of
|
adamc@330
|
172 ENamed n' => n' = n
|
adamc@330
|
173 | _ => false
|
adamc@330
|
174 in
|
adamc@330
|
175 if U.Exp.exists {kind = kind, con = con, exp = exp} e then
|
adamc@330
|
176 d
|
adamc@330
|
177 else
|
adamc@330
|
178 DVal vi
|
adamc@330
|
179 end
|
adamc@330
|
180 | _ => d
|
adamc@20
|
181
|
adamc@133
|
182 val reduce = U.File.mapB {kind = kind, con = con, exp = exp, decl = decl, bind = bind} E.empty
|
adamc@20
|
183
|
adamc@20
|
184 end
|