1 4 package gnu.mapping; 5 import gnu.bytecode.Type; 6 7 9 10 public abstract class MethodProc extends ProcedureN 11 { 12 14 protected Object argTypes; 15 16 18 public int isApplicable(Type[] argTypes) 19 { 20 int argCount = argTypes.length; 21 int num = numArgs(); 22 if (argCount < (num & 0xFFF) 23 || (num >= 0 && argCount > (num >> 12))) 24 return -1; 25 int result = 1; 26 for (int i = argCount; --i >= 0; ) 27 { 28 Type ptype = getParameterType(i); 29 int code = ptype.compare(argTypes[i]); 30 if (code == -3) 31 return -1; 32 if (code < 0) 33 result = 0; 34 } 35 return result; 36 } 37 38 39 public int numParameters() 40 { 41 int num = numArgs(); 42 int max = num >> 12; 43 if (max >= 0) 44 return max; 45 int min = num & 0xFFF; 47 return min + 1; 48 } 49 50 static final Type[] unknownArgTypes = { Type.pointer_type }; 51 52 53 protected void resolveParameterTypes() 54 { 55 argTypes = unknownArgTypes; 56 } 57 58 public Type getParameterType(int index) 59 { 60 if (! (argTypes instanceof Type[])) 61 resolveParameterTypes(); 62 63 Type[] atypes = (Type[]) argTypes; 64 if (index >= atypes.length) 65 index = atypes.length - 1; 66 return atypes[index]; 67 } 68 69 70 public static final int NO_MATCH = -1; 71 72 74 public static final int NO_MATCH_TOO_FEW_ARGS = 0xfff10000; 75 76 78 public static final int NO_MATCH_TOO_MANY_ARGS = 0xfff20000; 79 80 81 public static final int NO_MATCH_AMBIGUOUS = 0xfff30000; 82 83 86 public static final int NO_MATCH_BAD_TYPE = 0xfff40000; 87 88 90 public static RuntimeException 91 matchFailAsException(int code, Procedure proc, Object [] args) 92 { 93 int arg = (short) code; 94 code &= 0xffff0000; 95 if (code != NO_MATCH_BAD_TYPE) 96 return new WrongArguments(proc, args.length); 97 return new WrongType(proc, arg, arg > 0 ? args[arg-1] : null); 98 } 99 100 public Object applyN(Object [] args) throws Throwable 101 { 102 checkArgCount(this, args.length); 103 CallContext ctx = CallContext.getInstance(); 104 checkN(args, ctx); 105 return ctx.runUntilValue(); 106 } 107 108 110 public static MethodProc mostSpecific(MethodProc proc1, MethodProc proc2) 111 { 112 boolean not1 = false; 114 boolean not2 = false; 116 int min1 = proc1.minArgs(); 117 int min2 = proc2.minArgs(); 118 int max1 = proc1.maxArgs(); 119 int max2 = proc2.maxArgs(); 120 if ((max1 >= 0 && max1 < min2) 121 || (max2 >= 0 && max2 < min1)) 122 return null; 123 int num1 = proc1.numParameters(); 124 int num2 = proc2.numParameters(); 125 int limit = num1 > num2 ? num1 : num2; 126 if (max1 != max2) 127 { 128 if (max1 < 0) 129 not2 = true; 130 if (max2 < 0) 131 not1 = true; 132 } 133 if (min1 < min2) 134 not2 = true; 135 else if (min1 > min2) 136 not1 = true; 137 for (int i = 0; i < limit; i++) 138 { 139 Type t1 = proc1.getParameterType(i); 140 Type t2 = proc2.getParameterType(i); 141 int comp = t1.compare(t2); 142 if (comp == -1) 143 { 144 not2 = true; 145 if (not1) 146 return null; 147 } 148 if (comp == 1) 149 { 150 not1 = true; 151 if (not2) 152 return null; 153 } 154 } 155 return not2 ? proc1 : not1 ? proc2 : null; 156 } 157 158 159 public static int mostSpecific(MethodProc[] procs, int length) 160 { 161 if (length <= 1) return length - 1; 163 MethodProc best = procs[0]; 165 MethodProc[] bests = null; 168 int bestn = 0; 171 outer: 172 for (int i = 1; i < length; i++) 173 { 174 MethodProc method = procs[i]; 175 if (best != null) 176 { 177 MethodProc winner = mostSpecific(best, method); 178 if (winner == null) 179 { 180 if (bests == null) 181 bests = new MethodProc[length]; 182 bests[0] = best; 183 bests[1] = method; 184 bestn = 2; 185 best = null; 186 } 187 else if (winner == method) 188 { 189 best = method; 190 bestn = i; 191 } 192 } 193 else 194 { 195 for (int j = 0; j < bestn; j++) 196 { 197 MethodProc old = bests[j]; 198 MethodProc winner = mostSpecific(old, method); 199 if (winner == old) 200 continue outer; 201 if (winner == null) 202 { 203 bests[bestn++] = method; 204 continue outer; 205 } 206 } 207 best = method; 209 bestn = i; 210 } 211 } 212 return best == null ? -1 : bestn; 213 } 214 } 215 | Popular Tags |