123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- package kawa.standard;
- import kawa.lang.*;
- import gnu.mapping.*;
- import gnu.expr.*;
- /** Implements the "constant-fold" transformer. */
- public class constant_fold extends Syntax
- {
- public static final constant_fold constant_fold = new constant_fold();
- static { constant_fold.setName("constant-fold"); }
- static Object checkConstant(Expression exp, Translator tr)
- {
- if (exp instanceof QuoteExp)
- return ((QuoteExp) exp).getValue();
- if (exp instanceof ReferenceExp)
- {
- ReferenceExp rexp = (ReferenceExp) exp;
- Declaration decl = rexp.getBinding();
- if (decl == null || decl.getFlag(Declaration.IS_UNKNOWN))
- return Environment.user().get(rexp.getName(), null);
- else
- return Declaration.followAliases(decl).getConstantValue();
- }
- return null;
- }
- public Expression rewrite (Object obj, Translator tr)
- {
- Expression exp = tr.rewrite(obj);
- if (! (exp instanceof ApplyExp))
- return exp;
- ApplyExp aexp = (ApplyExp) exp;
- Object func = checkConstant(aexp.getFunction(), tr);
- if (! (func instanceof Procedure))
- return exp;
- // Not quite the same - checkConstant also looks up name in Environment,
- // which seems a bit too dangerous for inlineIfConstant. FIXME.
- // return aexp.inlineIfConstant((Procedure) func, tr.getMessages());
- Expression[] args = aexp.getArgs();
- int i = args.length;
- Object[] vals = new Object[i];
- while (--i >= 0)
- {
- Object val = checkConstant(args[i], tr);
- if (val == null)
- return exp;
- vals[i] = val;
- }
- try
- {
- return new QuoteExp(((Procedure) func).applyN(vals));
- }
- catch (Error ex)
- {
- throw ex;
- }
- catch (Throwable ex)
- {
- String msg = "caught exception in constant-fold: "+ex;
- tr.getMessages().error('e', msg, ex);
- return new ErrorExp(msg);
- }
- }
- }
|