123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- package kawa.standard;
- import kawa.lang.*;
- import gnu.mapping.*;
- import gnu.bytecode.ClassType;
- import gnu.bytecode.Method;
- import gnu.expr.*;
- import gnu.lists.*;
- import gnu.kawa.reflect.Invoke;
- /**
- * The Syntax transformer that re-writes the "%define" internal form.
- * This is used to implement define, define-private, and define-constant.
- * Syntax: {@code (%define name code type value)}.
- * The {@code name} is an identifier ({@code String} or
- * {@code Symbol}) or {@code Declaration}.
- * The {@code code} is an integer mask,
- * where 1 means type specified, 2 means a function definition,
- * 4 means private, 8 means constant, 16 means an early constant.,
- * and 32 means a fluid variable (define-variable).
- * As a special case, define-procedure is 1+2+8+16=27
- * The {@code type} is the declarated type or{@code null}.
- * The {@code value} is the initializing value.
- * @author Per Bothner
- */
- public class define extends Syntax
- {
- public static final define defineRaw = new define(SchemeCompilation.lambda);
- Lambda lambda;
- String getName (int options)
- {
- if ((options & 4) != 0)
- return "define-private";
- else if ((options & 8) != 0)
- return "define-constant";
- else if ((options & 32) != 0)
- return "define-variable";
- else
- return "define";
- }
- public define(Lambda lambda)
- {
- this.lambda = lambda;
- }
- public void scanForm (Pair st, ScopeExp defs, Translator tr)
- {
- Pair p1 = (Pair) st.getCdr();
- Pair p2 = (Pair) p1.getCdr();
- Pair p3 = (Pair) p2.getCdr();
- TemplateScope templateScope = null;
- Object name = p1.getCar();
- while (name instanceof SyntaxForm)
- {
- SyntaxForm nameSyntax = (SyntaxForm) name;
- templateScope = nameSyntax.getScope();
- name = nameSyntax.getDatum();
- }
- int options = ((Number) Translator.stripSyntax(p2.getCar())).intValue();
- boolean makePrivate = (options & 4) != 0;
- boolean makeConstant = (options & 8) != 0;
- boolean makeFluid = (options & 32) != 0;
- boolean makeCompoundProcedure = options == 27;
- name = tr.namespaceResolve(name);
- if (! (name instanceof Symbol))
- {
- tr.error('e', "'"+name+"' is not a valid identifier");
- name = null;
- }
- Object savePos = tr.pushPositionOf(p1);
- Declaration decl = tr.define(name, templateScope, defs);
- tr.popPositionOf(savePos);
- name = decl.getSymbol();
- if (makePrivate)
- {
- if (defs instanceof ModuleExp && defs.getFlag(ModuleExp.INTERACTIVE))
- tr.error('w', "'define-private' should not be used in interactive mode");
- else {
- decl.setFlag(Declaration.PRIVATE_SPECIFIED);
- decl.setPrivate(true);
- }
- }
- if (makeConstant)
- decl.setFlag(Declaration.IS_CONSTANT);
- if ((options & 16) != 0)
- decl.setFlag(Declaration.EARLY_INIT);
- decl.setFlag(Declaration.IS_SINGLE_VALUE);
- Expression value;
- if ((options & 2) != 0 && ! makeCompoundProcedure)
- {
- LambdaExp lexp = new LambdaExp();
- lexp.setSymbol(name);
- if (Compilation.inlineOk)
- {
- decl.setProcedureDecl(true);
- decl.setType(Compilation.typeProcedure);
- lexp.nameDecl = decl;
- }
- Translator.setLine(lexp, p1);
- value = lexp;
- }
- else
- value = null;
- SetExp sexp = new SetExp(decl, value);
- if (defs instanceof ModuleExp && ! makePrivate && ! makeConstant
- && (! Compilation.inlineOk || tr.sharedModuleDefs()))
- decl.setCanWrite(true);
- if (makeFluid) {
- decl.setSimple(false);
- decl.setPrivate(true);
- decl.setFlag(Declaration.IS_DYNAMIC);
- decl.setCanRead(true);
- decl.setCanWrite(true);
- decl.setIndirectBinding(true);
- sexp.setSetIfUnbound(true);
- }
- if ((options & 1) != 0)
- {
- decl.setTypeExp(new LangExp(p3));
- decl.setFlag(Declaration.TYPE_SPECIFIED);
- }
- st = Translator.makePair(st, this,
- Translator.makePair(p1, sexp, p2));
- Translator.setLine(decl, p1);
- tr.pushForm(st);
- }
- public Expression rewriteForm (Pair form, Translator tr)
- {
- Pair p1 = (Pair) form.getCdr();
- Pair p2 = (Pair) p1.getCdr();
- Pair p3 = (Pair) p2.getCdr();
- Pair p4 = (Pair) p3.getCdr();
- Object name = p1.getCar();
- int options = ((Number) Translator.stripSyntax(p2.getCar())).intValue();
- boolean makePrivate = (options & 4) != 0;
- boolean makeFluid = (options & 32) != 0;
- boolean makeCompoundProcedure = options == 27;
- if (! (name instanceof SetExp))
- return tr.syntaxError(getName(options) + " is only allowed in a <body>");
- SetExp sexp = (SetExp) name;
- Declaration decl = sexp.getBinding();
- if (decl.getFlag(Declaration.TYPE_SPECIFIED))
- {
- Expression texp = decl.getTypeExp();
- if (texp instanceof LangExp)
- {
- Pair typeSpecPair = (Pair) ((LangExp) texp).getLangValue();
- decl.setType(tr.exp2Type(typeSpecPair));
- }
- }
- if (makeFluid
- && Translator.stripSyntax(p4.getCar())==Special.undefined)
- return QuoteExp.voidExp;
- BeginExp bexp2 = null;
- boolean unknownValue;
- if ((options & 2) != 0 && ! makeCompoundProcedure)
- {
- LambdaExp lexp = (LambdaExp) sexp.getNewValue();
- Object formals = p4.getCar();
- Object body = p4.getCdr();
- lambda.rewrite(lexp, formals, body, tr, null);
- unknownValue = ! Compilation.inlineOk;
- }
- else
- {
- unknownValue = decl.context instanceof ModuleExp && ! makePrivate && decl.getCanWrite();
- if (makeCompoundProcedure) {
- tr.letStart();
- ClassType classGenericProc = ClassType.make("gnu.expr.GenericProc");
- Declaration gproc =
- tr.letVariable(null,
- classGenericProc,
- new ApplyExp(Invoke.make,
- new Expression[] {
- QuoteExp.getInstance(classGenericProc),
- QuoteExp.getInstance(decl.getName()) }));
- gproc.setFlag(Declaration.ALLOCATE_ON_STACK);
- tr.letEnter();
- BeginExp bexp1 = new BeginExp(); // early-init-code goes here
- Method addMethod = classGenericProc.getDeclaredMethod("add", 1);
- Method setPropMethod =
- classGenericProc.getDeclaredMethod("setProperty", 2);
- for (;;) {
- Keyword key = null;
- Object car = Translator.stripSyntax(p4.getCar());
- if (car instanceof Keyword) {
- key = (Keyword) car;
- Object cdr = p4.getCdr();
- if (! (cdr instanceof Pair)
- || Translator.safeCar(cdr) instanceof Keyword) {
- tr.error('e', "missing value following keyword");
- break;
- }
- p4 = (Pair) cdr;
- }
- Expression arg = tr.rewrite_car(p4, false);
- if (key != null) {
- if (bexp2 == null)
- bexp2 = new BeginExp();
- bexp2.add(new ApplyExp(setPropMethod,
- new Expression[] {
- new ReferenceExp(decl),
- QuoteExp.getInstance(key),
- arg }));
- } else {
- Declaration gdecl = arg instanceof LambdaExp ? gproc : decl;
- Expression addCall =
- new ApplyExp(addMethod,
- new Expression[] {
- new ReferenceExp(gdecl),
- arg });
- if (arg instanceof LambdaExp) {
- LambdaExp larg = (LambdaExp) arg;
- String lname = larg.getName();
- String dname = decl.getName();
- if (lname == null || lname.equals(dname)) {
- // Needed so PrimProcedure.getMethodFor
- // can find this method.
- if (decl.isPublic())
- larg.setFlag(LambdaExp.PUBLIC_METHOD);
- // FIXME Maybe set larg.nameDecl to decl?
- // At least if we have a single LambdaExp?
- // FIXME set the name?
- // This "enables" ModuleMethod#resolveParameterTypes
- // to search for the most specific method, which
- // is expensive - and pull in Compilation and
- // related classes.
- // if (lname == null)
- // larg.setName(dname);
- }
- bexp1.add(addCall);
- } else {
- if (bexp2 == null)
- bexp2 = new BeginExp();
- bexp2.add(addCall);
- }
- }
- Object cdr = p4.getCdr();
- if (! (cdr instanceof Pair)) {
- if (cdr != LList.Empty)
- tr.error('e', "not a proper list");
- break;
- }
- p4 = (Pair) cdr;
- }
- ReferenceExp gref = new ReferenceExp(gproc);
- gref.setFlag(ReferenceExp.ALLOCATE_ON_STACK_LAST);
- bexp1.add(gref);
- sexp.setNewValue(tr.letDone(BeginExp.canonicalize(bexp1)));
- } else
- sexp.setNewValue(tr.rewrite_car(p4, false));
- }
- if (unknownValue)
- decl.noteValueUnknown();
- else
- decl.noteValueFromSet(sexp);
- sexp.setDefining (true);
- if (makePrivate && ! (decl.getContext() instanceof ModuleExp))
- tr.error('w', "define-private not at top level");
- if (bexp2 != null)
- return new BeginExp(sexp, bexp2);
- return sexp;
- }
- }
|