Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * Copyright (C) 1997-2000 NEC Research Institute. | |
4 | * | |
5 | * MLton is released under a BSD-style license. | |
6 | * See the file MLton-LICENSE for details. | |
7 | *) | |
8 | ||
9 | functor SxmlSimplify (S: SXML_SIMPLIFY_STRUCTS): SXML_SIMPLIFY = | |
10 | struct | |
11 | ||
12 | open S | |
13 | ||
14 | structure ImplementExceptions = ImplementExceptions (open S) | |
15 | structure ImplementSuffix = ImplementSuffix (open S) | |
16 | structure Polyvariance = Polyvariance (open S) | |
17 | (* structure Uncurry = Uncurry (open S) *) | |
18 | structure CPSTransform = CPSTransform (open S) | |
19 | ||
20 | fun polyvariance (hofo, rounds, small, product) p = | |
21 | Ref.fluidLet | |
22 | (Control.polyvariance, | |
23 | SOME {hofo = hofo, rounds = rounds, small = small, product = product}, | |
24 | fn () => Polyvariance.transform p) | |
25 | ||
26 | type pass = {name: string, | |
27 | doit: Program.t -> Program.t, | |
28 | execute: bool} | |
29 | ||
30 | val sxmlPassesDefault = | |
31 | {name = "sxmlShrink1", doit = S.shrink, execute = true} :: | |
32 | {name = "implementSuffix", doit = ImplementSuffix.transform, execute = true} :: | |
33 | {name = "sxmlShrink2", doit = S.shrink, execute = true} :: | |
34 | {name = "implementExceptions", doit = ImplementExceptions.transform, execute = true} :: | |
35 | {name = "sxmlShrink3", doit = S.shrink, execute = true} :: | |
36 | (* {name = "uncurry", doit = Uncurry.transform, execute = true} :: *) | |
37 | (* {name = "sxmlShrink4", doit = S.shrink, execute = true} :: *) | |
38 | {name = "polyvariance", doit = Polyvariance.transform, execute = true} :: | |
39 | {name = "sxmlShrink4", doit = S.shrink, execute = true} :: | |
40 | nil | |
41 | ||
42 | val sxmlPassesCpsTransform = | |
43 | sxmlPassesDefault @ | |
44 | {name = "cpsTransform", doit = CPSTransform.transform, execute = true} :: | |
45 | {name = "cpsSxmlShrink5", doit = S.shrink, execute = true} :: | |
46 | {name = "cpsPolyvariance", doit = Polyvariance.transform, execute = true} :: | |
47 | {name = "cpsSxmlShrink6", doit = S.shrink, execute = true} :: | |
48 | nil | |
49 | ||
50 | val sxmlPassesMinimal = | |
51 | {name = "implementSuffix", doit = ImplementSuffix.transform, execute = true} :: | |
52 | {name = "implementExceptions", doit = ImplementExceptions.transform, execute = true} :: | |
53 | nil | |
54 | ||
55 | val sxmlPasses : pass list ref = ref sxmlPassesDefault | |
56 | ||
57 | local | |
58 | type passGen = string -> pass option | |
59 | ||
60 | fun mkSimplePassGen (name, doit): passGen = | |
61 | let val count = Counter.new 1 | |
62 | in fn s => if s = name | |
63 | then SOME {name = name ^ "#" ^ | |
64 | (Int.toString (Counter.next count)), | |
65 | doit = doit, | |
66 | execute = true} | |
67 | else NONE | |
68 | end | |
69 | ||
70 | val polyvariancePassGen = | |
71 | let | |
72 | val count = Counter.new 1 | |
73 | fun nums s = | |
74 | if s = "" | |
75 | then SOME [] | |
76 | else if String.sub (s, 0) = #"(" | |
77 | andalso String.sub (s, String.size s - 1)= #")" | |
78 | then let | |
79 | val s = String.dropFirst (String.dropLast s) | |
80 | in | |
81 | case List.fold (String.split (s, #","), SOME [], | |
82 | fn (s,SOME nums) => (case Int.fromString s of | |
83 | SOME i => SOME (i::nums) | |
84 | | NONE => NONE) | |
85 | | (_, NONE) => NONE) of | |
86 | SOME (l as _::_) => SOME (List.rev l) | |
87 | | _ => NONE | |
88 | end | |
89 | else NONE | |
90 | in | |
91 | fn s => | |
92 | if String.hasPrefix (s, {prefix = "polyvariance"}) | |
93 | then let | |
94 | fun mk (hofo, rounds, small, product) = | |
95 | SOME {name = concat ["polyvariance(", | |
96 | Bool.toString hofo, ",", | |
97 | Int.toString rounds, ",", | |
98 | Int.toString small, ",", | |
99 | Int.toString product, ")#", | |
100 | Int.toString (Counter.next count)], | |
101 | doit = polyvariance (hofo, rounds, small, product), | |
102 | execute = true} | |
103 | val s = String.dropPrefix (s, String.size "polyvariance") | |
104 | in | |
105 | case nums s of | |
106 | SOME [] => mk (true, 2, 30, 300) | |
107 | | SOME [hofo, rounds, small, product] => | |
108 | mk (hofo <> 0, rounds, small, product) | |
109 | | _ => NONE | |
110 | end | |
111 | else NONE | |
112 | end | |
113 | ||
114 | val passGens = | |
115 | polyvariancePassGen :: | |
116 | (List.map([("sxmlShrink", S.shrink), | |
117 | ("implementExceptions", ImplementExceptions.transform), | |
118 | ("implementSuffix", ImplementSuffix.transform)], | |
119 | mkSimplePassGen)) | |
120 | in | |
121 | fun sxmlPassesSetCustom s = | |
122 | Exn.withEscape | |
123 | (fn esc => | |
124 | (let val ss = String.split (s, #":") | |
125 | in | |
126 | sxmlPasses := | |
127 | List.map(ss, fn s => | |
128 | case (List.peekMap (passGens, fn gen => gen s)) of | |
129 | NONE => esc (Result.No s) | |
130 | | SOME pass => pass) | |
131 | ; Result.Yes () | |
132 | end)) | |
133 | end | |
134 | ||
135 | val sxmlPassesString = ref "default" | |
136 | val sxmlPassesGet = fn () => !sxmlPassesString | |
137 | val sxmlPassesSet = fn s => | |
138 | let | |
139 | val _ = sxmlPassesString := s | |
140 | in | |
141 | case s of | |
142 | "default" => (sxmlPasses := sxmlPassesDefault | |
143 | ; Result.Yes ()) | |
144 | | "cpsTransform" => (sxmlPasses := sxmlPassesCpsTransform | |
145 | ; Result.Yes ()) | |
146 | | "minimal" => (sxmlPasses := sxmlPassesMinimal | |
147 | ; Result.Yes ()) | |
148 | | _ => sxmlPassesSetCustom s | |
149 | end | |
150 | val _ = List.push (Control.optimizationPasses, | |
151 | {il = "sxml", get = sxmlPassesGet, set = sxmlPassesSet}) | |
152 | ||
153 | fun pass ({name, doit}, p) = | |
154 | let | |
155 | val _ = | |
156 | let open Control | |
157 | in maybeSaveToFile | |
158 | ({name = name, | |
159 | suffix = "pre.sxml"}, | |
160 | Control.No, p, Control.Layouts Program.layouts) | |
161 | end | |
162 | val p = | |
163 | Control.passTypeCheck | |
164 | {display = Control.Layouts Program.layouts, | |
165 | name = name, | |
166 | stats = Program.layoutStats, | |
167 | style = Control.No, | |
168 | suffix = "post.sxml", | |
169 | thunk = fn () => doit p, | |
170 | typeCheck = typeCheck} | |
171 | in | |
172 | p | |
173 | end | |
174 | fun maybePass ({name, doit, execute}, p) = | |
175 | if List.foldr (!Control.executePasses, execute, fn ((re, new), old) => | |
176 | if Regexp.Compiled.matchesAll (re, name) | |
177 | then new | |
178 | else old) | |
179 | then pass ({name = name, doit = doit}, p) | |
180 | else (Control.messageStr (Control.Pass, name ^ " skipped"); p) | |
181 | fun simplify p = | |
182 | let | |
183 | fun simplify' p = | |
184 | List.fold | |
185 | (!sxmlPasses, p, fn ({name, doit, execute}, p) => | |
186 | maybePass ({name = name, doit = doit, execute = execute}, p)) | |
187 | val p = simplify' p | |
188 | in | |
189 | p | |
190 | end | |
191 | ||
192 | val simplify = fn p => let | |
193 | (* Always want to type check the initial and final XML | |
194 | * programs, even if type checking is turned off, just | |
195 | * to catch bugs. | |
196 | *) | |
197 | val _ = typeCheck p | |
198 | val p' = simplify p | |
199 | val _ = typeCheck p' | |
200 | in | |
201 | p' | |
202 | end | |
203 | end |