KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > kawa > lang > Macro


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 JavaDoc expander;
11
12   Object JavaDoc 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) // possibly if immediate.
23
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 JavaDoc 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 JavaDoc name, Procedure expander,
51                        Object JavaDoc 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 JavaDoc name, Procedure expander)
60   {
61     Macro mac = new Macro(name, expander);
62     return mac;
63   }
64
65   public static Macro make(Object JavaDoc name, Procedure expander, Object JavaDoc 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   /** Copy constructor. */
80   public Macro (Macro old)
81   {
82     name = old.name;
83     expander = old.expander;
84     hygienic = old.hygienic;
85   }
86
87   public Macro(Object JavaDoc name, Procedure expander)
88   {
89     super(name);
90     this.expander = new QuoteExp(expander);
91   }
92
93   public Macro(Object JavaDoc name)
94   {
95     super(name);
96   }
97
98   /* FIXME redundant */
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 JavaDoc form, Translator tr)
105   {
106     return tr.rewrite(expand(form, tr));
107   }
108
109   public String JavaDoc 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 JavaDoc expand (Object JavaDoc form, Translator tr)
122   {
123     try
124       {
125     Procedure pr;
126     Object JavaDoc 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             /* DEBUGGING:
146             if (exp instanceof LambdaExp)
147               {
148                 System.err.println("expand "+this+" expander:"+exp);
149                 System.err.flush();
150                 OutPort dout = OutPort.errDefault();
151         dout.flush();
152                 ((Expression) exp).print(dout);
153                 dout.println(']');
154         dout.flush();
155              }
156             */

157         pr = (Procedure)
158           ((Expression) exp).eval(tr.getGlobalEnvironment());
159       }
160     Object JavaDoc 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 JavaDoc[] args = new Object JavaDoc[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 JavaDoc 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 JavaDoc 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 JavaDoc 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   /**
217    * @serialData Write the name followed by the expansion procedure,
218    * both using writeObject.
219    */

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 JavaDoc
228   {
229     setName((String JavaDoc) in.readObject());
230     expander = new QuoteExp(in.readObject());
231   }
232 }
233
Popular Tags