fluid_let.java 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package kawa.standard;
  2. import kawa.lang.*;
  3. import gnu.mapping.*;
  4. import gnu.expr.*;
  5. import gnu.lists.*;
  6. import gnu.kawa.reflect.StaticFieldLocation;
  7. /**
  8. * The Syntax transformer that re-writes the Scheme "fluid-let" primitive.
  9. * @author Per Bothner
  10. */
  11. public class fluid_let extends Syntax
  12. {
  13. public static final fluid_let fluid_let = new fluid_let();
  14. static { fluid_let.setName("fluid-set"); }
  15. /** True if bindings should be evaluated sequentionally, as in ELisp let*. */
  16. boolean star;
  17. /** Value to use if an initial value is not specified.
  18. * Null means use the existing binding. */
  19. Expression defaultInit;
  20. boolean warnIfUndefined;
  21. public fluid_let(boolean star, boolean warnIfUndefined, Expression defaultInit)
  22. {
  23. this.star = star;
  24. this.defaultInit = defaultInit;
  25. this.warnIfUndefined = warnIfUndefined;
  26. }
  27. public fluid_let()
  28. {
  29. this.star = false;
  30. }
  31. public Expression rewrite (Object obj, Translator tr)
  32. {
  33. if (! (obj instanceof Pair))
  34. return tr.syntaxError ("missing let arguments");
  35. Pair pair = (Pair) obj;
  36. return rewrite(pair.getCar(), pair.getCdr(), tr);
  37. }
  38. public Expression rewrite (Object bindings, Object body, Translator tr)
  39. {
  40. int decl_count = star ? 1 : LList.length (bindings);
  41. FluidLetExp let = new FluidLetExp();
  42. for (int i = 0; i < decl_count; i++)
  43. {
  44. Pair bind_pair = (Pair) bindings;
  45. Object savePos = tr.pushPositionOf(bind_pair);
  46. try
  47. {
  48. Expression value;
  49. Pair binding;
  50. Object name = bind_pair.getCar();
  51. if (name instanceof String || name instanceof Symbol)
  52. {
  53. value = defaultInit;
  54. }
  55. else if (name instanceof Pair
  56. && ((binding = (Pair) name).getCar() instanceof String
  57. || binding.getCar() instanceof Symbol
  58. || binding.getCar() instanceof SyntaxForm))
  59. {
  60. name = binding.getCar();
  61. if (name instanceof SyntaxForm)
  62. name = ((SyntaxForm) name).getDatum();
  63. if (binding.getCdr() == LList.Empty)
  64. value = defaultInit;
  65. else if (! (binding.getCdr() instanceof Pair)
  66. || (binding = (Pair) binding.getCdr()).getCdr() != LList.Empty)
  67. return tr.syntaxError("bad syntax for value of " + name
  68. + " in " + getName());
  69. else
  70. value = tr.rewrite_car(binding, false);
  71. }
  72. else
  73. return tr.syntaxError("invalid " + getName() + " syntax");
  74. Declaration decl = let.addDeclaration(name);
  75. Declaration found = tr.lookup(name, -1);
  76. if (found == null && name instanceof Symbol)
  77. {
  78. Location loc = tr.getLanguage().getLangEnvironment()
  79. .lookup((Symbol) name, null);
  80. if (loc != null)
  81. loc = loc.getBase();
  82. if (loc instanceof StaticFieldLocation)
  83. found = ((StaticFieldLocation) loc).getDeclaration();
  84. }
  85. if (found != null)
  86. {
  87. found.maybeIndirectBinding(tr);
  88. decl.base = found;
  89. found.setFluid(true);
  90. found.setCanWrite(true);
  91. }
  92. else if (! warnIfUndefined)
  93. decl.setFlag(Declaration.IS_DYNAMIC);
  94. decl.setCanWrite(true);
  95. decl.setFluid(true);
  96. decl.setIndirectBinding(true);
  97. if (value == null)
  98. value = new ReferenceExp(name);
  99. decl.setInitValue(value);
  100. decl.noteValueUnknown();
  101. bindings = bind_pair.getCdr();
  102. }
  103. finally
  104. {
  105. tr.popPositionOf(savePos);
  106. }
  107. }
  108. tr.push(let);
  109. let.setBody(star && bindings != LList.Empty ? rewrite (bindings, body, tr)
  110. : tr.rewrite_body(body));
  111. tr.pop(let);
  112. return let;
  113. }
  114. }