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@21
|
68 val liftConInExp =
|
adamc@21
|
69 U.Exp.mapB {kind = fn k => k,
|
adamc@21
|
70 con = fn bound => fn c =>
|
adamc@21
|
71 case c of
|
adamc@21
|
72 CRel xn =>
|
adamc@21
|
73 if xn < bound then
|
adamc@21
|
74 c
|
adamc@21
|
75 else
|
adamc@21
|
76 CRel (xn + 1)
|
adamc@21
|
77 | _ => c,
|
adamc@21
|
78 exp = fn _ => fn e => e,
|
adamc@21
|
79 bind = fn (bound, U.Exp.RelC _) => bound + 1
|
adamc@21
|
80 | (bound, _) => bound}
|
adamc@21
|
81
|
adamc@21
|
82 val subConInExp =
|
adamc@21
|
83 U.Exp.mapB {kind = fn k => k,
|
adamc@21
|
84 con = fn (xn, rep) => fn c =>
|
adamc@21
|
85 case c of
|
adamc@21
|
86 CRel xn' =>
|
adamc@74
|
87 (case Int.compare (xn', xn) of
|
adamc@74
|
88 EQUAL => #1 rep
|
adamc@74
|
89 | GREATER => CRel (xn' - 1)
|
adamc@74
|
90 | LESS => c)
|
adamc@21
|
91 | _ => c,
|
adamc@21
|
92 exp = fn _ => fn e => e,
|
adamc@21
|
93 bind = fn ((xn, rep), U.Exp.RelC _) => (xn+1, liftConInCon 0 rep)
|
adamc@21
|
94 | (ctx, _) => ctx}
|
adamc@21
|
95
|
adamc@20
|
96 fun bindC (env, b) =
|
adamc@20
|
97 case b of
|
adamc@20
|
98 U.Con.Rel (x, k) => E.pushCRel env x k
|
adamc@20
|
99 | U.Con.Named (x, n, k, co) => E.pushCNamed env x n k co
|
adamc@20
|
100
|
adamc@20
|
101 fun bind (env, b) =
|
adamc@20
|
102 case b of
|
adamc@20
|
103 U.Decl.RelC (x, k) => E.pushCRel env x k
|
adamc@20
|
104 | U.Decl.NamedC (x, n, k, co) => E.pushCNamed env x n k co
|
adamc@20
|
105 | U.Decl.RelE (x, t) => E.pushERel env x t
|
adamc@109
|
106 | U.Decl.NamedE (x, n, t, eo, s) => E.pushENamed env x n t eo s
|
adamc@20
|
107
|
adamc@20
|
108 fun kind k = k
|
adamc@20
|
109
|
adamc@20
|
110 fun con env c =
|
adamc@20
|
111 case c of
|
adamc@70
|
112 CApp ((CApp ((CApp ((CFold ks, _), f), _), i), loc), (CRecord (k, xcs), _)) =>
|
adamc@70
|
113 (case xcs of
|
adamc@70
|
114 [] => #1 i
|
adamc@70
|
115 | (n, v) :: rest =>
|
adamc@70
|
116 #1 (reduceCon env (CApp ((CApp ((CApp (f, n), loc), v), loc),
|
adamc@70
|
117 (CApp ((CApp ((CApp ((CFold ks, loc), f), loc), i), loc),
|
adamc@70
|
118 (CRecord (k, rest), loc)), loc)), loc)))
|
adamc@70
|
119 | CApp ((CAbs (_, _, c1), loc), c2) =>
|
adamc@20
|
120 #1 (reduceCon env (subConInCon (0, c2) c1))
|
adamc@20
|
121 | CNamed n =>
|
adamc@20
|
122 (case E.lookupCNamed env n of
|
adamc@20
|
123 (_, _, SOME c') => #1 c'
|
adamc@20
|
124 | _ => c)
|
adamc@20
|
125 | CConcat ((CRecord (k, xcs1), loc), (CRecord (_, xcs2), _)) => CRecord (k, xcs1 @ xcs2)
|
adamc@215
|
126
|
adamc@215
|
127 | CProj ((CTuple cs, _), n) => #1 (List.nth (cs, n - 1))
|
adamc@215
|
128
|
adamc@20
|
129 | _ => c
|
adamc@20
|
130
|
adamc@20
|
131 and reduceCon env = U.Con.mapB {kind = kind, con = con, bind = bindC} env
|
adamc@20
|
132
|
adamc@21
|
133 fun exp env e =
|
adamc@21
|
134 case e of
|
adamc@21
|
135 ENamed n =>
|
adamc@21
|
136 (case E.lookupENamed env n of
|
adamc@109
|
137 (_, _, SOME e', _) => #1 e'
|
adamc@21
|
138 | _ => e)
|
adamc@21
|
139
|
adamc@74
|
140 | ECApp ((EApp ((EApp ((ECApp ((EFold ks, _), ran), _), f), _), i), _), (CRecord (k, xcs), loc)) =>
|
adamc@74
|
141 (case xcs of
|
adamc@74
|
142 [] => #1 i
|
adamc@74
|
143 | (n, v) :: rest =>
|
adamc@74
|
144 #1 (reduceExp env (EApp ((ECApp ((ECApp ((ECApp (f, n), loc), v), loc), (CRecord (k, rest), loc)), loc),
|
adamc@74
|
145 (ECApp ((EApp ((EApp ((ECApp ((EFold ks, loc), ran), loc), f), loc), i), loc),
|
adamc@74
|
146 (CRecord (k, rest), loc)), loc)), loc)))
|
adamc@74
|
147
|
adamc@26
|
148 | EApp ((EAbs (_, _, _, e1), loc), e2) =>
|
adamc@21
|
149 #1 (reduceExp env (subExpInExp (0, e2) e1))
|
adamc@21
|
150 | ECApp ((ECAbs (_, _, e1), loc), c) =>
|
adamc@21
|
151 #1 (reduceExp env (subConInExp (0, c) e1))
|
adamc@21
|
152
|
adamc@22
|
153 | EField ((ERecord xes, _), (CName x, _), _) =>
|
adamc@29
|
154 (case List.find (fn ((CName x', _), _, _) => x' = x
|
adamc@22
|
155 | _ => false) xes of
|
adamc@29
|
156 SOME (_, e, _) => #1 e
|
adamc@22
|
157 | NONE => e)
|
adamc@149
|
158 | ECut (r as (_, loc), _, {rest = (CRecord (k, xts), _), ...}) =>
|
adamc@149
|
159 let
|
adamc@149
|
160 fun fields (remaining, passed) =
|
adamc@149
|
161 case remaining of
|
adamc@149
|
162 [] => []
|
adamc@149
|
163 | (x, t) :: rest =>
|
adamc@149
|
164 (x,
|
adamc@149
|
165 (EField (r, x, {field = t,
|
adamc@149
|
166 rest = (CRecord (k, List.revAppend (passed, rest)), loc)}), loc),
|
adamc@149
|
167 t) :: fields (rest, (x, t) :: passed)
|
adamc@149
|
168 in
|
adamc@149
|
169 #1 (reduceExp env (ERecord (fields (xts, [])), loc))
|
adamc@149
|
170 end
|
adamc@22
|
171
|
adamc@21
|
172 | _ => e
|
adamc@21
|
173
|
adamc@21
|
174 and reduceExp env = U.Exp.mapB {kind = kind, con = con, exp = exp, bind = bind} env
|
adamc@20
|
175
|
adamc@20
|
176 fun decl env d = d
|
adamc@20
|
177
|
adamc@133
|
178 val reduce = U.File.mapB {kind = kind, con = con, exp = exp, decl = decl, bind = bind} E.empty
|
adamc@20
|
179
|
adamc@20
|
180 end
|