1 4 package gnu.kawa.reflect; 5 import gnu.bytecode.*; 6 import gnu.mapping.Procedure; 7 import gnu.mapping.Values; 8 import gnu.lists.*; 9 import java.io.*; 10 import gnu.expr.*; 11 12 13 14 public class OccurrenceType extends ObjectType 15 implements Externalizable, TypeValue 16 { 17 Type base; 18 int minOccurs; 19 int maxOccurs; 20 21 public Type getBase () { return base; } 22 public int minOccurs() { return minOccurs; } 23 public int maxOccurs() { return maxOccurs; } 24 25 public OccurrenceType (Type base, int minOccurs, int maxOccurs) 26 { 27 this.base = base; 28 this.minOccurs = minOccurs; 29 this.maxOccurs = maxOccurs; 30 } 31 32 public static Type getInstance (Type base, int minOccurs, int maxOccurs) 33 { 34 if (minOccurs == 1 && maxOccurs == 1) 35 return base; 36 if (minOccurs == 0 && maxOccurs < 0 37 && (base == SingletonType.instance || base == Type.pointer_type)) 38 return Type.pointer_type; 39 return new OccurrenceType(base, minOccurs, maxOccurs); 40 } 41 42 public static final Type emptySequenceType = 43 OccurrenceType.getInstance(SingletonType.instance, 0, 0); 44 45 public Type getImplementationType() 46 { 47 return Type.pointer_type; 48 } 49 50 public int compare(Type other) 51 { 52 if (other instanceof OccurrenceType) 53 { 54 OccurrenceType occOther = (OccurrenceType) other; 55 if (minOccurs == occOther.minOccurs 56 && maxOccurs == occOther.maxOccurs) 57 return base.compare(occOther.getBase()); 58 } 59 64 return -2; 65 } 66 67 public Object coerceFromObject (Object obj) 68 { 69 if (obj instanceof Values) 70 { 71 } 72 else 73 { 74 if (minOccurs <= 1 && maxOccurs != 0) 76 return base.coerceFromObject(obj); 77 } 78 if (! isInstance(obj)) 80 throw new ClassCastException (); 81 return obj; 82 } 83 84 public boolean isInstance (Object obj) 85 { 86 if (obj instanceof Values) 87 { 88 Values vals = (Values) obj; 89 int pos = vals.startPos(); 90 int n = 0; 91 if (base instanceof ElementPredicate) 92 { 93 ElementPredicate pred = (ElementPredicate) base; 94 for (;;) 95 { 96 boolean matches; 97 matches = pred.isInstancePos(vals, pos); 98 pos = vals.nextPos(pos); 99 if (pos == 0) 100 { 101 return n >= minOccurs 102 && (maxOccurs < 0 || n <= maxOccurs); 103 } 104 if (! matches) 105 return false; 106 n++; 107 } 108 } 109 else 110 { 111 112 for (;;) 113 { 114 pos = vals.nextPos(pos); 115 if (pos == 0) 116 { 117 return n >= minOccurs 118 && (maxOccurs < 0 || n <= maxOccurs); 119 } 120 Object value = vals.getPosPrevious(pos); 121 if (! base.isInstance(value)) 122 return false; 123 n++; 124 } 125 } 126 } 127 else 128 { 129 if (minOccurs > 1 || maxOccurs == 0) 130 return false; 131 return base.isInstance(obj); 132 } 133 } 134 135 public void emitTestIf(Variable incoming, Declaration decl, 136 Compilation comp) 137 { 138 CodeAttr code = comp.getCode(); 139 if (incoming != null) 140 code.emitLoad(incoming); 141 if (decl != null) 142 { 143 code.emitDup(); 144 decl.compileStore(comp); 145 } 146 comp.compileConstant(this); 147 code.emitSwap(); 148 code.emitInvokeVirtual(isInstanceMethod); 149 code.emitIfIntNotZero(); 150 } 151 152 public void emitIsInstance(Variable incoming, 153 Compilation comp, Target target) 154 { 155 gnu.kawa.reflect.InstanceOf.emitIsInstance(this, incoming, comp, target); 156 } 157 158 public Procedure getConstructor () 159 { 160 return null; 161 } 162 163 167 public static int itemCountRange (Type type) 168 { 169 if (type instanceof SingletonType) 170 return (1 << 12) | 1; 171 if (type instanceof OccurrenceType) 172 { 173 OccurrenceType occ = (OccurrenceType) type; 174 int min = occ.minOccurs(); 175 int max = occ.maxOccurs(); 176 int bnum = itemCountRange(occ.getBase()); 177 if ((min == 1 && max == 1) 178 || bnum == 0) 179 return bnum; 180 if (max > 0xfffff) 181 max = -1; 182 if (max == 0) 183 return 0; 184 int bmin = bnum & 0xfff; 185 int bmax = bnum >> 12; 186 if (bnum != 0x1001) 187 { 188 if (min > 0xfff) 189 min = 0xfff; 190 min = min * bmin; 191 if (min > 0xfff) 192 min = 0xfff; 193 if (max < 0 || bmax < 0) 194 max = -1; 195 else 196 max = max * bmax; 197 if (max > 0xfffff) 198 max = -1; 199 } 200 return (max << 12) | min; 201 } 202 if (type instanceof PrimType) 203 return type.isVoid() ? 0 : 0x1001; 204 if (type instanceof ArrayType) 205 return 0x1001; 206 if (type instanceof ObjectType) 207 { 208 int cmp = type.compare(Compilation.typeValues); 209 if (cmp == -3) 210 return 0x1001; 211 } 212 return -1 << 12; 213 } 214 215 222 public static char itemCountCode (Type type) 223 { 224 int num = itemCountRange(type); 225 int min = num & 0xFFF; 226 int max = num >> 12; 227 return max == 0 ? '0' 228 : min == 0 ? (max == 1 ? '?' : '*') 229 : min == 1 && max == 1 ? '1' : '+'; 230 } 231 232 public static boolean itemCountIsZeroOrOne (Type type) 233 { 234 return (itemCountRange(type) >> 13) == 0; 236 } 237 238 public static boolean itemCountIsOne (Type type) 239 { 240 return itemCountRange(type) == 0x1001; 241 } 242 243 245 public static Type itemPrimeType (Type type) 246 { 247 while (type instanceof OccurrenceType) 248 type = ((OccurrenceType) type).getBase(); 249 return itemCountIsOne(type) ? type : SingletonType.instance; 250 251 } 252 253 public void writeExternal(ObjectOutput out) throws IOException 254 { 255 out.writeObject(base); 256 out.writeInt(minOccurs); 257 out.writeInt(maxOccurs); 258 } 259 260 public String toString () 261 { 262 String b = base.toString(); 263 boolean parens = b == null || b.indexOf(' ') >= 0; 264 StringBuffer sbuf = new StringBuffer (); 265 if (parens) 266 sbuf.append('('); 267 sbuf.append(b); 268 if (parens) 269 sbuf.append(')'); 270 if (minOccurs == 1 && maxOccurs == 1) 271 ; 272 else if (minOccurs == 0 && maxOccurs == 1) 273 sbuf.append('?'); 274 else if (minOccurs == 1 && maxOccurs == -1) 275 sbuf.append('+'); 276 else if (minOccurs == 0 && maxOccurs == -1) 277 sbuf.append('*'); 278 else 279 { 280 sbuf.append('{'); 281 sbuf.append(minOccurs); 282 sbuf.append(','); 283 if (maxOccurs >= 0) 284 sbuf.append(maxOccurs); 285 else 286 sbuf.append('*'); 287 sbuf.append('}'); 288 } 289 return sbuf.toString(); 290 } 291 292 public void readExternal(ObjectInput in) 293 throws IOException, ClassNotFoundException 294 { 295 base = (Type) in.readObject(); 296 minOccurs = in.readInt(); 297 maxOccurs = in.readInt(); 298 } 299 300 public static final ClassType typeOccurrenceType 301 = ClassType.make("gnu.kawa.reflect.OccurrenceType"); 302 static final Method isInstanceMethod 303 = typeOccurrenceType.getDeclaredMethod("isInstance", 1); 304 } 305 | Popular Tags |