1 ///////////////////////////////////////////////////////////////////////////////
3 // This file implements the rewriting partial evaluator/supercompiler.
4 // This is used to optimize Prop's rewriting systems.
6 ///////////////////////////////////////////////////////////////////////////////
15 ///////////////////////////////////////////////////////////////////////////////
19 ///////////////////////////////////////////////////////////////////////////////
20 typedef RewriteMix::Result Result;
21 type sharing Bool = bool;
23 ///////////////////////////////////////////////////////////////////////////////
25 // The constructors and destructors
27 ///////////////////////////////////////////////////////////////////////////////
28 RewriteMix::RewriteMix() { reduction_limit = 10; }
29 RewriteMix::~RewriteMix() {}
31 ///////////////////////////////////////////////////////////////////////////////
33 // Method to optimize a set of rewrite rules
35 ///////////////////////////////////////////////////////////////////////////////
36 MatchRules RewriteMix::optimize_rewrite (Id id, MatchRules rules)
37 { if (options.optimize_rewrite)
38 { msg ("%Lpartial evaluating rewrite class %s\n", id);
40 msg ("%Lfinished partial evaluating rewrite class %s\n", id);
45 ///////////////////////////////////////////////////////////////////////////////
47 // Method to partially evaluate a set of rules
49 ///////////////////////////////////////////////////////////////////////////////
50 MatchRules RewriteMix::mix (MatchRules rules)
52 for_each (MatchRule, rule, rules)
54 { MATCHrule(_,_,_,_,act as #[MARKEDdecl(l,REPLACEMENTdecl(rhs,mode))]):
56 { debug_msg("PE [partial evaluating %r]\n", rule);
57 Exp new_rhs = subst(rhs,0);
58 new_rhs = simplify(new_rhs,IDexp(#"(redex)"));
60 Exp reduced_rhs = normalize(new_rhs,rules,reduced);
62 { rewrite (reduced_rhs) type (Exp, Exps)
63 { IDexp("(redex)"): IDexp(#"redex")
65 msg("%!optimizing rhs of rule %r --> %e\n",
66 rule->loc(),rule,reduced_rhs);
77 ///////////////////////////////////////////////////////////////////////////////
79 // Method to normalizes an expression with respect to a set
82 ///////////////////////////////////////////////////////////////////////////////
83 Exp RewriteMix::normalize (Exp exp, MatchRules rules, Bool& reduced)
86 int limit = reduction_limit;
90 { APPexp(_,TUPLEexp es):
91 { for(Exps exps = es; exps; exps=exps->#2)
92 { Exp ne = normalize(exps->#1,rules,reduced);
93 if (ne != exps->#1) { exps->#1 = ne; changed = true; }
96 | APPexp(_,RECORDexp es):
97 { for(LabExps exps = es; exps; exps=exps->#2)
98 { Exp ne = normalize(exps->#1.exp,rules,reduced);
99 if (ne != exps->#1.exp)
100 { exps->#1.exp = ne; changed = true; }
104 { Exp ne = normalize(e,rules,reduced);
105 if (ne != e) { e = ne; changed = true; }
109 Exp replacement = NOexp;
110 Result r = reduce(redex, rules, replacement);
115 if (changed) reduced = true;
116 } while (changed && --limit >= 0);
117 debug_msg("PE [%e normalizes to %e]\n",exp,redex);
121 ///////////////////////////////////////////////////////////////////////////////
123 // Method to match an expression against a set of rules.
125 ///////////////////////////////////////////////////////////////////////////////
126 Result RewriteMix::reduce (Exp redex, MatchRules rules, Exp& replacement)
128 for_each (MatchRule, rule, rules)
130 { MATCHrule(_,pat,guard,_,action):
131 { Result r = pmatch(pat,redex);
133 { debug_msg("PE [%e is unknown at %r]\n",redex,rule);
136 if (r == FAILURE) goto try_next;
138 { Exp guard_exp = subst(guard,0);
139 match (simplify(guard_exp))
140 { LITERALexp(BOOLlit true): { r = SUCCESS; }
141 | LITERALexp(BOOLlit false): { goto try_next; }
143 { debug_msg("PE [%e fails guard at %r]\n",redex,rule);
151 { #[d : Decl]: { decl = d; }
153 { debug_msg("PE [%e has unknown action at %r]\n",redex,rule);
160 { REPLACEMENTdecl(exp2,_): { rhs = exp2; goto found; }
161 | MARKEDdecl(_,d): { decl = d; }
163 { debug_msg("PE [%e has unknown action at %r]\n",redex,rule);
170 replacement = simplify(rhs,redex);
171 debug_msg("PE [%e => %e via %r]\n",redex,replacement,rule);
177 debug_msg("PE [%e fails all rules]\n",redex);
181 ///////////////////////////////////////////////////////////////////////////////
183 // Class to simplify an expression
185 ///////////////////////////////////////////////////////////////////////////////
186 rewrite class RedexSimplifier (Exp, Exps, Cons, Literal)
190 RedexSimplifier(Exp r)
192 TRUE(LITERALexp(BOOLlit(true))),
193 FALSE(LITERALexp(BOOLlit(false))) {}
196 ///////////////////////////////////////////////////////////////////////////////
200 ///////////////////////////////////////////////////////////////////////////////
201 datatype law TRUE = LITERALexp(BOOLlit true)
202 | FALSE = LITERALexp(BOOLlit false)
203 | AND(a,b) = BINOPexp("&&",a,b)
204 | OR(a,b) = BINOPexp("||",a,b)
205 | NOT a = PREFIXexp("!",a)
208 rewrite RedexSimplifier
210 | DOTexp(TUPLEexp es, id): component_exp(es,id)
211 | DOTexp(RECORDexp les, id): component_exp(les,id)
212 | SELECTORexp(APPexp(IDexp id,e),ONEcons { name ...},_) | name == id: e
213 | EQexp(_,a,b) | equal(a,b): TRUE
214 | IDexp "redex": current_redex
217 | AND(FALSE,X): FALSE
218 | AND(X,FALSE): FALSE
228 ///////////////////////////////////////////////////////////////////////////////
230 // Method to simplify an expression
232 ///////////////////////////////////////////////////////////////////////////////
233 Exp RewriteMix::simplify (Exp exp, Exp redex)
234 { RedexSimplifier S(redex);
235 debug_msg("PE [simplifying %e [redex = %e] => ", exp, redex);
237 debug_msg("%e]\n", exp);
241 ///////////////////////////////////////////////////////////////////////////////
243 // This is the main method for matching an expression against a pattern.
244 // If sucessful, the bindings for the pattern variables are returned
245 // in environment. Matching can have one of 3 different results:
246 // (1) SUCCESS, in which case the match is successful,
247 // (2) FAILURE, in which case the match is not successful, or
248 // (3) UNKNOWN, if the result cannot be determined statically.
250 ///////////////////////////////////////////////////////////////////////////////
251 Result RewriteMix::pmatch (Pat pat, Exp exp)
253 // Perform bindings and some simple simplifications.
255 { TYPEDpat(p, _): { pat = p; }
256 | MARKEDpat(_, p): { pat = p; }
257 | ASpat(id,p,ty,e): { pat = p; }
258 | WILDpat _: { return SUCCESS; }
259 | IDpat(id, ty, e): { return SUCCESS; }
262 // Match the expression against the pattern.
263 match (pat) and (exp)
265 LITERALpat a, LITERALexp b:
266 { return literal_equal(a,b) ? SUCCESS : FAILURE; }
267 | TUPLEpat ps, TUPLEexp es: { return pmatch(ps,es); }
268 | EXTUPLEpat ps, EXTUPLEexp es: { return pmatch(ps,es); }
269 | RECORDpat (lps, _), RECORDexp les: { return pmatch(lps,les); }
270 //| LISTpat { head, tail ... }, LISTexp (_,_,heade,taile):
271 // { return pmatch(head,tail,heade,taile,E,visible,plr); }
272 | CONSpat ONEcons { name ... }, IDexp id:
273 { return name == id ? SUCCESS : FAILURE; }
274 | APPpat(CONSpat ONEcons { name ... }, p), APPexp(IDexp id,e)
275 | find_cons(id) != NOcons:
276 { if (name != id) return FAILURE;
277 else return pmatch(p,e);
279 | APPpat(CONSpat _,_), IDexp id | find_cons(id) != NOcons:
281 | CONSpat _, APPexp(IDexp id,_) | find_cons(id) != NOcons:
283 | _: { return UNKNOWN; }
287 ///////////////////////////////////////////////////////////////////////////////
289 // Method to match an expression list against a pattern list.
291 ///////////////////////////////////////////////////////////////////////////////
292 Result RewriteMix::pmatch (Pats pats, Exps exps)
293 { match while (pats) and (exps)
294 { #[a ... b], #[c ... d]:
295 { Result r = pmatch(a,c);
296 if (r != SUCCESS) return r;
303 ///////////////////////////////////////////////////////////////////////////////
305 // Method to match a labeled expression list against a labeled pattern list.
307 ///////////////////////////////////////////////////////////////////////////////
308 Result RewriteMix::pmatch (LabPats pats, LabExps exps)
309 { for_each (LabPat, p, pats)
310 { for_each (LabExp, e, exps)
311 { if (p.label == e.label)
312 { Result r = pmatch(p.pat,e.exp);
313 if (r != SUCCESS) return r;