KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > GenericProc


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 gnu.bytecode.Type;
7
8 /** A collection of MethodProcs; one is chosen at apply time. */
9
10 public class GenericProc extends MethodProc
11 {
12   protected MethodProc[] methods;
13   int count;
14   int minArgs;
15   int maxArgs;
16
17   public GenericProc (String JavaDoc name)
18   {
19     setName(name);
20   }
21
22   public GenericProc ()
23   {
24   }
25
26   public int numArgs()
27   {
28     return minArgs | (maxArgs << 12);
29   }
30
31   protected synchronized void add (MethodProc[] procs)
32   {
33     int n = procs.length;
34     if (methods == null)
35       methods = new MethodProc[n];
36     for (int i = 0; i < n; i++)
37       add(procs[i]);
38   }
39
40   public synchronized void add(MethodProc method)
41   {
42     if (methods == null)
43       methods = new MethodProc[8];
44     else if (count >= methods.length)
45       {
46         MethodProc[] copy = new MethodProc[2 * methods.length];
47         System.arraycopy(methods, 0, copy, 0, count);
48         methods = copy;
49       }
50
51     int i;
52     for (i = 0; i < count; i++)
53       {
54     MethodProc best = MethodProc.mostSpecific(method, methods[i]);
55     if (best == method)
56       break;
57       }
58     if (i < count)
59       System.arraycopy(methods, i, methods, i + 1, count - i);
60     methods[i] = method;
61
62     int n = method.minArgs();
63     if (n < minArgs || count==0)
64       minArgs = n;
65     n = method.maxArgs();
66     if (n == -1 || n > maxArgs)
67       maxArgs = n;
68     count++;
69   }
70
71   /* Possibly optimization. Likewise for apply0, apply2, apply3, apply4.
72   public Object apply1 (Object arg1) throws Throwable
73   {
74     if (numArgs() != 0x1001)
75       {
76     Object[] args = { arg1 };
77     return applyN(args);
78       }
79     CallContext ctx = CallContext.getInstance();
80     for (int i = 0; i < count; i++)
81       {
82         MethodProc method = methods[i];
83         if (method.match1(arg1, ctx) == 0)
84       return method.applyV(ctx);
85       }
86     throw new WrongType(this, WrongType.ARG_UNKNOWN, null);
87   }
88   */

89
90   public Object JavaDoc applyN(Object JavaDoc[] args) throws Throwable JavaDoc
91   {
92     if (count == 1)
93       return methods[0].applyN(args);
94     checkArgCount(this, args.length);
95     CallContext ctx = CallContext.getInstance();
96     for (int i = 0; i < count; i++)
97       {
98         MethodProc method = methods[i];
99     int m = method.matchN(args, ctx);
100         if (m == 0)
101       return ctx.runUntilValue();
102       }
103     throw new WrongType(this, WrongType.ARG_UNKNOWN, null);
104   }
105
106   public int isApplicable(Type[] args)
107   {
108     int best = -1;
109     for (int i = count; --i >= 0; )
110       {
111         MethodProc method = methods[i];
112         int result = method.isApplicable(args);
113         if (result == 1)
114           return 1;
115         if (result == 0)
116           best = 0;
117       }
118     return best;
119   }
120
121   public int match0 (CallContext ctx)
122   {
123     if (count == 1)
124       return methods[0].match0(ctx);
125     for (int i = 0; i < count; i++)
126       {
127         MethodProc method = methods[i];
128     int code = method.match0(ctx);
129     if (code == 0)
130       return 0;
131       }
132     ctx.proc = null;
133     return NO_MATCH;
134   }
135
136   public int match1 (Object JavaDoc arg1, CallContext ctx)
137   {
138     if (count == 1)
139       return methods[0].match1(arg1, ctx);
140     for (int i = 0; i < count; i++)
141       {
142         MethodProc method = methods[i];
143     int code = method.match1(arg1, ctx);
144     if (code == 0)
145       return 0;
146       }
147     ctx.proc = null;
148     return NO_MATCH;
149   }
150
151   public int match2 (Object JavaDoc arg1, Object JavaDoc arg2, CallContext ctx)
152   {
153     if (count == 1)
154       return methods[0].match2(arg1, arg2, ctx);
155     for (int i = 0; i < count; i++)
156       {
157         MethodProc method = methods[i];
158     int code = method.match2(arg1, arg2, ctx);
159     if (code == 0)
160       return 0;
161       }
162     ctx.proc = null;
163     return NO_MATCH;
164   }
165
166   public int match3 (Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3, CallContext ctx)
167   {
168     if (count == 1)
169       return methods[0].match3(arg1, arg2, arg3, ctx);
170     for (int i = 0; i < count; i++)
171       {
172         MethodProc method = methods[i];
173     int code = method.match3(arg1, arg2, arg3, ctx);
174     if (code == 0)
175       return 0;
176       }
177     ctx.proc = null;
178     return NO_MATCH;
179   }
180
181   public int match4 (Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3, Object JavaDoc arg4,
182              CallContext ctx)
183   {
184     if (count == 1)
185       return methods[0].match4(arg1, arg2, arg3, arg4, ctx);
186     for (int i = 0; i < count; i++)
187       {
188         MethodProc method = methods[i];
189     int code = method.match4(arg1, arg2, arg3, arg4, ctx);
190     if (code == 0)
191       return 0;
192       }
193     ctx.proc = null;
194     return NO_MATCH;
195   }
196
197   public int matchN (Object JavaDoc[] args, CallContext ctx)
198   {
199     if (count == 1)
200       return methods[0].matchN(args, ctx);
201     int alen = args.length;
202     Type[] atypes = new Type[alen];
203     Language language = Language.getDefaultLanguage();
204     // As a rough approximation of finding the "best match", and also
205
// an approximation of what we do when selecting a method at compile-time,
206
// let's make a pre-pass to check which methods are applicable.
207
for (int j = 0; j < alen; j++)
208       {
209         Object JavaDoc arg = args[j];
210         Type atype;
211         if (arg == null)
212           atype = Type.nullType;
213         else
214           {
215             Class JavaDoc aclass = arg.getClass();
216             if (language != null)
217               atype = language.getTypeFor(aclass);
218             else
219               atype = Type.make(aclass);
220           }
221         atypes[j] = atype;
222       }
223     int[] codes = new int[count];
224     int defCount = 0;
225     int maybeCount = 0;
226     int bestIndex = -1;
227     for (int i = 0; i < count; i++)
228       {
229         int code = methods[i].isApplicable(atypes);
230         if (defCount == 0 && code >= 0)
231           bestIndex = i;
232         if (code > 0)
233           defCount++;
234         else if (code == 0)
235           maybeCount++;
236         codes[i] = code;
237       }
238     if (defCount == 1 || (defCount == 0 && maybeCount == 1))
239       return methods[bestIndex].matchN(args, ctx);
240     for (int i = 0; i < count; i++)
241       {
242         int code = codes[i];
243         if (code < 0 || (code == 0 && defCount > 0))
244           continue;
245         MethodProc method = methods[i];
246     code = method.matchN(args, ctx);
247     if (code == 0)
248       return 0;
249       }
250     ctx.proc = null;
251     return NO_MATCH;
252   }
253
254   public final void setProperties (Object JavaDoc[] args)
255   {
256     int alen = args.length;
257     for (int i = 0; i < alen; i++)
258       {
259     Object JavaDoc arg = args[i];
260     if (arg instanceof Keyword)
261       {
262         String JavaDoc name = ((Keyword) arg).getName();
263         Object JavaDoc value = args[++i];
264         if (name == "name")
265           setName(value.toString());
266         else if (name == "method")
267           add((MethodProc) value);
268         else
269           setProperty(name, value);
270       }
271     else
272       add((MethodProc) arg);
273       }
274   }
275
276   /** Create a GenericProc from one or more methods, plus properties. */
277   public static GenericProc make (Object JavaDoc[] args)
278   {
279     GenericProc result = new GenericProc();
280     result.setProperties(args);
281     return result;
282   }
283 }
284
Popular Tags