set_b.java 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package kawa.standard;
  2. import kawa.lang.*;
  3. import gnu.mapping.*;
  4. import gnu.expr.*;
  5. import gnu.lists.*;
  6. /**
  7. * The Syntax transformer that re-writes the Scheme "set!" primitive.
  8. * @author Per Bothner
  9. */
  10. public class set_b extends Syntax
  11. {
  12. public static final set_b set = new set_b();
  13. static { set.setName("set!"); }
  14. public Expression rewriteForm (Pair form, Translator tr)
  15. {
  16. Object o1 = form.getCdr();
  17. SyntaxForm syntax = null;
  18. while (o1 instanceof SyntaxForm)
  19. {
  20. syntax = (SyntaxForm) o1;
  21. o1 = syntax.getDatum();
  22. }
  23. if (! (o1 instanceof Pair))
  24. return tr.syntaxError ("missing name");
  25. Pair p1 = (Pair) o1;
  26. Expression name = tr.rewrite_car(p1, syntax);
  27. Object o2 = p1.getCdr();
  28. while (o2 instanceof SyntaxForm)
  29. {
  30. syntax = (SyntaxForm) o2;
  31. o2 = syntax.getDatum();
  32. }
  33. Pair p2;
  34. if (! (o2 instanceof Pair)
  35. || (p2 = (Pair) o2).getCdr() != LList.Empty)
  36. return tr.syntaxError ("missing or extra arguments to set!");
  37. Expression value = tr.rewrite_car(p2, syntax);
  38. if (name instanceof ApplyExp)
  39. {
  40. // rewrite (set! (proc . args) rhs) => ((setter proc) args ... rhs)
  41. ApplyExp aexp = (ApplyExp) name;
  42. Expression[] args = aexp.getArgs();
  43. int nargs = args.length;
  44. int skip = 0;
  45. Expression func = aexp.getFunction();
  46. if (args.length > 0 && func instanceof ReferenceExp
  47. && ((ReferenceExp) func).getBinding() == SchemeCompilation.applyFieldDecl)
  48. {
  49. skip = 1;
  50. nargs--;
  51. func = args[0];
  52. }
  53. Expression[] setterArgs = { func };
  54. Expression[] xargs = new Expression[nargs+1];
  55. System.arraycopy(args, skip, xargs, 0, nargs);
  56. xargs[nargs] = value;
  57. Declaration setter = gnu.kawa.functions.CompilationHelpers.setterDecl;
  58. return new ApplyExp(new ApplyExp(new ReferenceExp(setter),
  59. setterArgs), xargs);
  60. }
  61. else if (! (name instanceof ReferenceExp))
  62. return tr.syntaxError ("first set! argument is not a variable name");
  63. ReferenceExp ref = (ReferenceExp) name;
  64. Declaration decl = ref.getBinding();
  65. SetExp sexp = new SetExp (ref.getSymbol(), value);
  66. // A kludge to treat interactive set! as similar to (re-)definition.
  67. if (decl != null
  68. && decl.getContext() instanceof ModuleExp
  69. && tr.currentScope() instanceof ModuleExp
  70. && decl.getContext().getFlag(ModuleExp.INTERACTIVE)
  71. && decl.getContext() != tr.getModule()) {
  72. decl = tr.define(decl.getSymbol(), syntax, tr.getModule());
  73. ref.setBinding(decl);
  74. sexp.setBinding(decl);
  75. sexp.setDefining(true);
  76. decl.noteValueUnknown();
  77. }
  78. sexp.setContextDecl(ref.contextDecl());
  79. if (decl != null)
  80. {
  81. decl.setCanWrite(true);
  82. sexp.setBinding(decl);
  83. decl = Declaration.followAliases(decl);
  84. if (decl != null)
  85. decl.noteValueFromSet(sexp);
  86. if (decl.getFlag(Declaration.IS_CONSTANT))
  87. return tr.syntaxError ("constant variable "+decl.getName()+" is set!");
  88. else if (decl.context != tr.mainLambda
  89. && decl.context instanceof ModuleExp
  90. && ! decl.getFlag(Declaration.IS_DYNAMIC)
  91. && ! decl.context.getFlag(ModuleExp.IMMEDIATE))
  92. // Should be an error, but for now make it a warning
  93. tr.error('w', decl, "imported variable ", " is set!");
  94. }
  95. return sexp;
  96. }
  97. }