123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- package kawa.standard;
- import kawa.lang.*;
- import gnu.mapping.*;
- import gnu.expr.*;
- import gnu.lists.*;
- /**
- * The Syntax transformer that re-writes the Scheme "set!" primitive.
- * @author Per Bothner
- */
- public class set_b extends Syntax
- {
- public static final set_b set = new set_b();
- static { set.setName("set!"); }
- public Expression rewriteForm (Pair form, Translator tr)
- {
- Object o1 = form.getCdr();
- SyntaxForm syntax = null;
- while (o1 instanceof SyntaxForm)
- {
- syntax = (SyntaxForm) o1;
- o1 = syntax.getDatum();
- }
- if (! (o1 instanceof Pair))
- return tr.syntaxError ("missing name");
- Pair p1 = (Pair) o1;
- Expression name = tr.rewrite_car(p1, syntax);
- Object o2 = p1.getCdr();
- while (o2 instanceof SyntaxForm)
- {
- syntax = (SyntaxForm) o2;
- o2 = syntax.getDatum();
- }
- Pair p2;
- if (! (o2 instanceof Pair)
- || (p2 = (Pair) o2).getCdr() != LList.Empty)
- return tr.syntaxError ("missing or extra arguments to set!");
- Expression value = tr.rewrite_car(p2, syntax);
- if (name instanceof ApplyExp)
- {
- // rewrite (set! (proc . args) rhs) => ((setter proc) args ... rhs)
- ApplyExp aexp = (ApplyExp) name;
- Expression[] args = aexp.getArgs();
- int nargs = args.length;
- int skip = 0;
- Expression func = aexp.getFunction();
- if (args.length > 0 && func instanceof ReferenceExp
- && ((ReferenceExp) func).getBinding() == SchemeCompilation.applyFieldDecl)
- {
- skip = 1;
- nargs--;
- func = args[0];
- }
- Expression[] setterArgs = { func };
- Expression[] xargs = new Expression[nargs+1];
- System.arraycopy(args, skip, xargs, 0, nargs);
- xargs[nargs] = value;
- Declaration setter = gnu.kawa.functions.CompilationHelpers.setterDecl;
- return new ApplyExp(new ApplyExp(new ReferenceExp(setter),
- setterArgs), xargs);
- }
- else if (! (name instanceof ReferenceExp))
- return tr.syntaxError ("first set! argument is not a variable name");
- ReferenceExp ref = (ReferenceExp) name;
- Declaration decl = ref.getBinding();
- SetExp sexp = new SetExp (ref.getSymbol(), value);
- // A kludge to treat interactive set! as similar to (re-)definition.
- if (decl != null
- && decl.getContext() instanceof ModuleExp
- && tr.currentScope() instanceof ModuleExp
- && decl.getContext().getFlag(ModuleExp.INTERACTIVE)
- && decl.getContext() != tr.getModule()) {
- decl = tr.define(decl.getSymbol(), syntax, tr.getModule());
- ref.setBinding(decl);
- sexp.setBinding(decl);
- sexp.setDefining(true);
- decl.noteValueUnknown();
- }
- sexp.setContextDecl(ref.contextDecl());
- if (decl != null)
- {
- decl.setCanWrite(true);
- sexp.setBinding(decl);
- decl = Declaration.followAliases(decl);
- if (decl != null)
- decl.noteValueFromSet(sexp);
- if (decl.getFlag(Declaration.IS_CONSTANT))
- return tr.syntaxError ("constant variable "+decl.getName()+" is set!");
- else if (decl.context != tr.mainLambda
- && decl.context instanceof ModuleExp
- && ! decl.getFlag(Declaration.IS_DYNAMIC)
- && ! decl.context.getFlag(ModuleExp.IMMEDIATE))
- // Should be an error, but for now make it a warning
- tr.error('w', decl, "imported variable ", " is set!");
- }
- return sexp;
- }
- }
|