KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > Expression


1 package gnu.expr;
2 import gnu.bytecode.Type;
3 import gnu.mapping.*;
4 import gnu.text.Printable;
5 import gnu.text.SourceLocator;
6 import gnu.lists.Consumer;
7 import java.io.PrintWriter JavaDoc;
8
9 /**
10  * Abstract class for syntactic forms that evaluate to a value.
11  * Scheme S-expressions get re-written to these before evaluation.
12  * @author Per Bothner
13  */

14
15 public abstract class Expression extends Procedure0
16   implements Printable, SourceLocator
17 {
18   public final Object JavaDoc eval (CallContext ctx) throws Throwable JavaDoc
19   {
20     int start = ctx.startFromContext();
21     try
22       {
23     match0(ctx);
24     return ctx.getFromContext(start);
25       }
26     catch (Throwable JavaDoc ex)
27       {
28     ctx.cleanupFromContext(start);
29     throw ex;
30       }
31   }
32
33   public final Object JavaDoc eval (Environment env) throws Throwable JavaDoc
34   {
35     CallContext ctx = CallContext.getInstance();
36     Environment save = ctx.getEnvironmentRaw();
37     if (env != save)
38       ctx.setEnvironmentRaw(env);
39     try
40       {
41         return eval(ctx);
42       }
43     finally
44       {
45         if (env != save)
46           ctx.setEnvironmentRaw(save);
47       }
48   }
49
50   protected abstract boolean mustCompile ();
51
52   public final int match0 (CallContext ctx)
53   {
54     ctx.proc = this;
55     ctx.pc = 0;
56     return 0;
57   }
58
59   public final Object JavaDoc apply0 () throws Throwable JavaDoc
60   {
61     CallContext ctx = CallContext.getInstance();
62     check0(ctx);
63     return ctx.runUntilValue();
64   }
65
66   /** Evaluate the expression.
67    * This is named apply rather than eval so it is compatible with the
68    * full-tail-call calling convention, and we can stash an Expression in
69    * CallContext's proc field. FIXME - are we making use of this?
70    */

71   public void apply (CallContext ctx) throws Throwable JavaDoc
72   {
73     throw new RuntimeException JavaDoc ("internal error - "
74                     + getClass() + ".eval called");
75   }
76
77   public final void print (Consumer out)
78   {
79     if (out instanceof OutPort)
80       print((OutPort) out);
81     else if (out instanceof PrintWriter JavaDoc)
82       {
83     OutPort port = new OutPort((PrintWriter JavaDoc) out);
84     print(port);
85     port.close();
86       }
87     else
88       {
89     CharArrayOutPort port = new CharArrayOutPort();
90     print(port);
91     port.close();
92         port.writeTo(out);
93       }
94   }
95
96   public abstract void print (OutPort ps);
97
98   /**
99    * Print line and column number if specified.
100    * This is a helper routineintended for use by print(OutPort).
101    */

102   public void printLineColumn(OutPort out)
103   {
104     int line = getLineNumber();
105     if (line > 0)
106       {
107     out.print("line:");
108     out.print(line);
109     int column = getColumnNumber();
110     if (column > 0)
111       {
112         out.print(':');
113         out.print(column);
114       }
115     out.writeSpaceFill();
116       }
117   }
118
119   public abstract void compile (Compilation comp, Target target);
120
121   /** Same as compile, but emit line number beforehard. */
122   public final void compileWithPosition(Compilation comp, Target target)
123   {
124     int line = getLineNumber ();
125     if (line > 0)
126       {
127         comp.getCode().putLineNumber(getFileName(), line);
128         compileNotePosition(comp, target, this);
129       }
130     else
131       compile(comp, target);
132   }
133
134   /** Same as 2-argument compileWithPosition,
135    * but use some other Expression's line number. */

136   public final void compileWithPosition(Compilation comp, Target target,
137                     Expression position)
138   {
139     int line = position.getLineNumber ();
140     if (line > 0)
141       {
142         comp.getCode().putLineNumber(position.getFileName(), line);
143         compileNotePosition(comp, target, position);
144       }
145     else
146       compile(comp, target);
147   }
148
149   /** Compile, but take note of line number. */
150   public final void compileNotePosition(Compilation comp, Target target,
151                     Expression position)
152   {
153     String JavaDoc saveFilename = comp.getFileName();
154     int saveLine = comp.getLineNumber();
155     int saveColumn = comp.getColumnNumber();
156     comp.setLine(position);
157     compile(comp, target);
158     // This might logically belong in a `finally' clause.
159
// It is intentionally not so, so if there is an internal error causing
160
// an exception, we get the line number where the exception was thrown.
161
comp.setLine(saveFilename, saveLine, saveColumn);
162   }
163
164   public final void compile (Compilation comp, Type type)
165   {
166     // Should we use Target.pushValue instead? FIXME.
167
compile (comp, StackTarget.getInstance(type));
168   }
169
170   /** Compile an expression with checking suitable for a known Declaration.
171    * Leaves the result on the stack (i.e. does not assign to the lhs).
172    * It does coerce the value to a suitable type for the lhs, and
173    * throw a hopefully-informative WrongType exception on failure.
174    */

175   public final void compile (Compilation comp, Declaration lhs)
176   {
177     compile (comp,
178              CheckedTarget.getInstance(lhs.getType(),
179                                        lhs.getName(),
180                                        WrongType.ARG_VARNAME));
181   }
182
183   /** Compile all but the first sub-"statement".
184    * A kludge used for constructor methods, since if the first "statement"
185    * is a super-constructor we need to inject initializer expressions. */

186   public static void compileButFirst (Expression exp, Compilation comp)
187   {
188     if (exp instanceof BeginExp)
189       {
190         BeginExp bexp = (BeginExp) exp;
191     int n = bexp.length;
192         if (n == 0)
193           return;
194         Expression[] exps = bexp.exps;
195         compileButFirst(exps[0], comp);
196     for (int i = 1; i < n; i++)
197       exps[i].compileWithPosition(comp, Target.Ignore);
198       }
199   }
200
201   protected Expression walk (ExpWalker walker)
202   {
203     return walker.walkExpression(this);
204   }
205
206   protected void walkChildren (ExpWalker walker) { }
207
208   /** Apply inlining transformations on a given ApplyExp.
209    * Assumes the ApplyExp's function is the this expression,
210    * or can be optimized to this expression.
211    * @param exp an application whose function expression can be simplified
212    * to this expression.
213    * @param walker the context for the current inlining pass
214    * @param decl if non-null, a Declaration bound to this expression
215    * @return an Expression equivalent to te passed-in exp.
216    */

217   public Expression inline (ApplyExp exp, InlineCalls walker, Declaration decl)
218   {
219     return exp;
220   }
221
222   String JavaDoc filename;
223   int position;
224
225   public static final Expression[] noExpressions = new Expression[0];
226
227   /** Helper method to create a `while' statement. */
228   public static Expression makeWhile(Object JavaDoc cond, Object JavaDoc body, Compilation parser)
229   {
230     Expression[] inits = new Expression[1];
231     LetExp let = new LetExp(inits);
232     String JavaDoc fname = "%do%loop";
233     Declaration fdecl = let.addDeclaration(fname);
234     Expression recurse = new ApplyExp(new ReferenceExp(fdecl), noExpressions);
235     LambdaExp lexp = new LambdaExp();
236     parser.push(lexp);
237     lexp.body = new IfExp(parser.parse(cond),
238               new BeginExp(parser.parse(body), recurse),
239               QuoteExp.voidExp);
240     lexp.setName(fname);
241     parser.pop(lexp);
242     inits[0] = lexp;
243     fdecl.noteValue(lexp);
244     let.setBody(new ApplyExp(new ReferenceExp(fdecl), noExpressions));
245     return let;
246   }
247   
248   /** Copies the current location. */
249   public final void setLocation (SourceLocator location)
250   {
251     this.filename = location.getFileName();
252     setLine(location.getLineNumber(), location.getColumnNumber());
253   }
254
255   public final Expression setLine(Expression old)
256   {
257     setLocation(old);
258     return this;
259   }
260
261   public final void setFile (String JavaDoc filename)
262   {
263     this.filename = filename;
264   }
265
266   public final void setLine (int lineno, int colno)
267   {
268     if (lineno < 0)
269       lineno = 0;
270     if (colno < 0)
271       colno = 0;
272     position = (lineno << 12) + colno;
273   }
274
275   public final void setLine (int lineno)
276   {
277     setLine (lineno, 0);
278   }
279
280   public final String JavaDoc getFileName ()
281   {
282     return filename;
283   }
284
285   /** Set line number from current position in <code>Compilation</code>. */
286   public void setLine (Compilation comp)
287   {
288     int line = comp.getLineNumber();
289     if (line > 0)
290       {
291     setFile(comp.getFileName());
292     setLine(line, comp.getColumnNumber());
293       }
294   }
295
296   public String JavaDoc getPublicId ()
297   {
298     return null;
299   }
300
301   public String JavaDoc getSystemId ()
302   {
303     return filename;
304   }
305
306   /** Get the line number of (the start of) this Expression.
307     * The "first" line is line 1; unknown is -1. */

308   public final int getLineNumber()
309   {
310     int line = position >> 12;
311     return line == 0 ? -1 : line;
312   }
313
314   public final int getColumnNumber()
315   {
316     int column = position & ((1 << 12) - 1);
317     return column == 0 ? -1 : column;
318   }
319
320   public boolean isStableSourceLocation() { return true; }
321
322   /** Return the Type used to represent the values of this Expression. */
323   public Type getType()
324   {
325     return Type.pointer_type;
326   }
327
328   /** Return value if it is constant, or null if non-constant or unknown. */
329   public Object JavaDoc valueIfConstant ()
330   {
331     return null;
332   }
333
334   protected int flags;
335   protected static final int NEXT_AVAIL_FLAG = 1;
336
337   public void setFlag (boolean setting, int flag)
338   {
339     if (setting) flags |= flag;
340     else flags &= ~flag;
341   }
342
343   public void setFlag (int flag)
344   {
345     flags |= flag;
346   }
347
348   public int getFlags()
349   {
350     return flags;
351   }
352
353   public boolean getFlag (int flag)
354   {
355     return (flags & flag) != 0;
356   }
357
358   /** True if evaluating may have side-effects. */
359   public boolean side_effects () { return true; }
360
361   public String JavaDoc toString ()
362   {
363     String JavaDoc tname = getClass().getName();
364     if (tname.startsWith("gnu.expr."))
365       tname = tname.substring(9);
366     return tname+"@"+Integer.toHexString(hashCode());
367   }
368 }
369
Popular Tags