199 (*the normalizer works yoyo-like: top-down, bottom-up, top-down, ...*) |
199 (*the normalizer works yoyo-like: top-down, bottom-up, top-down, ...*) |
200 |
200 |
201 fun normalize trace stat get_rules pre_ast = |
201 fun normalize trace stat get_rules pre_ast = |
202 let |
202 let |
203 val passes = ref 0; |
203 val passes = ref 0; |
204 val lookups = ref 0; |
|
205 val failed_matches = ref 0; |
204 val failed_matches = ref 0; |
206 val changes = ref 0; |
205 val changes = ref 0; |
207 |
206 |
208 fun subst _ (ast as Constant _) = ast |
207 fun subst _ (ast as Constant _) = ast |
209 | subst env (Variable x) = the (Symtab.lookup (env, x)) |
208 | subst env (Variable x) = the (Symtab.lookup (env, x)) |
210 | subst env (Appl asts) = Appl (map (subst env) asts); |
209 | subst env (Appl asts) = Appl (map (subst env) asts); |
211 |
210 |
212 fun try_rules ast ((lhs, rhs) :: pats) = |
211 fun try_rules ((lhs, rhs) :: pats) ast = |
213 (case match ast lhs of |
212 (case match ast lhs of |
214 Some (env, args) => |
213 Some (env, args) => |
215 (inc changes; Some (mk_appl (subst env rhs) args)) |
214 (inc changes; Some (mk_appl (subst env rhs) args)) |
216 | None => (inc failed_matches; try_rules ast pats)) |
215 | None => (inc failed_matches; try_rules pats ast)) |
217 | try_rules _ [] = None; |
216 | try_rules [] _ = None; |
218 |
217 val try_headless_rules = try_rules (get_rules ""); |
219 fun try ast a = (inc lookups; try_rules ast (get_rules a)); |
218 |
|
219 fun try ast a = |
|
220 (case try_rules (get_rules a) ast of |
|
221 None => try_headless_rules ast |
|
222 | some => some); |
220 |
223 |
221 fun rewrite (ast as Constant a) = try ast a |
224 fun rewrite (ast as Constant a) = try ast a |
222 | rewrite (ast as Variable a) = try ast a |
225 | rewrite (ast as Variable a) = try ast a |
223 | rewrite (ast as Appl (Constant a :: _)) = try ast a |
226 | rewrite (ast as Appl (Constant a :: _)) = try ast a |
224 | rewrite (ast as Appl (Variable a :: _)) = try ast a |
227 | rewrite (ast as Appl (Variable a :: _)) = try ast a |
225 | rewrite ast = try ast ""; |
228 | rewrite ast = try_headless_rules ast; |
226 |
229 |
227 fun rewrote old_ast new_ast = |
230 fun rewrote old_ast new_ast = |
228 if trace then |
231 if trace then |
229 writeln ("rewrote: " ^ str_of_ast old_ast ^ " -> " ^ str_of_ast new_ast) |
232 writeln ("rewrote: " ^ str_of_ast old_ast ^ " -> " ^ str_of_ast new_ast) |
230 else (); |
233 else (); |
260 val post_ast = normal pre_ast; |
263 val post_ast = normal pre_ast; |
261 in |
264 in |
262 if trace orelse stat then |
265 if trace orelse stat then |
263 writeln ("post: " ^ str_of_ast post_ast ^ "\nnormalize: " ^ |
266 writeln ("post: " ^ str_of_ast post_ast ^ "\nnormalize: " ^ |
264 string_of_int (! passes) ^ " passes, " ^ |
267 string_of_int (! passes) ^ " passes, " ^ |
265 string_of_int (! lookups) ^ " lookups, " ^ |
|
266 string_of_int (! changes) ^ " changes, " ^ |
268 string_of_int (! changes) ^ " changes, " ^ |
267 string_of_int (! failed_matches) ^ " matches failed") |
269 string_of_int (! failed_matches) ^ " matches failed") |
268 else (); |
270 else (); |
269 post_ast |
271 post_ast |
270 end; |
272 end; |