KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > ModuleMethod


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

4 package gnu.expr;
5 import gnu.mapping.*;
6 import java.lang.reflect.*;
7
8 /** Call a specified method in in a ModuleBody.
9  * We use an extra level of indirection, but we save by having
10  * to create fewer classes than in the one-class-per-procedure
11  * scheme, without having to use (slow) reflection.
12  */

13
14 public class ModuleMethod extends MethodProc
15 {
16   public ModuleBody module;
17   public final int selector;
18   protected int numArgs;
19
20   public ModuleMethod(ModuleBody module, int selector,
21                       Object JavaDoc name, int numArgs)
22   {
23     this.module = module;
24     this.selector = selector;
25     this.numArgs = numArgs;
26     if (name != null)
27       setSymbol(name);
28   }
29
30   public ModuleMethod (ModuleBody module, int selector,
31                Object JavaDoc name, int numArgs, Object JavaDoc argTypes)
32   {
33     this.module = module;
34     this.selector = selector;
35     this.numArgs = numArgs;
36     if (name != null)
37       setSymbol(name);
38     this.argTypes = argTypes;
39   }
40
41   /** Figure out parameter types.
42    * Uses reflection to get method parameter types.
43    * INCOMPLETE - does not handle procedures with optional or rest args. */

44   protected void resolveParameterTypes()
45   {
46     Method method = null;
47     try
48       {
49     Class JavaDoc moduleClass = module.getClass();
50     Method[] methods = moduleClass.getDeclaredMethods();
51     String JavaDoc mangledName = Compilation.mangleNameIfNeeded(getName());
52     for (int i = methods.length; --i >= 0; )
53       {
54         if (methods[i].getName().equals(mangledName))
55           {
56         if (method != null)
57           {
58             method = null;
59             break;
60           }
61         method = methods[i];
62           }
63       }
64     if (method != null)
65       {
66         Language lang = Language.getDefaultLanguage();
67         Class JavaDoc[] parameterClasses = method.getParameterTypes();
68         int numParamTypes = parameterClasses.length;
69         gnu.bytecode.Type[] atypes = new gnu.bytecode.Type[numParamTypes];
70         for (int i = numParamTypes; --i >= 0; )
71           {
72         atypes[i] = lang.getTypeFor(parameterClasses[i]);
73           }
74         this.argTypes = atypes;
75       }
76       }
77     catch (Throwable JavaDoc ex)
78       {
79       }
80     if (argTypes == null)
81       super.resolveParameterTypes();
82   }
83
84   public int numArgs() { return numArgs; }
85
86   public int match0 (CallContext ctx)
87   {
88     ctx.count = 0;
89     ctx.where = 0;
90     return module.match0(this, ctx);
91   }
92
93   public int match1 (Object JavaDoc arg1, CallContext ctx)
94   {
95     ctx.count = 1;
96     ctx.where = CallContext.ARG_IN_VALUE1;
97     return module.match1(this, arg1, ctx);
98   }
99
100   public int match2 (Object JavaDoc arg1, Object JavaDoc arg2, CallContext ctx)
101   {
102     ctx.count = 2;
103     ctx.where = CallContext.ARG_IN_VALUE1
104       |(CallContext.ARG_IN_VALUE2<<4);
105     return module.match2(this, arg1, arg2, ctx);
106   }
107
108   public int match3 (Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3, CallContext ctx)
109   {
110     ctx.count = 3;
111     ctx.where = CallContext.ARG_IN_VALUE1
112       |(CallContext.ARG_IN_VALUE2<<4)
113       |(CallContext.ARG_IN_VALUE3<<8);
114     return module.match3(this, arg1, arg2, arg3, ctx);
115   }
116
117   public int match4 (Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3, Object JavaDoc arg4,
118              CallContext ctx)
119   {
120     ctx.count = 4;
121     ctx.where = (CallContext.ARG_IN_VALUE1
122          |(CallContext.ARG_IN_VALUE2<<4)
123          |(CallContext.ARG_IN_VALUE3<<8)
124          |(CallContext.ARG_IN_VALUE4<<12));
125     return module.match4(this, arg1, arg2, arg3, arg4, ctx);
126   }
127
128   public int matchN (Object JavaDoc[] args, CallContext ctx)
129   {
130     ctx.count = args.length;
131     ctx.where = 0;
132     return module.matchN(this, args, ctx);
133   }
134
135   public void apply (CallContext ctx)
136     throws Throwable JavaDoc
137   {
138     // This method does not get called for methods compiled with
139
// --full-tailcalls, since their match methods set ctx.proc to the
140
// ModuleWithContext, rather than this ModuleMethod.
141
// We get here for methods compiled with the --no-full-tailcalls option.
142
// In that case the compiler-generated matchX methods set ctx.pc
143
// to 0...5 to indicate where the arguments were saved.
144
// It would be more consistent to set ctx.where and ctx.count, though
145
// a simple switch of ctx.pc is faster. But how robust is this?
146
Object JavaDoc result;
147     switch (ctx.pc)
148       {
149       case 0:
150     result = apply0();
151     break;
152       case 1:
153     result = apply1(ctx.value1);
154     break;
155       case 2:
156     result = apply2(ctx.value1, ctx.value2);
157     break;
158       case 3:
159     result = apply3(ctx.value1, ctx.value2, ctx.value3);
160     break;
161       case 4:
162     result = apply4(ctx.value1, ctx.value2, ctx.value3, ctx.value4);
163     break;
164       case 5:
165     result = applyN(ctx.values);
166     break;
167       default:
168     throw new Error JavaDoc("internal error - apply "+this);
169       }
170     ctx.writeValue(result);
171   }
172
173   public Object JavaDoc apply0()
174     throws Throwable JavaDoc
175   {
176     return module.apply0(this);
177   }
178
179   public Object JavaDoc apply1(Object JavaDoc arg1)
180     throws Throwable JavaDoc
181   {
182     return module.apply1(this, arg1);
183   }
184
185   public Object JavaDoc apply2(Object JavaDoc arg1, Object JavaDoc arg2)
186     throws Throwable JavaDoc
187   {
188     return module.apply2(this, arg1, arg2);
189   }
190
191   public Object JavaDoc apply3(Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3)
192     throws Throwable JavaDoc
193   {
194     return module.apply3(this, arg1, arg2, arg3);
195   }
196
197   public Object JavaDoc apply4(Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3, Object JavaDoc arg4)
198     throws Throwable JavaDoc
199   {
200     return module.apply4(this, arg1, arg2, arg3, arg4);
201   }
202
203   public Object JavaDoc applyN(Object JavaDoc[] args)
204     throws Throwable JavaDoc
205   {
206     return module.applyN(this, args);
207   }
208
209   public static Object JavaDoc apply0Default(ModuleMethod method)
210     throws Throwable JavaDoc
211   {
212     return method.module.applyN(method, Values.noArgs);
213   }
214
215   public static Object JavaDoc apply1Default(ModuleMethod method, Object JavaDoc arg1)
216     throws Throwable JavaDoc
217   {
218     Object JavaDoc[] args = new Object JavaDoc[1];
219     args[0] = arg1;
220     return method.module.applyN(method, args);
221   }
222
223   public static Object JavaDoc apply2Default(ModuleMethod method, Object JavaDoc arg1, Object JavaDoc arg2)
224     throws Throwable JavaDoc
225   {
226     Object JavaDoc[] args = new Object JavaDoc[2];
227     args[0] = arg1;
228     args[1] = arg2;
229     return method.module.applyN(method, args);
230   }
231
232   public static Object JavaDoc apply3Default(ModuleMethod method,
233                        Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3)
234     throws Throwable JavaDoc
235   {
236     Object JavaDoc[] args = new Object JavaDoc[3];
237     args[0] = arg1;
238     args[1] = arg2;
239     args[2] = arg3;
240     return method.module.applyN(method, args);
241   }
242
243   public static Object JavaDoc apply4Default(ModuleMethod method,
244                        Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3, Object JavaDoc arg4)
245     throws Throwable JavaDoc
246   {
247     Object JavaDoc[] args = new Object JavaDoc[4];
248     args[0] = arg1;
249     args[1] = arg2;
250     args[2] = arg3;
251     args[3] = arg4;
252     return method.module.applyN(method, args);
253   }
254
255   public static Object JavaDoc applyNDefault(ModuleMethod method, Object JavaDoc[] args)
256     throws Throwable JavaDoc
257   {
258     int count = args.length;
259     int num = method.numArgs();
260     ModuleBody module = method.module;
261     if (count >= (num & 0xFFF)
262     && (num < 0 || count <= (num >> 12)))
263       {
264         switch (count)
265           {
266           case 0:
267             return module.apply0(method);
268           case 1:
269             return module.apply1(method, args[0]);
270           case 2:
271             return module.apply2(method, args[0], args[1]);
272           case 3:
273             return module.apply3(method, args[0], args[1], args[2]);
274           case 4:
275             return module.apply4(method, args[0], args[1], args[2], args[3]);
276           }
277       }
278     throw new WrongArguments(method, count);
279   }
280
281   /** Helper methods for default ModuleBody actions. */
282
283   public static void applyError()
284   {
285     throw new Error JavaDoc("internal error - bad selector");
286   }
287 }
288
Popular Tags