01: package kawa.standard;
02:
03: import kawa.lang.*;
04: import gnu.mapping.*;
05: import gnu.expr.*;
06:
07: /** Implements the "constant-fold" transformer. */
08:
09: public class constant_fold extends Syntax {
10: public static final constant_fold constant_fold = new constant_fold();
11: static {
12: constant_fold.setName("constant-fold");
13: }
14:
15: static Object checkConstant(Expression exp, Translator tr) {
16: if (exp instanceof QuoteExp)
17: return ((QuoteExp) exp).getValue();
18: if (exp instanceof ReferenceExp) {
19: ReferenceExp rexp = (ReferenceExp) exp;
20: Declaration decl = rexp.getBinding();
21: if (decl == null || decl.getFlag(Declaration.IS_UNKNOWN))
22: return Environment.user().get(rexp.getName(), null);
23: else
24: return Declaration.followAliases(decl)
25: .getConstantValue();
26: }
27: return null;
28: }
29:
30: public Expression rewrite(Object obj, Translator tr) {
31: Expression exp = tr.rewrite(obj);
32: if (!(exp instanceof ApplyExp))
33: return exp;
34: ApplyExp aexp = (ApplyExp) exp;
35: Object func = checkConstant(aexp.getFunction(), tr);
36: if (!(func instanceof Procedure))
37: return exp;
38:
39: // Not quite the same - checkConstant also looks up name in Environment,
40: // which seems a bit too dangerous for inlineIfConstant. FIXME.
41: // return aexp.inlineIfConstant((Procedure) func, tr.getMessages());
42:
43: Expression[] args = aexp.getArgs();
44: int i = args.length;
45: Object[] vals = new Object[i];
46: while (--i >= 0) {
47: Object val = checkConstant(args[i], tr);
48: if (val == null)
49: return exp;
50: vals[i] = val;
51: }
52: try {
53: return new QuoteExp(((Procedure) func).applyN(vals));
54: } catch (Throwable ex) {
55: exp = tr.syntaxError("caught exception in constant-fold:");
56: tr.syntaxError(ex.toString());
57: return exp;
58: }
59: }
60: }
|