KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mapping > CallContext


1 // Copyright (C) 2002, 2003, 2004 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.mapping;
5 import gnu.math.*;
6 import gnu.lists.*;
7
8 /** A procedure activation stack (when compiled with explicit stacks). */
9
10 public class CallContext // implements Runnable
11
// extends ValueStack ??? FIXME
12
{
13   /* #ifdef JAVA2 */
14   static ThreadLocal JavaDoc currentContext = new ThreadLocal JavaDoc();
15   /* #else */
16   // static java.util.Hashtable threadMap = new java.util.Hashtable(50);
17
/* #endif */
18   Thread JavaDoc currentThread;
19
20   Environment curEnvironment;
21
22   public final Environment getEnvironmentRaw() { return curEnvironment; }
23   public final void setEnvironmentRaw(Environment env) { curEnvironment = env;}
24
25   public final Environment getEnvironment()
26   {
27     if (curEnvironment == null)
28       {
29     Environment env
30           = Environment.make(currentThread.getName(), Environment.global);
31         env.flags |= Environment.THREAD_SAFE;
32         curEnvironment = env;
33       }
34     return curEnvironment;
35   }
36
37   public static void setInstance(CallContext ctx)
38   {
39     Thread JavaDoc thread = Thread.currentThread();
40     ctx.currentThread = thread;
41     /* #ifdef JAVA2 */
42     currentContext.set(ctx);
43     /* #else */
44     // if (thread instanceof Future)
45
// ((Future) thread).closure.context = ctx;
46
// else
47
// threadMap.put(thread, ctx);
48
/* #endif */
49   }
50
51   /** Get but don't create a CallContext for the current thread. */
52   public static CallContext getOnlyInstance()
53   {
54     /* #ifdef JAVA2 */
55     return (CallContext) currentContext.get();
56     /* #else */
57     // Thread thread = Thread.currentThread();
58
// if (thread instanceof Future)
59
// return ((Future) thread).getCallContext();
60
// return (CallContext) threadMap.get(thread);
61
/* #endif */
62   }
63
64   /** Get or create a CallContext for the current thread. */
65   public static CallContext getInstance()
66   {
67     CallContext ctx = getOnlyInstance();
68     if (ctx == null)
69       {
70     ctx = new CallContext();
71     setInstance(ctx);
72       }
73     return ctx;
74   }
75
76   public Procedure proc;
77
78   /** The program location in the current procedure.
79    * This a selector that only has meaning to the proc's Procedure.*/

80   public int pc;
81
82   /* CPS:
83   CallFrame frame;
84   */

85
86   /** Default place for function results.
87    * In the future, function arguments will also use vstack. */

88   public ValueStack vstack = new ValueStack(); // ?? super
89
/** Function results are written to this Consumer.
90    * This may point to vstack - or some other Consumer. */

91   public Consumer consumer = vstack;
92
93   /** Used for passing parameters. (Will be replaced by vstack.) */
94   public Object JavaDoc value1;
95   public Object JavaDoc value2;
96   public Object JavaDoc value3;
97   public Object JavaDoc value4;
98   public Object JavaDoc[] values;
99   public int ivalue1;
100   public int ivalue2;
101
102   /** Number of actual arguments. */
103   public int count;
104   
105   /** Index of next argument.
106    * This is used by methods like getNextArg, used by callees. */

107   public int next;
108
109   /** Encoding of where the arguments are.
110    * Each argument uses 4 bits.
111    * Arguments beyond 8 are implicitly ARG_IN_VALUES_ARRAY.
112    */

113   public int where;
114   public final static int ARG_IN_VALUES_ARRAY = 0;
115   public final static int ARG_IN_VALUE1 = 1;
116   public final static int ARG_IN_VALUE2 = 2;
117   public final static int ARG_IN_VALUE3 = 3;
118   public final static int ARG_IN_VALUE4 = 4;
119   public final static int ARG_IN_IVALUE1 = 5;
120   public final static int ARG_IN_IVALUE2 = 6;
121
122   Object JavaDoc getArgAsObject(int i)
123   {
124     if (i < 8)
125       {
126         switch ((this.where >> (4 * i)) & 15)
127           {
128           case ARG_IN_VALUE1: return value1;
129           case ARG_IN_VALUE2: return value2;
130           case ARG_IN_VALUE3: return value3;
131           case ARG_IN_VALUE4: return value4;
132           case ARG_IN_IVALUE1: return IntNum.make(ivalue1);
133           case ARG_IN_IVALUE2: return IntNum.make(ivalue2);
134           }
135       }
136     return values[i];
137   }
138
139   /** Get the next incoming argument.
140    * Throw WrongArguments if there are no more arguments.
141    * FIXME: This and following methods don't really fit until the
142    * current match/apply-based API, at least as currently implemented.
143    * We probably need to pass in (or make this a method of) the Procedure.
144    */

145   public Object JavaDoc getNextArg()
146   {
147     if (next >= count)
148       throw new WrongArguments(null, count);
149     return getArgAsObject(next++);
150   }
151
152   public int getNextIntArg()
153   {
154     if (next >= count)
155       throw new WrongArguments(null, count);
156     Object JavaDoc arg = getArgAsObject(next++);
157     return ((Number JavaDoc) arg).intValue();
158   }
159
160   /** Get the next incoming argument.
161    * Return defaultValue if there are no more arguments.
162    */

163   public Object JavaDoc getNextArg(Object JavaDoc defaultValue)
164   {
165     if (next >= count)
166       return defaultValue;
167     return getArgAsObject(next++);
168   }
169
170   public int getNextIntArg(int defaultValue)
171   {
172     if (next >= count)
173       return defaultValue;
174     return ((Number JavaDoc) getArgAsObject(next++)).intValue();
175   }
176
177   /** Get remaining arguments as an array. */
178   public final Object JavaDoc[] getRestArgsArray (int next)
179   {
180     Object JavaDoc[] args = new Object JavaDoc[count - next];
181     int i = 0;
182     while (next < count)
183       {
184     args[i++] = getArgAsObject(next++);
185       }
186     return args;
187   }
188
189   /** Get remaining arguments as a list.
190    * Used for Scheme and Lisp rest args. */

191   public final LList getRestArgsList (int next)
192   {
193     LList nil = LList.Empty;
194     LList list = nil;
195     Pair last = null;
196     while (next < count)
197       {
198     Pair pair = new Pair(getArgAsObject(next++), nil);
199     if (last == null)
200       list = pair;
201     else
202       last.cdr = pair;
203     last = pair;
204       }
205     return list;
206   }
207
208   /** Note that we are done with the input arguments.
209    * Throw WrongArguments if there are unprocessed arguments.
210    */

211   public void lastArg()
212   {
213     if (next < count)
214       throw new WrongArguments(null, count);
215     values = null;
216   }
217
218   public Object JavaDoc[] getArgs()
219   {
220     if (where == 0)
221       return values;
222     else
223       {
224     int n = count;
225     next = 0;
226     Object JavaDoc[] args = new Object JavaDoc[n];
227     for (int i = 0; i < n; i++)
228       args[i] = getNextArg();
229     return args;
230       }
231   }
232
233   public void runUntilDone() throws Throwable JavaDoc
234   {
235     for (;;)
236       {
237     Procedure proc = this.proc;
238     if (proc == null)
239       {
240         /* CPS:
241         CallFrame fr = frame;
242         if (fr == null)
243           break;
244         proc = fr.proc;
245         frame = fr.previous;
246         if (proc == null)
247         */

248           break;
249       }
250     this.proc = null;
251     proc.apply(this);
252       }
253   }
254
255   /** Setup routine before calling a method that takes a CallContext.
256    * The compiler emits a call to this before a call to a method that takes
257    * a CallContext, when it wants the function result as an Object.
258    * It pushes the CallContest state so it can uses the vstack for a
259    * temporary, After the method, getFromContext extract the method's result
260    * from the vstack and restores the state.
261    */

262   public final int startFromContext ()
263   {
264     ValueStack vst = vstack;
265     int oindex = vst.find(consumer);
266     vst.ensureSpace(3);
267     int gapStart = vst.gapStart;
268     vst.data[gapStart++] = TreeList.INT_FOLLOWS;
269     vst.setIntN(gapStart, oindex);
270     gapStart += 2;
271     consumer = vst;
272     vst.gapStart = gapStart;
273     return gapStart;
274   }
275
276   /** Routine to extract result and restore state after startFromContext.
277    */

278   public final Object JavaDoc getFromContext (int oldIndex) throws Throwable JavaDoc
279   {
280     runUntilDone();
281     ValueStack vst = vstack;
282     Object JavaDoc result = Values.make(vst, oldIndex, vst.gapStart);
283     cleanupFromContext(oldIndex);
284     return result;
285   }
286
287   /** Cleanup-only part of getFromContext.
288    * This can be in an exception handler as an alternative
289    * to getFromContext, which is called in the non-exception case.
290    * (Alternatively, the compiler could call cleanupFromContext
291    * from a finally clause but that is less efficient, partly
292    * because the JVM stack must be empty before a finally subroutine.)
293    */

294   public final void cleanupFromContext (int oldIndex) throws Throwable JavaDoc
295   {
296     ValueStack vst = vstack;
297     char[] data = vst.data;
298     int oindex = (data[oldIndex-2] << 16) | (data[oldIndex -1] & 0xFFFF);
299     consumer = (Consumer) vst.objects[oindex];
300     vst.objects[oindex] = null;
301     vst.oindex = oindex;
302     vst.gapStart = oldIndex - 3;
303   }
304
305   /** Run until no more continuations, returning final result. */
306   public final Object JavaDoc runUntilValue() throws Throwable JavaDoc
307   {
308     Consumer consumerSave = consumer;
309     ValueStack vst = vstack;
310     consumer = vst;
311     int dindexSave = vst.gapStart;
312     int oindexSave = vst.oindex;
313     try
314       {
315     runUntilDone();
316     return Values.make(vst, dindexSave, vst.gapStart);
317       }
318     finally
319       {
320     consumer = consumerSave;
321     vst.gapStart = dindexSave;
322     vst.oindex = oindexSave;
323       }
324   }
325
326   /** Run until no more continuations, sending result to a COnsumer. */
327   public final void runUntilValue(Consumer out) throws Throwable JavaDoc
328   {
329     Consumer consumerSave = consumer;
330     consumer = out;
331     try
332       {
333     runUntilDone();
334       }
335     finally
336       {
337     consumer = consumerSave;
338       }
339   }
340
341   /** Write values (of function result) to current consumer. */
342   public void writeValue(Object JavaDoc value)
343   {
344     Values.writeValues(value, consumer);
345   }
346
347   protected String JavaDoc baseUri;
348   protected static String JavaDoc baseUriDefault;
349
350   public static String JavaDoc getBaseUriDefault ()
351   {
352     String JavaDoc uri = baseUriDefault;
353     if (uri == null)
354       {
355         /* #ifdef use:java.net.URI */
356         uri = new java.io.File JavaDoc("").toURI().toString();
357         /* #else */
358     // uri = System.getProperty("user.dir");
359
// if (uri == null)
360
// return null;
361
// char sep = java.io.File.separatorChar;
362
// /* Note this does not encode illegal characters using '%'. */
363
// if (sep != '/')
364
// uri = uri.replace(sep, '/');
365
// uri = ((uri.charAt(0) == '/' ? "file:" : "file:/")
366
// + uri + '/');
367
/* #endif */
368     baseUriDefault = uri;
369       }
370     return uri;
371   }
372
373   public String JavaDoc getBaseUriRaw ()
374   {
375     return baseUri;
376   }
377
378   /* Get the current "base URI", which defaults to the current directory.
379    * However, it may get reset to the "current document". */

380   public String JavaDoc getBaseUri ()
381   {
382     String JavaDoc uri = baseUri;
383     if (uri == null)
384       baseUri = uri = getBaseUriDefault();
385     return uri;
386   }
387
388   /** Set the current "base URI". */
389   public void setBaseUri (String JavaDoc baseUri)
390   {
391     this.baseUri = baseUri;
392   }
393
394   /** A stack of currently re-bound fluids variables.
395    * There is one for each active fluids-let or parmaterize variable. */

396   Location[] pushedFluids;
397   /** The number of active elements of the pushedFluids array. */
398   int pushedFluidsCount;
399
400   public final void pushFluid (Location loc)
401   {
402     Location[] fluids = pushedFluids;
403     int count = pushedFluidsCount;
404     if (fluids == null)
405       {
406         pushedFluids = fluids = new Location[10];
407       }
408     else if (count == fluids.length)
409       {
410         Location[] newFluids = new Location[2 * count];
411         System.arraycopy(fluids, 0, newFluids, 0, count);
412         pushedFluids = fluids = newFluids;
413       }
414     fluids[count] = loc;
415     pushedFluidsCount = count + 1;
416   }
417
418   public final void popFluid ()
419   {
420     pushedFluids[--pushedFluidsCount] = null;
421   }
422
423   /** Current stack of evaluation frames for interpreter. */
424   public Object JavaDoc[][] evalFrames;
425 }
426
427 /* CPS:
428 class CallFrame
429 {
430   Procedure proc;
431   CallFrame previous;
432   int saveVstackLen;
433
434   // Should probably be in sub-classes of ClassFrame:
435   Object[] values;
436 }
437 */

438
Popular Tags