1 4 package gnu.expr; 5 import gnu.mapping.*; 6 import gnu.bytecode.Type; 7 8 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 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 89 90 public Object applyN(Object [] args) throws Throwable 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 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 arg1, Object 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 arg1, Object arg2, Object 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 arg1, Object arg2, Object arg3, Object 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 [] 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 for (int j = 0; j < alen; j++) 208 { 209 Object arg = args[j]; 210 Type atype; 211 if (arg == null) 212 atype = Type.nullType; 213 else 214 { 215 Class 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 [] args) 255 { 256 int alen = args.length; 257 for (int i = 0; i < alen; i++) 258 { 259 Object arg = args[i]; 260 if (arg instanceof Keyword) 261 { 262 String name = ((Keyword) arg).getName(); 263 Object 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 277 public static GenericProc make (Object [] args) 278 { 279 GenericProc result = new GenericProc(); 280 result.setProperties(args); 281 return result; 282 } 283 } 284 | Popular Tags |