constant_fold.java 1.8 KB

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