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@508
|
34 structure IM = IntBinaryMap
|
adamc@20
|
35
|
adamc@508
|
36 datatype env_item =
|
adamc@508
|
37 UnknownC
|
adamc@508
|
38 | KnownC of con
|
adamc@21
|
39
|
adamc@508
|
40 | UnknownE
|
adamc@508
|
41 | KnownE of exp
|
adamc@20
|
42
|
adamc@508
|
43 | Lift of int * int
|
adamc@20
|
44
|
adamc@508
|
45 type env = env_item list
|
adamc@20
|
46
|
adamc@508
|
47 fun conAndExp (namedC, namedE) =
|
adamc@508
|
48 let
|
adamc@508
|
49 fun con env (all as (c, loc)) =
|
adamc@508
|
50 case c of
|
adamc@508
|
51 TFun (c1, c2) => (TFun (con env c1, con env c2), loc)
|
adamc@508
|
52 | TCFun (x, k, c2) => (TCFun (x, k, con (UnknownC :: env) c2), loc)
|
adamc@508
|
53 | TRecord c => (TRecord (con env c), loc)
|
adamc@215
|
54
|
adamc@508
|
55 | CRel n =>
|
adamc@508
|
56 let
|
adamc@508
|
57 fun find (n', env, lift) =
|
adamc@508
|
58 if n' = 0 then
|
adamc@508
|
59 case env of
|
adamc@508
|
60 UnknownC :: _ => (CRel (n + lift), loc)
|
adamc@508
|
61 | KnownC c :: _ => con (Lift (lift, 0) :: env) c
|
adamc@508
|
62 | _ => raise Fail "Reduce.con: CRel [1]"
|
adamc@508
|
63 else
|
adamc@508
|
64 case env of
|
adamc@508
|
65 UnknownC :: rest => find (n' - 1, rest, lift + 1)
|
adamc@508
|
66 | KnownC _ :: rest => find (n' - 1, rest, lift)
|
adamc@508
|
67 | UnknownE :: rest => find (n' - 1, rest, lift)
|
adamc@508
|
68 | KnownE _ :: rest => find (n' - 1, rest, lift)
|
adamc@508
|
69 | Lift (lift', _) :: rest => find (n' - 1, rest, lift + lift')
|
adamc@508
|
70 | [] => raise Fail "Reduce.con: CRel [2]"
|
adamc@508
|
71 in
|
adamc@508
|
72 find (n, env, 0)
|
adamc@508
|
73 end
|
adamc@508
|
74 | CNamed n =>
|
adamc@508
|
75 (case IM.find (namedC, n) of
|
adamc@508
|
76 NONE => all
|
adamc@508
|
77 | SOME c => c)
|
adamc@508
|
78 | CFfi _ => all
|
adamc@508
|
79 | CApp (c1, c2) =>
|
adamc@508
|
80 let
|
adamc@508
|
81 val c1 = con env c1
|
adamc@508
|
82 val c2 = con env c2
|
adamc@508
|
83 in
|
adamc@508
|
84 case #1 c1 of
|
adamc@508
|
85 CAbs (_, _, b) =>
|
adamc@508
|
86 con (KnownC c2 :: env) b
|
adamc@215
|
87
|
adamc@508
|
88 | CApp ((CApp (fold as (CFold _, _), f), _), i) =>
|
adamc@508
|
89 (case #1 c2 of
|
adamc@508
|
90 CRecord (_, []) => i
|
adamc@508
|
91 | CRecord (k, (x, c) :: rest) =>
|
adamc@508
|
92 con env (CApp ((CApp ((CApp (f, x), loc), c), loc),
|
adamc@508
|
93 (CApp ((CApp ((CApp (fold, f), loc), i), loc),
|
adamc@508
|
94 (CRecord (k, rest), loc)), loc)), loc)
|
adamc@508
|
95 | _ => (CApp (c1, c2), loc))
|
adamc@20
|
96
|
adamc@508
|
97 | _ => (CApp (c1, c2), loc)
|
adamc@508
|
98 end
|
adamc@508
|
99 | CAbs (x, k, b) => (CAbs (x, k, con (UnknownC :: env) b), loc)
|
adamc@20
|
100
|
adamc@508
|
101 | CName _ => all
|
adamc@21
|
102
|
adamc@508
|
103 | CRecord (k, xcs) => (CRecord (k, map (fn (x, c) => (con env x, con env c)) xcs), loc)
|
adamc@508
|
104 | CConcat (c1, c2) =>
|
adamc@508
|
105 let
|
adamc@508
|
106 val c1 = con env c1
|
adamc@508
|
107 val c2 = con env c2
|
adamc@508
|
108 in
|
adamc@508
|
109 case (#1 c1, #1 c2) of
|
adamc@508
|
110 (CRecord (k, xcs1), CRecord (_, xcs2)) =>
|
adamc@508
|
111 (CRecord (k, xcs1 @ xcs2), loc)
|
adamc@508
|
112 | _ => (CConcat (c1, c2), loc)
|
adamc@508
|
113 end
|
adamc@508
|
114 | CFold _ => all
|
adamc@74
|
115
|
adamc@508
|
116 | CUnit => all
|
adamc@21
|
117
|
adamc@508
|
118 | CTuple cs => (CTuple (map (con env) cs), loc)
|
adamc@508
|
119 | CProj (c, n) =>
|
adamc@508
|
120 let
|
adamc@508
|
121 val c = con env c
|
adamc@508
|
122 in
|
adamc@508
|
123 case #1 c of
|
adamc@508
|
124 CTuple cs => List.nth (cs, n - 1)
|
adamc@508
|
125 | _ => (CProj (c, n), loc)
|
adamc@508
|
126 end
|
adamc@22
|
127
|
adamc@508
|
128 fun exp env e = e
|
adamc@417
|
129 in
|
adamc@508
|
130 {con = con, exp = exp}
|
adamc@417
|
131 end
|
adamc@21
|
132
|
adamc@508
|
133 fun con namedC c = #con (conAndExp (namedC, IM.empty)) [] c
|
adamc@508
|
134 fun exp (namedC, namedE) e = #exp (conAndExp (namedC, namedE)) [] e
|
adamc@20
|
135
|
adamc@508
|
136 fun reduce file =
|
adamc@508
|
137 let
|
adamc@508
|
138 fun doDecl (d as (_, loc), st as (namedC, namedE)) =
|
adamc@508
|
139 case #1 d of
|
adamc@508
|
140 DCon (x, n, k, c) =>
|
adamc@508
|
141 let
|
adamc@508
|
142 val c = con namedC c
|
adamc@508
|
143 in
|
adamc@508
|
144 ((DCon (x, n, k, c), loc),
|
adamc@508
|
145 (IM.insert (namedC, n, c), namedE))
|
adamc@508
|
146 end
|
adamc@508
|
147 | DDatatype (x, n, ps, cs) =>
|
adamc@508
|
148 ((DDatatype (x, n, ps, map (fn (x, n, co) => (x, n, Option.map (con namedC) co)) cs), loc),
|
adamc@508
|
149 st)
|
adamc@508
|
150 | DVal (x, n, t, e, s) =>
|
adamc@508
|
151 let
|
adamc@508
|
152 val t = con namedC t
|
adamc@508
|
153 val e = exp (namedC, namedE) e
|
adamc@508
|
154 in
|
adamc@508
|
155 ((DVal (x, n, t, e, s), loc),
|
adamc@508
|
156 (namedC, IM.insert (namedE, n, e)))
|
adamc@508
|
157 end
|
adamc@508
|
158 | DValRec vis =>
|
adamc@508
|
159 ((DValRec (map (fn (x, n, t, e, s) => (x, n, con namedC t, exp (namedC, namedE) e, s)) vis), loc),
|
adamc@508
|
160 st)
|
adamc@508
|
161 | DExport _ => (d, st)
|
adamc@508
|
162 | DTable (s, n, c, s') => ((DTable (s, n, con namedC c, s'), loc), st)
|
adamc@508
|
163 | DSequence _ => (d, st)
|
adamc@508
|
164 | DDatabase _ => (d, st)
|
adamc@508
|
165 | DCookie (s, n, c, s') => ((DCookie (s, n, con namedC c, s'), loc), st)
|
adamc@20
|
166
|
adamc@508
|
167 val (file, _) = ListUtil.foldlMap doDecl (IM.empty, IM.empty) file
|
adamc@508
|
168 in
|
adamc@508
|
169 file
|
adamc@508
|
170 end
|
adamc@20
|
171
|
adamc@20
|
172 end
|