1 4 package gnu.mapping; 5 6 10 11 public abstract class Procedure extends PropertySet 12 { 13 private static final String sourceLocationKey = "source-location"; 14 private static final String setterKey = "setter"; 15 16 public void setSourceLocation (String file, int line) 17 { 18 setProperty(sourceLocationKey, file + ":" + line); 19 } 20 21 public String getSourceLocation () 22 { 23 Object value = getProperty(sourceLocationKey, null); 24 return value == null ? null : value.toString(); 25 } 26 27 public Procedure() 28 { 29 } 30 31 public Procedure(String n) 32 { 33 setName(n); 34 } 35 36 public abstract Object applyN (Object [] args) throws Throwable ; 37 38 public abstract Object apply0 () throws Throwable ; 39 40 public abstract Object apply1 (Object arg1) throws Throwable ; 41 42 public abstract Object apply2 (Object arg1,Object arg2) throws Throwable ; 43 44 public abstract Object apply3 (Object arg1, Object arg2, Object arg3) throws Throwable ; 45 46 public abstract Object apply4(Object arg1,Object arg2, 47 Object arg3,Object arg4) throws Throwable ; 48 49 50 public final int minArgs() { return numArgs() & 0xFFF; } 51 52 55 public final int maxArgs() { return numArgs() >> 12; } 56 57 63 public static void checkArgCount(Procedure proc, int argCount) 64 { 65 int num = proc.numArgs(); 66 if (argCount < (num & 0xFFF) 67 || (num >= 0 && argCount > (num >> 12))) 68 throw new WrongArguments(proc, argCount); 69 } 70 71 72 73 78 public int numArgs() { return 0xfffff000; } 79 80 88 89 92 93 public void apply (CallContext ctx) throws Throwable 94 { 95 apply(this, ctx); 96 } 97 98 public static void apply (Procedure proc, CallContext ctx) throws Throwable 99 { 100 Object result; 101 int count = ctx.count; 102 if (ctx.where == 0 && count != 0) 103 result = proc.applyN(ctx.values); 104 else 105 { 106 switch (count) 107 { 108 case 0: 109 result = proc.apply0(); 110 break; 111 case 1: 112 result = proc.apply1(ctx.getNextArg()); 113 break; 114 case 2: 115 result = proc.apply2(ctx.getNextArg(), ctx.getNextArg()); 116 break; 117 case 3: 118 result = proc.apply3(ctx.getNextArg(), ctx.getNextArg(), 119 ctx.getNextArg()); 120 break; 121 case 4: 122 result = proc.apply4(ctx.getNextArg(), ctx.getNextArg(), 123 ctx.getNextArg(), ctx.getNextArg()); 124 break; 125 default: 126 result = proc.applyN(ctx.getArgs()); 127 break; 128 } 129 } 130 ctx.writeValue(result); 131 } 132 133 136 public int match0 (CallContext ctx) 137 { 138 int num = numArgs(); 139 int min = num & 0xFFF; 140 if (min > 0) 141 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 142 if (num < 0) 143 return matchN(ProcedureN.noArgs, ctx); 144 ctx.count = 0; 145 ctx.where = 0; 146 ctx.next = 0; 147 ctx.proc = this; 148 return 0; 149 } 150 151 154 public int match1 (Object arg1, CallContext ctx) 155 { 156 int num = numArgs(); 157 int min = num & 0xFFF; 158 if (min > 1) 159 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 160 if (num >= 0) 161 { 162 int max = num >> 12; 163 if (max < 1) 164 return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 165 ctx.value1 = arg1; 166 ctx.count = 1; 167 ctx.where = CallContext.ARG_IN_VALUE1; 168 ctx.next = 0; 169 ctx.proc = this; 170 return 0; 171 } 172 Object [] args = { arg1 }; 173 return matchN(args, ctx); 174 } 175 176 179 public int match2 (Object arg1, Object arg2, CallContext ctx) 180 { 181 int num = numArgs(); 182 int min = num & 0xFFF; 183 if (min > 2) 184 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 185 if (num >= 0) 186 { 187 int max = num >> 12; 188 if (max < 2) 189 return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 190 ctx.value1 = arg1; 191 ctx.value2 = arg2; 192 ctx.count = 2; 193 ctx.where = CallContext.ARG_IN_VALUE1 194 |(CallContext.ARG_IN_VALUE2<<4); 195 ctx.next = 0; 196 ctx.proc = this; 197 return 0; 198 } 199 Object [] args = { arg1, arg2 }; 200 return matchN(args, ctx); 201 } 202 203 206 public int match3 (Object arg1, Object arg2, Object arg3, CallContext ctx) 207 { 208 int num = numArgs(); 209 int min = num & 0xFFF; 210 if (min > 3) 211 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 212 if (num >= 0) 213 { 214 int max = num >> 12; 215 if (max < 3) 216 return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 217 ctx.value1 = arg1; 218 ctx.value2 = arg2; 219 ctx.value3 = arg3; 220 ctx.count = 3; 221 ctx.where = CallContext.ARG_IN_VALUE1 222 |(CallContext.ARG_IN_VALUE2<<4) 223 |(CallContext.ARG_IN_VALUE3<<8); 224 ctx.next = 0; 225 ctx.proc = this; 226 return 0; 227 } 228 Object [] args = { arg1, arg2, arg3 }; 229 return matchN(args, ctx); 230 } 231 232 235 public int match4 (Object arg1, Object arg2, Object arg3, Object arg4, 236 CallContext ctx) 237 { 238 int num = numArgs(); 239 int min = num & 0xFFF; 240 if (min > 4) 241 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 242 if (num >= 0) 243 { 244 int max = num >> 12; 245 if (max < 4) 246 return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 247 ctx.value1 = arg1; 248 ctx.value2 = arg2; 249 ctx.value3 = arg3; 250 ctx.value4 = arg4; 251 ctx.count = 4; 252 ctx.where = (CallContext.ARG_IN_VALUE1 253 |(CallContext.ARG_IN_VALUE2<<4) 254 |(CallContext.ARG_IN_VALUE3<<8) 255 |(CallContext.ARG_IN_VALUE4<<12)); 256 ctx.next = 0; 257 ctx.proc = this; 258 return 0; 259 } 260 Object [] args = { arg1, arg2, arg3, arg4 }; 261 return matchN(args, ctx); 262 } 263 264 public int matchN (Object [] args, CallContext ctx) 265 { 266 int num = numArgs(); 267 int min = num & 0xFFF; 268 if (args.length < min) 269 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 270 if (num >= 0) 271 { 272 switch (args.length) 273 { 274 case 0: 275 return match0(ctx); 276 case 1: 277 return match1(args[0], ctx); 278 case 2: 279 return match2(args[0], args[1], ctx); 280 case 3: 281 return match3(args[0], args[1], args[2], ctx); 282 case 4: 283 return match4(args[0], args[1], args[2], args[3], ctx); 284 default: 285 int max = num >> 12; 286 if (args.length > max) 287 return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 288 } 289 } 290 ctx.values = args; 291 ctx.count = args.length; 292 ctx.where = 0; 293 ctx.next = 0; 294 ctx.proc = this; 295 return 0; 296 } 297 298 299 public void check0 (CallContext ctx) 300 { 301 int code = match0(ctx); 302 if (code != 0) 303 { 304 throw MethodProc.matchFailAsException(code, this, ProcedureN.noArgs); 305 } 306 } 307 308 309 public void check1 (Object arg1, CallContext ctx) 310 { 311 int code = match1(arg1, ctx); 312 if (code != 0) 313 { 314 Object [] args = { arg1 }; 315 throw MethodProc.matchFailAsException(code, this, args); 316 } 317 } 318 319 320 public void check2 (Object arg1, Object arg2, CallContext ctx) 321 { 322 int code = match2(arg1, arg2, ctx); 323 if (code != 0) 324 { 325 Object [] args = { arg1, arg2 }; 326 throw MethodProc.matchFailAsException(code, this, args); 327 } 328 } 329 330 331 public void check3 (Object arg1, Object arg2, Object arg3, CallContext ctx) 332 { 333 int code = match3(arg1, arg2, arg3, ctx); 334 if (code != 0) 335 { 336 Object [] args = { arg1, arg2, arg3 }; 337 throw MethodProc.matchFailAsException(code, this, args); 338 } 339 } 340 341 342 public void check4 (Object arg1, Object arg2, Object arg3, Object arg4, 343 CallContext ctx) 344 { 345 int code = match4(arg1, arg2, arg3, arg4, ctx); 346 if (code != 0) 347 { 348 Object [] args = { arg1, arg2, arg3, arg4 }; 349 throw MethodProc.matchFailAsException(code, this, args); 350 } 351 } 352 353 354 public void checkN (Object [] args, CallContext ctx) 355 { 356 int code = matchN(args, ctx); 357 if (code != 0) 358 { 359 throw MethodProc.matchFailAsException(code, this, args); 360 } 361 } 362 363 public Procedure getSetter() 364 { 365 if (! (this instanceof HasSetter)) 366 { 367 Object setter = getProperty(setterKey, null); 368 if (setter instanceof Procedure) 369 return (Procedure) setter; 370 throw new RuntimeException ("procedure '"+getName()+ "' has no setter"); 371 } 372 int num_args = numArgs(); 373 if (num_args == 0x0000) 374 return new Setter0(this); 375 if (num_args == 0x1001) 376 return new Setter1(this); 377 return new Setter(this); 378 } 379 380 public void setSetter (Procedure setter) 381 { 382 if (this instanceof HasSetter) 383 throw new RuntimeException ("procedure '"+getName()+ 384 "' has builtin setter - cannot be modified"); 385 setProperty(Procedure.setterKey, setter); 386 } 387 388 389 public void set0(Object result) throws Throwable 390 { 391 getSetter().apply1(result); 392 } 393 394 public void set1(Object arg1, Object value) throws Throwable 395 { 396 getSetter().apply2(arg1, value); 397 } 398 399 public void setN (Object [] args) throws Throwable 400 { 401 getSetter().applyN(args); 402 } 403 404 public String toString () 405 { 406 StringBuffer sbuf = new StringBuffer (); 407 sbuf.append ("#<procedure "); 408 String n = getName(); 409 if (n == null) 410 n = getSourceLocation(); 411 if (n == null) 412 n = getClass().getName(); 413 sbuf.append(n); 414 sbuf.append('>'); 415 return sbuf.toString(); 416 } 417 } 418 | Popular Tags |