KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > reflect > OccurrenceType


1 // Copyright (c) 2003, 2006 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

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 /** A type that matches some number of repetitions of a basetype. */
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     /*
60     Type primeThis = itemPrimeType(getBase());
61     Type primeOther = itemPrimeType(other);
62     FIXME: Compare primThis with primOther AND the occurrence numbers.
63     */

64     return -2;
65   }
66
67   public Object JavaDoc coerceFromObject (Object JavaDoc obj)
68   {
69     if (obj instanceof Values)
70       {
71       }
72     else
73       {
74         // Assumes that base is an item type. FIXME.
75
if (minOccurs <= 1 && maxOccurs != 0)
76           return base.coerceFromObject(obj);
77       }
78     // FIXME
79
if (! isInstance(obj))
80       throw new ClassCastException JavaDoc();
81     return obj;
82   }
83
84   public boolean isInstance (Object JavaDoc 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 JavaDoc 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   /** Return a conservative estimage on the min/max number of items of a type.
164    * @return {@code maxCount << 12 | minCount & 0xFFF},
165    * where a {@code maxCount} of -1 means unbounded.
166    */

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   /** Returna a quantifer kind for a sequence type.
216    * @return '0' if type is known to be a void (0-item) type;
217    * '1' if type is known to be a single-item type;
218    * '?' if type matches a sequence of 0 or 1 items;
219    * '+' if type matches a sequence of 1 or more items;
220    * '*' otherwise.
221    */

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     // cute hack for: max == 0 || max == 1.
235
return (itemCountRange(type) >> 13) == 0;
236   }
237
238   public static boolean itemCountIsOne (Type type)
239   {
240     return itemCountRange(type) == 0x1001;
241   }
242
243   /** QUery formal semantics "prime type"
244    */

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 JavaDoc toString ()
261   {
262     String JavaDoc b = base.toString();
263     boolean parens = b == null || b.indexOf(' ') >= 0;
264     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
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 JavaDoc
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