001: // Copyright (C) 2005 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ../../COPYING.
003:
004: package kawa.standard;
005:
006: import kawa.lang.*;
007: import gnu.expr.*;
008: import gnu.bytecode.ClassType;
009: import gnu.mapping.*;
010: import gnu.lists.*;
011:
012: public class define_syntax extends Syntax {
013: public static final define_syntax define_macro = new define_syntax(
014: "%define-macro", false);
015:
016: public static final define_syntax define_syntax = new define_syntax(
017: "%define-syntax", true);
018:
019: public define_syntax() {
020: this .hygienic = true;
021: }
022:
023: public define_syntax(Object name, boolean hygienic) {
024: super (name);
025: this .hygienic = hygienic;
026: }
027:
028: static ClassType typeMacro = ClassType.make("kawa.lang.Macro");
029: static PrimProcedure makeHygienic = new PrimProcedure(typeMacro
030: .getDeclaredMethod("make", 3));
031: static PrimProcedure makeNonHygienic = new PrimProcedure(typeMacro
032: .getDeclaredMethod("makeNonHygienic", 3));
033: static PrimProcedure setCapturedScope = new PrimProcedure(typeMacro
034: .getDeclaredMethod("setCapturedScope", 1));
035:
036: boolean hygienic;
037:
038: public Expression rewriteForm(Pair form, Translator tr) {
039: return tr.syntaxError("define-syntax not in a body");
040: }
041:
042: public void scanForm(Pair st, ScopeExp defs, Translator tr) {
043: SyntaxForm syntax = null;
044: Object st_cdr = st.cdr;
045: while (st_cdr instanceof SyntaxForm) {
046: syntax = (SyntaxForm) st_cdr;
047: st_cdr = syntax.form;
048: }
049: Object p = st_cdr;
050: Object name;
051: if (p instanceof Pair) {
052: Pair pp = (Pair) p;
053: name = pp.car;
054: p = pp.cdr;
055: } else
056: name = null;
057: SyntaxForm nameSyntax = syntax;
058: while (name instanceof SyntaxForm) {
059: nameSyntax = (SyntaxForm) name;
060: name = nameSyntax.form;
061: }
062: name = tr.namespaceResolve(name);
063: if (!(name instanceof String || name instanceof Symbol)) {
064: tr.formStack.addElement(tr
065: .syntaxError("missing macro name for "
066: + Translator.safeCar(st)));
067: return;
068: }
069: if (p == null || Translator.safeCdr(p) != LList.Empty) {
070: tr.formStack.addElement(tr
071: .syntaxError("invalid syntax for " + getName()));
072: return;
073: }
074:
075: Declaration decl = tr.define(name, nameSyntax, defs);
076: decl.setType(typeMacro);
077: tr.push(decl);
078:
079: Macro savedMacro = tr.currentMacroDefinition;
080: Macro macro = Macro.make(decl);
081: macro.setHygienic(hygienic);
082: tr.currentMacroDefinition = macro;
083: Expression rule = tr.rewrite_car((Pair) p, syntax);
084: tr.currentMacroDefinition = savedMacro;
085: macro.expander = rule;
086:
087: if (rule instanceof LambdaExp)
088: ((LambdaExp) rule).setFlag(LambdaExp.NO_FIELD);
089: Expression args[] = new Expression[3];
090: args[0] = new QuoteExp(name);
091: args[1] = rule;
092: args[2] = ThisExp.makeGivingContext(defs);
093: rule = new ApplyExp(hygienic ? makeHygienic : makeNonHygienic,
094: args);
095: decl.noteValue(rule);
096: decl.setProcedureDecl(true);
097:
098: if (decl.context instanceof ModuleExp) {
099: SetExp result = new SetExp(decl, rule);
100: result.setDefining(true);
101: if (tr.getLanguage().hasSeparateFunctionNamespace())
102: result.setFuncDef(true);
103:
104: tr.formStack.addElement(result);
105:
106: if (tr.immediate) {
107: args = new Expression[2];
108: args[0] = new ReferenceExp(decl);
109: args[1] = new QuoteExp(defs);
110: tr.formStack.addElement(new ApplyExp(setCapturedScope,
111: args));
112: }
113: }
114: }
115: }
|