1 package kawa.lang; 2 import gnu.expr.*; 3 import gnu.mapping.*; 4 import gnu.lists.*; 5 import java.io.*; 6 import gnu.text.Printable; 7 8 public class Macro extends Syntax implements Printable, Externalizable 9 { 10 public Object expander; 11 12 Object instance; 13 14 private boolean hygienic = true; 15 16 private ScopeExp capturedScope; 17 18 public ScopeExp getCapturedScope () 19 { 20 if (capturedScope == null) 21 { 22 if (instance instanceof ModuleExp) capturedScope = (ModuleExp) instance; 24 else if (instance != null) 25 capturedScope = ModuleInfo.findFromInstance(instance).getModuleExp(); 26 } 27 return capturedScope; 28 } 29 30 public void setCapturedScope (ScopeExp scope) 31 { 32 capturedScope = scope; 33 } 34 35 public static Macro make (Declaration decl) 36 { 37 Macro mac = new Macro(decl.getSymbol()); 38 decl.setSyntax(); 39 mac.capturedScope = decl.context; 40 return mac; 41 } 42 43 public static Macro makeNonHygienic (Object name, Procedure expander) 44 { 45 Macro mac = new Macro(name, expander); 46 mac.hygienic = false; 47 return mac; 48 } 49 50 public static Macro makeNonHygienic (Object name, Procedure expander, 51 Object instance) 52 { 53 Macro mac = new Macro(name, expander); 54 mac.hygienic = false; 55 mac.instance = instance; 56 return mac; 57 } 58 59 public static Macro make (Object name, Procedure expander) 60 { 61 Macro mac = new Macro(name, expander); 62 return mac; 63 } 64 65 public static Macro make(Object name, Procedure expander, Object instance) 66 { 67 Macro mac = new Macro(name, expander); 68 mac.instance = instance; 69 return mac; 70 } 71 72 public final boolean isHygienic() { return hygienic; } 73 public final void setHygienic (boolean hygienic) {this.hygienic = hygienic;} 74 75 public Macro () 76 { 77 } 78 79 80 public Macro (Macro old) 81 { 82 name = old.name; 83 expander = old.expander; 84 hygienic = old.hygienic; 85 } 86 87 public Macro(Object name, Procedure expander) 88 { 89 super(name); 90 this.expander = new QuoteExp(expander); 91 } 92 93 public Macro(Object name) 94 { 95 super(name); 96 } 97 98 99 public gnu.expr.Expression rewriteForm (Pair form, Translator tr) 100 { 101 return tr.rewrite(expand(form, tr)); 102 } 103 104 public gnu.expr.Expression rewriteForm (Object form, Translator tr) 105 { 106 return tr.rewrite(expand(form, tr)); 107 } 108 109 public String toString() 110 { 111 return "#<macro "+getName()+'>'; 112 } 113 114 public void print (Consumer out) 115 { 116 out.write("#<macro "); 117 out.write(getName()); 118 out.write ('>'); 119 } 120 121 public Object expand (Object form, Translator tr) 122 { 123 try 124 { 125 Procedure pr; 126 Object exp = expander; 127 if (exp instanceof Procedure && ! (exp instanceof Expression)) 128 pr = (Procedure) exp; 129 else 130 { 131 if (! (exp instanceof Expression)) 132 { 133 Macro savedMacro = tr.currentMacroDefinition; 134 tr.currentMacroDefinition = this; 135 try 136 { 137 exp = tr.rewrite(exp); 138 expander = exp; 139 } 140 finally 141 { 142 tr.currentMacroDefinition = savedMacro; 143 } 144 } 145 157 pr = (Procedure) 158 ((Expression) exp).eval(tr.getGlobalEnvironment()); 159 } 160 Object result; 161 if (! hygienic) 162 { 163 form = Quote.quote(form, tr); 164 int nargs = Translator.listLength(form); 165 if (nargs <= 0) 166 return tr.syntaxError("invalid macro argument list to "+this); 167 Object [] args = new Object [nargs-1]; 168 for (int i = 0; i < nargs; i++) 169 { 170 Pair pair = (Pair) form; 171 if (i > 0) 172 args[i-1] = pair.car; 173 form = pair.cdr; 174 } 175 result = pr.applyN(args); 176 } 177 else 178 result = pr.apply1(form); 179 if (form instanceof PairWithPosition && result instanceof Pair 180 && ! (result instanceof PairWithPosition)) 181 { 182 Pair p = (Pair) result; 183 result = new PairWithPosition((PairWithPosition) form, 184 p.car, p.cdr); 185 } 186 return result; 187 } 188 catch (Throwable ex) 189 { 190 ex.printStackTrace(); 191 return tr.syntaxError("evaluating syntax transformer '" 192 + getName() + "' threw " + ex); 193 } 194 } 195 196 public void scanForm (Pair st, ScopeExp defs, Translator tr) 197 { 198 String save_filename = tr.getFileName(); 199 int save_line = tr.getLineNumber(); 200 int save_column = tr.getColumnNumber(); 201 Syntax saveSyntax = tr.currentSyntax; 202 try 203 { 204 tr.setLine(st); 205 tr.currentSyntax = this; 206 Object x = expand(st, tr); 207 tr.scanForm(x, defs); 208 } 209 finally 210 { 211 tr.setLine(save_filename, save_line, save_column); 212 tr.currentSyntax = saveSyntax; 213 } 214 } 215 216 220 public void writeExternal(ObjectOutput out) throws IOException 221 { 222 out.writeObject(getName()); 223 out.writeObject(((QuoteExp) expander).getValue()); 224 } 225 226 public void readExternal(ObjectInput in) 227 throws IOException, ClassNotFoundException 228 { 229 setName((String ) in.readObject()); 230 expander = new QuoteExp(in.readObject()); 231 } 232 } 233 | Popular Tags |