While the rewrite class construct provides a very general abstraction
for rewriting, in general its full power is unneeded. It is often
convenient to be able to perform rewriting on a term without having
to make a new name for a class just for the occasion, especially if member
functions and member data are unneeded. To accommodate these situations,
the rewrite
statement is provided
to perform a set rewriting transformations on a term without having
to define a temporary rewrite class. It is simply syntactic sugar
for the more general rewrite class and rewrite
rules specifications.
For example, a simplify routine for type Exp
defined above can be
specified as follows:
Exp simplify (Exp e) { // transformations on e before rewrite (e) type (Exp) { ADD (INT a, INT b): INT(a+b) | SUB (INT a, INT b): INT(a-b) | MUL (INT a, INT b): INT(a*b) | ... } // transformations on e after return e; }
The rewrite
normally performs the replacement in-place.
An applicative version of the same can be written as follows8:
Exp simplify (Exp e) { rewrite (e) => e type (Exp) { ADD (INT a, INT b): INT(a+b) | SUB (INT a, INT b): INT(a+b) | MUL (INT a, INT b): INT(a*b) | ... } return e; }
The syntax of the rewrite statement is as follows. The traversal list of the set of rewrite rule is listed next to the keyword type.