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: walker.walk(exp);
14: }
15:
16: protected Expression walkApplyExp(ApplyExp exp) {
17: Expression func = exp.func;
18: if (func instanceof LetExp && !(func instanceof FluidLetExp)) // [APPLY-LET]
19: {
20: // Optimize ((let (...) body) . args) to (let (...) (body . args)).
21: LetExp let = (LetExp) func;
22: Expression body = let.body;
23: let.body = exp;
24: exp.func = body;
25: return let.walk(this );
26: }
27: if (func instanceof BeginExp) // [APPLY-BEGIN]
28: {
29: // Optimize ((begin ... last) . args) to (begin ... (last . args)).
30: BeginExp begin = (BeginExp) func;
31: Expression[] stmts = begin.exps;
32: int last_index = begin.exps.length - 1;
33: exp.func = stmts[last_index];
34: stmts[last_index] = exp;
35: return begin.walk(this);
36: }
37: exp.walkChildren(this);
38: return exp;
39: }
40: }
|