001: package gnu.expr;
002:
003: import gnu.mapping.*;
004: import gnu.lists.*;
005: import gnu.kawa.reflect.ClassMemberLocation;
006:
007: /**
008: * Class for the dummy top-level function of a module.
009: */
010:
011: public abstract class ModuleBody extends Procedure0 {
012: public void apply(CallContext ctx) throws Throwable {
013: if (ctx.pc == 0)
014: run(ctx);
015: }
016:
017: protected boolean runDone;
018:
019: public void run(CallContext ctx) throws Throwable {
020: }
021:
022: public void run() {
023: synchronized (this ) {
024: if (runDone)
025: return;
026: runDone = true;
027: }
028: run(VoidConsumer.instance);
029: }
030:
031: public void run(Consumer out) {
032: // This should match the "run" method generated in Compilation.
033: CallContext ctx = CallContext.getInstance();
034: Consumer save = ctx.consumer;
035: ctx.consumer = out;
036: Throwable th;
037: try {
038: run(ctx);
039: th = null;
040: } catch (Throwable ex) {
041: th = ex;
042: }
043: runCleanup(ctx, th, save);
044: }
045:
046: public static void runCleanup(CallContext ctx, Throwable th,
047: Consumer save) {
048: if (th == null) {
049: try {
050: ctx.runUntilDone();
051: } catch (Throwable ex) {
052: th = ex;
053: }
054: }
055: ctx.consumer = save;
056: if (th != null) {
057: if (th instanceof RuntimeException)
058: throw (RuntimeException) th;
059: if (th instanceof Error)
060: throw (Error) th;
061: throw new WrappedException(th);
062: }
063: }
064:
065: public Object apply0() throws Throwable {
066: CallContext ctx = CallContext.getInstance();
067: match0(ctx);
068: return ctx.runUntilValue();
069: }
070:
071: private static boolean mainPrintValues;
072:
073: /** True if runAsMain should print values (in top-level expressions). */
074: public static boolean getMainPrintValues() {
075: return mainPrintValues;
076: }
077:
078: public static void setMainPrintValues(boolean value) {
079: mainPrintValues = value;
080: }
081:
082: /** This is invoked by main when ModuleBody is compiled with --main. */
083: public static void processArgs(String[] args) {
084: int iArg = kawa.repl.processArgs(args, 0, args.length);
085: kawa.repl.setArgs(args, iArg);
086: }
087:
088: /** This is invoked by main when ModuleBody is compiled with --main. */
089: public final void runAsMain() {
090: gnu.text.WriterManager.instance.registerShutdownHook();
091: try {
092: CallContext ctx = CallContext.getInstance();
093: // FIXME - not appropriate for XQuery.
094: ClassMemberLocation.defineAll(this , ctx.getEnvironment());
095: if (getMainPrintValues()) {
096: OutPort out = OutPort.outDefault();
097: ctx.consumer = kawa.Shell.getOutputConsumer(out);
098: run(ctx);
099: ctx.runUntilDone();
100: out.freshLine();
101: } else {
102: run();
103: ctx.runUntilDone();
104: }
105: // Redundant if registerShutdownHook succeeded (e.g on JDK 1.3).
106: gnu.mapping.OutPort.runCleanups();
107: kawa.repl.exitDecrement();
108: } catch (Throwable ex) {
109: ex.printStackTrace();
110: gnu.mapping.OutPort.runCleanups();
111: System.exit(-1);
112: }
113: }
114:
115: /**
116: * A subclass will typically override this like:
117: * switch (method.selector) {
118: * case 3: return function3();
119: * case 5: return function5();
120: * default: super.apply0(method);
121: * }
122: */
123:
124: public Object apply0(ModuleMethod method) throws Throwable {
125: return applyN(method, Values.noArgs);
126: }
127:
128: public Object apply1(ModuleMethod method, Object arg1)
129: throws Throwable {
130: Object[] args = new Object[1];
131: args[0] = arg1;
132: return applyN(method, args);
133: }
134:
135: public Object apply2(ModuleMethod method, Object arg1, Object arg2)
136: throws Throwable {
137: Object[] args = new Object[2];
138: args[0] = arg1;
139: args[1] = arg2;
140: return applyN(method, args);
141: }
142:
143: public Object apply3(ModuleMethod method, Object arg1, Object arg2,
144: Object arg3) throws Throwable {
145: Object[] args = new Object[3];
146: args[0] = arg1;
147: args[1] = arg2;
148: args[2] = arg3;
149: return applyN(method, args);
150: }
151:
152: public Object apply4(ModuleMethod method, Object arg1, Object arg2,
153: Object arg3, Object arg4) throws Throwable {
154: Object[] args = new Object[4];
155: args[0] = arg1;
156: args[1] = arg2;
157: args[2] = arg3;
158: args[3] = arg4;
159: return applyN(method, args);
160: }
161:
162: public Object applyN(ModuleMethod method, Object[] args)
163: throws Throwable {
164: int count = args.length;
165: int num = method.numArgs();
166: if (count >= (num & 0xFFF) && (num < 0 || count <= (num >> 12))) {
167: switch (count) {
168: case 0:
169: return apply0(method);
170: case 1:
171: return apply1(method, args[0]);
172: case 2:
173: return apply2(method, args[0], args[1]);
174: case 3:
175: return apply3(method, args[0], args[1], args[2]);
176: case 4:
177: return apply4(method, args[0], args[1], args[2],
178: args[3]);
179: }
180: }
181: throw new WrongArguments(method, count);
182: }
183:
184: public int match0(ModuleMethod proc, CallContext ctx) {
185: int num = proc.numArgs();
186: int min = num & 0xFFF;
187: if (min > 0)
188: return MethodProc.NO_MATCH_TOO_FEW_ARGS | min;
189: if (num < 0)
190: return matchN(proc, ProcedureN.noArgs, ctx);
191: ctx.count = 0;
192: ctx.where = 0;
193: ctx.next = 0;
194: ctx.proc = proc;
195: return 0;
196: }
197:
198: public int match1(ModuleMethod proc, Object arg1, CallContext ctx) {
199: int num = proc.numArgs();
200: int min = num & 0xFFF;
201: if (min > 1)
202: return MethodProc.NO_MATCH_TOO_FEW_ARGS | min;
203: if (num >= 0) {
204: int max = num >> 12;
205: if (max < 1)
206: return MethodProc.NO_MATCH_TOO_MANY_ARGS | max;
207: ctx.value1 = arg1;
208: ctx.count = 1;
209: ctx.where = CallContext.ARG_IN_VALUE1;
210: ctx.next = 0;
211: ctx.proc = proc;
212: //ctx.proc = this; ctx.pc = proc.selector;
213: return 0;
214: }
215: Object[] args = { arg1 };
216: return matchN(proc, args, ctx);
217: }
218:
219: public int match2(ModuleMethod proc, Object arg1, Object arg2,
220: CallContext ctx) {
221: int num = proc.numArgs();
222: int min = num & 0xFFF;
223: if (min > 2)
224: return MethodProc.NO_MATCH_TOO_FEW_ARGS | min;
225: if (num >= 0) {
226: int max = num >> 12;
227: if (max < 2)
228: return MethodProc.NO_MATCH_TOO_MANY_ARGS | max;
229: ctx.value1 = arg1;
230: ctx.value2 = arg2;
231: ctx.count = 2;
232: ctx.where = CallContext.ARG_IN_VALUE1
233: | (CallContext.ARG_IN_VALUE2 << 4);
234: ctx.next = 0;
235: ctx.proc = proc;
236: return 0;
237: }
238: Object[] args = { arg1, arg2 };
239: return matchN(proc, args, ctx);
240: }
241:
242: public int match3(ModuleMethod proc, Object arg1, Object arg2,
243: Object arg3, CallContext ctx) {
244: int num = proc.numArgs();
245: int min = num & 0xFFF;
246: if (min > 3)
247: return MethodProc.NO_MATCH_TOO_FEW_ARGS | min;
248: if (num >= 0) {
249: int max = num >> 12;
250: if (max < 3)
251: return MethodProc.NO_MATCH_TOO_MANY_ARGS | max;
252: ctx.value1 = arg1;
253: ctx.value2 = arg2;
254: ctx.value3 = arg3;
255: ctx.count = 3;
256: ctx.where = CallContext.ARG_IN_VALUE1
257: | (CallContext.ARG_IN_VALUE2 << 4)
258: | (CallContext.ARG_IN_VALUE3 << 8);
259: ctx.next = 0;
260: ctx.proc = proc;
261: // ctx.proc = this; ctx.pc = proc.selector;
262: return 0;
263: }
264: Object[] args = { arg1, arg2, arg3 };
265: return matchN(proc, args, ctx);
266: }
267:
268: public int match4(ModuleMethod proc, Object arg1, Object arg2,
269: Object arg3, Object arg4, CallContext ctx) {
270: int num = proc.numArgs();
271: int min = num & 0xFFF;
272: if (min > 4)
273: return MethodProc.NO_MATCH_TOO_FEW_ARGS | min;
274: if (num >= 0) {
275: int max = num >> 12;
276: if (max < 4)
277: return MethodProc.NO_MATCH_TOO_MANY_ARGS | max;
278: ctx.value1 = arg1;
279: ctx.value2 = arg2;
280: ctx.value3 = arg3;
281: ctx.value4 = arg4;
282: ctx.count = 4;
283: ctx.where = (CallContext.ARG_IN_VALUE1
284: | (CallContext.ARG_IN_VALUE2 << 4)
285: | (CallContext.ARG_IN_VALUE3 << 8) | (CallContext.ARG_IN_VALUE4 << 12));
286: ctx.next = 0;
287: ctx.proc = proc;
288: //ctx.proc = this; ctx.pc = proc.selector;
289: return 0;
290: }
291: Object[] args = { arg1, arg2, arg3, arg4 };
292: return matchN(proc, args, ctx);
293: }
294:
295: public int matchN(ModuleMethod proc, Object[] args, CallContext ctx) {
296: int num = proc.numArgs();
297: int min = num & 0xFFF;
298: if (args.length < min)
299: return MethodProc.NO_MATCH_TOO_FEW_ARGS | min;
300: if (num >= 0) {
301: switch (args.length) {
302: case 0:
303: return match0(proc, ctx);
304: case 1:
305: return match1(proc, args[0], ctx);
306: case 2:
307: return match2(proc, args[0], args[1], ctx);
308: case 3:
309: return match3(proc, args[0], args[1], args[2], ctx);
310: case 4:
311: return match4(proc, args[0], args[1], args[2], args[3],
312: ctx);
313: default:
314: int max = num >> 12;
315: if (args.length > max)
316: return MethodProc.NO_MATCH_TOO_MANY_ARGS | max;
317: }
318: }
319: ctx.values = args;
320: ctx.count = args.length;
321: ctx.where = 0;
322: ctx.next = 0;
323: ctx.proc = proc;
324: // The following doesn't work if this does not pass contexts
325: //ctx.proc = this; ctx.pc = proc.selector;
326: return 0;
327: }
328: }
|