01: package gnu.expr;
02:
03: /** Re-arranges ApplyExp where the function is a LetExp or BeginExp.
04: Optimizes ((let (...) body) . args) to (let (...) (body . args)).
05: Optimizes ((begin ... last) . args) to (begin ... (last . args)).
06: This helps optimize Scheme "named let" (and some other forms)
07: by making it more likely the application will be to a known procedure.
08: This optimization has to be done after Declarations are bound. */
09:
10: public class PushApply extends ExpWalker {
11: public static void pushApply(Expression exp) {
12: PushApply walker = new PushApply();
13: exp.walk(walker);
14: //or: walter.walkExpression(exp);
15: }
16:
17: protected Expression walkApplyExp(ApplyExp exp) {
18: Expression func = exp.func;
19: if (func instanceof LetExp && !(func instanceof FluidLetExp)) // [APPLY-LET]
20: {
21: // Optimize ((let (...) body) . args) to (let (...) (body . args)).
22: LetExp let = (LetExp) func;
23: Expression body = let.body;
24: let.body = exp;
25: exp.func = body;
26: return let.walk(this );
27: }
28: if (func instanceof BeginExp) // [APPLY-BEGIN]
29: {
30: // Optimize ((begin ... last) . args) to (begin ... (last . args)).
31: BeginExp begin = (BeginExp) func;
32: Expression[] stmts = begin.exps;
33: int last_index = begin.exps.length - 1;
34: exp.func = stmts[last_index];
35: stmts[last_index] = exp;
36: return begin.walk(this);
37: }
38: exp.walkChildren(this);
39: return exp;
40: }
41: }
|