KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > param > types > Subst_c


1 package polyglot.ext.param.types;
2
3 import polyglot.ext.jl.types.*;
4 import polyglot.types.*;
5 import polyglot.types.Package;
6 import polyglot.util.*;
7 import java.util.*;
8 import java.io.IOException JavaDoc;
9
10 import polyglot.ext.param.Topics;
11 import polyglot.main.Report;
12
13 /**
14  * Utility class that performs substitutions on type objects using a
15  * map. Subclasses must define how the substititions are performed and
16  * how to cache substituted types.
17  */

18 public class Subst_c implements Subst
19 {
20     /** Map from formal parameters (of type Param) to actuals. */
21     protected Map subst;
22
23     /** Cache of types. */
24     protected transient Map cache;
25
26     protected transient ParamTypeSystem ts;
27
28     public Subst_c(ParamTypeSystem ts, Map subst, Map cache)
29     {
30         this.ts = ts;
31         this.subst = subst;
32         this.cache = new HashMap();
33         this.cache.putAll(cache);
34     }
35
36     public ParamTypeSystem typeSystem() {
37         return ts;
38     }
39
40     /**
41      * Entries of the underlying substitution map.
42      * @return an <code>Iterator</code> of <code>Map.Entry</code>.
43      */

44     public Iterator entries() {
45         return substitutions().entrySet().iterator();
46     }
47
48     /**
49      * The underlying substitution map.
50      */

51     public Map substitutions() {
52         return Collections.unmodifiableMap(subst);
53     }
54
55     /** Perform substitutions on a type, without checking the cache. */
56     protected Type uncachedSubstType(Type t) {
57         if (t.isArray()) {
58             ArrayType at = t.toArray();
59             return at.base(substType(at.base()));
60         }
61
62         // We may have a parameterized type instantiated on the formals.
63
if (t instanceof SubstType) {
64             Type tbase = ((SubstType) t).base();
65             Map tsubst = ((SubstType) t).subst().substitutions();
66
67             Map newSubst = new HashMap();
68
69             for (Iterator i = tsubst.entrySet().iterator(); i.hasNext(); ) {
70                 Map.Entry e = (Map.Entry) i.next();
71                 Object JavaDoc formal = e.getKey();
72                 Object JavaDoc actual = e.getValue();
73                 
74                 Object JavaDoc existent = getSubstValueAsKey(actual);
75                 if (existent != null) {
76                     // In this case:
77
// this.base is C[T], where T is a formal of C
78
// t.base is D[U], where U is a formal of D
79
// t.subst has U -> T, thus t is D[T]
80
// this.subst has T -> X
81
// so replace U -> T in t.subst with U -> X
82
newSubst.put(formal, existent);
83                 }
84                 else {
85                     newSubst.put(formal, actual);
86                 }
87             }
88
89             // Now add our substitutions, overriding any substitutions
90
// performed in t.subst
91
newSubst.putAll(subst);
92
93             // We can use the same cache, since newSubst is compatible with
94
// this.subst.
95
return ts.subst(tbase, newSubst, cache);
96         }
97
98         if (t instanceof ClassType) {
99             return substClassType((ClassType) t);
100         }
101
102         return t;
103     }
104
105     /**
106      * When adding a new substitution A-&gt;B to the map, we need to check if
107      * there are already any existing substitutions, say C-&gt;A, and if so,
108      * replace them appropriately, in this case with C-&gt;B.
109      *
110      * This method allows subclasses to check if a value (B in the
111      * example above) is present as a key. Subclasses may need to override this
112      * if the keys and values are not the same object.
113      */

114     protected Object JavaDoc getSubstValueAsKey(Object JavaDoc v) {
115         return substitutions().get(v);
116     }
117     
118     /** Perform substitutions on a class type. Substitutions are performed
119      * lazily. */

120     public ClassType substClassType(ClassType t) {
121         return new SubstClassType_c(ts, t.position(), t, this);
122     }
123
124     /** Perform substitutions on a type. */
125     public Type substType(Type t) {
126         if (t == null || t == this)
127             return t;
128
129         Type cached = (Type) cache.get(t);
130
131         if (cached == null) {
132             cached = uncachedSubstType(t);
133             cache.put(t, cached);
134
135             if (Report.should_report(Topics.subst, 2))
136                 Report.report(2, "substType(" +
137                               t + ": " + t.getClass().getName() + ") = " +
138                               cached + ": " + cached.getClass().getName());
139         }
140
141         return cached;
142     }
143
144     /** Perform substitution on a PClass. */
145     public PClass substPClass(PClass pclazz) {
146         MuPClass newPclazz = ts.mutablePClass(pclazz.position());
147         newPclazz.formals(pclazz.formals());
148         newPclazz.clazz((ClassType) substType(pclazz.clazz()));
149         return newPclazz;
150     }
151
152     /** Perform substitutions on a field. */
153     public FieldInstance substField(FieldInstance fi) {
154         ReferenceType ct = (ReferenceType) substType(fi.container());
155         Type t = substType(fi.type());
156         return fi.type(t).container(ct);
157     }
158
159     /** Perform substitutions on a method. */
160     public MethodInstance substMethod(MethodInstance mi) {
161         ReferenceType ct = (ReferenceType) substType(mi.container());
162
163         Type rt = substType(mi.returnType());
164
165         List formalTypes = mi.formalTypes();
166         formalTypes = substTypeList(formalTypes);
167
168         List throwTypes = mi.throwTypes();
169         throwTypes = substTypeList(throwTypes);
170
171         return (MethodInstance) mi.returnType(rt).formalTypes(formalTypes).throwTypes(throwTypes).container(ct);
172     }
173
174     /** Perform substitutions on a constructor. */
175     public ConstructorInstance substConstructor(ConstructorInstance ci) {
176         ClassType ct = (ClassType) substType(ci.container());
177
178         List formalTypes = ci.formalTypes();
179         formalTypes = substTypeList(formalTypes);
180
181         List throwTypes = ci.throwTypes();
182         throwTypes = substTypeList(throwTypes);
183
184         return (ConstructorInstance) ci.formalTypes(formalTypes).throwTypes(throwTypes).container(ct);
185     }
186
187     /** Perform substititions on a list of <code>Type</code>. */
188     public List substTypeList(List list) {
189         return new CachingTransformingList(list, new TypeXform());
190     }
191
192     /** Perform substititions on a list of <code>MethodInstance</code>. */
193     public List substMethodList(List list) {
194         return new CachingTransformingList(list, new MethodXform());
195     }
196
197     /** Perform substititions on a list of <code>ConstructorInstance</code>. */
198     public List substConstructorList(List list) {
199         return new CachingTransformingList(list, new ConstructorXform());
200     }
201
202     /** Perform substititions on a list of <code>FieldInstance</code>. */
203     public List substFieldList(List list) {
204         return new CachingTransformingList(list, new FieldXform());
205     }
206
207     ////////////////////////////////////////////////////////////////
208
// Substitution machinery
209

210     /** Function object for transforming types. */
211     public class TypeXform implements Transformation {
212         public Object JavaDoc transform(Object JavaDoc o) {
213             if (! (o instanceof Type)) {
214                 throw new InternalCompilerError(o + " is not a type.");
215             }
216
217             return substType((Type) o);
218         }
219     }
220
221     /** Function object for transforming fields. */
222     public class FieldXform implements Transformation {
223         public Object JavaDoc transform(Object JavaDoc o) {
224             if (! (o instanceof FieldInstance)) {
225                 throw new InternalCompilerError(o + " is not a field.");
226             }
227
228             return substField((FieldInstance) o);
229         }
230     }
231
232     /** Function object for transforming methods. */
233     public class MethodXform implements Transformation {
234         public Object JavaDoc transform(Object JavaDoc o) {
235             if (! (o instanceof MethodInstance)) {
236                 throw new InternalCompilerError(o + " is not a method.");
237             }
238
239             return substMethod((MethodInstance) o);
240         }
241     }
242
243     /** Function object for transforming constructors. */
244     public class ConstructorXform implements Transformation {
245         public Object JavaDoc transform(Object JavaDoc o) {
246             if (! (o instanceof ConstructorInstance)) {
247                 throw new InternalCompilerError(o + " is not a constructor.");
248             }
249
250             return substConstructor((ConstructorInstance) o);
251         }
252     }
253
254     ////////////////////////////////////////////////////////////////
255
// Equality
256

257     public boolean equals(Object JavaDoc o) {
258         if (o instanceof Subst) {
259             return subst.equals(((Subst) o).substitutions());
260         }
261
262         return false;
263     }
264
265     public int hashCode() {
266         return subst.hashCode();
267     }
268
269     ////////////////////////////////////////////////////////////////
270
// Utility functions
271

272     public String JavaDoc toString() {
273         String JavaDoc str = "[";
274         for (Iterator iter = subst.keySet().iterator(); iter.hasNext(); ) {
275             Object JavaDoc key = iter.next();
276             str += "<" + key + ": " + subst.get(key) + ">";
277             if (iter.hasNext())
278                 str += ", ";
279         }
280         return str + "]";
281     }
282
283     private void writeObject(java.io.ObjectOutputStream JavaDoc out)
284     throws IOException JavaDoc
285     {
286         out.defaultWriteObject();
287     }
288
289     private void readObject(java.io.ObjectInputStream JavaDoc in)
290     throws IOException JavaDoc, ClassNotFoundException JavaDoc
291     {
292         if (in instanceof TypeInputStream) {
293             this.ts = (ParamTypeSystem) ((TypeInputStream) in).getTypeSystem();
294         }
295
296     this.cache = new HashMap();
297
298         in.defaultReadObject();
299     }
300
301 }
302
Popular Tags