KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > flow > FlowInfo


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.flow;
12
13 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
14 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
15
16 public abstract class FlowInfo {
17
18     public int tagBits; // REACHABLE by default
19
public final static int REACHABLE = 0;
20     public final static int UNREACHABLE = 1;
21     public final static int NULL_FLAG_MASK = 2;
22     
23     public final static int UNKNOWN = 0;
24     public final static int NULL = 1;
25     public final static int NON_NULL = -1;
26     
27     public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
28
static {
29         DEAD_END = new UnconditionalFlowInfo();
30         DEAD_END.tagBits = UNREACHABLE;
31     }
32
33 /**
34  * Add other inits to this flow info, then return this. The operation semantics
35  * are to match as closely as possible the application to this flow info of all
36  * the operations that resulted into otherInits.
37  * @param otherInits other inits to add to this
38  * @return this, modified according to otherInits information
39  */

40 abstract public FlowInfo addInitializationsFrom(FlowInfo otherInits);
41
42
43 /**
44  * Compose other inits over this flow info, then return this. The operation
45  * semantics are to wave into this flow info the consequences of a possible
46  * path into the operations that resulted into otherInits. The fact that this
47  * path may be left unexecuted under peculiar conditions results into less
48  * specific results than {@link #addInitializationsFrom(FlowInfo)
49  * addInitializationsFrom}.
50  * @param otherInits other inits to compose over this
51  * @return this, modified according to otherInits information
52  */

53 abstract public FlowInfo addPotentialInitializationsFrom(FlowInfo otherInits);
54
55     public FlowInfo asNegatedCondition() {
56
57         return this;
58     }
59
60     public static FlowInfo conditional(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){
61
62         // if (initsWhenTrue.equals(initsWhenFalse)) return initsWhenTrue; -- could optimize if #equals is defined
63
return new ConditionalFlowInfo(initsWhenTrue, initsWhenFalse);
64     }
65     
66 /**
67  * Check whether a given local variable is known to be unable to gain a definite
68  * non null or definite null status by the use of an enclosing flow info. The
69  * semantics are that if the current flow info marks the variable as potentially
70  * unknown or else as being both potentially null and potentially non null,
71  * then it won't ever be promoted as definitely null or definitely non null. (It
72  * could still get promoted to definite unknown).
73  * @param local the variable to ckeck
74  * @return true iff this flow info prevents local from being promoted to
75  * definite non null or definite null against an enclosing flow info
76  */

77 public boolean cannotBeDefinitelyNullOrNonNull(LocalVariableBinding local) {
78     return isPotentiallyUnknown(local) ||
79         isPotentiallyNonNull(local) && isPotentiallyNull(local);
80 }
81
82 /**
83  * Check whether a given local variable is known to be non null, either because
84  * it is definitely non null, or because is has been tested against non null.
85  * @param local the variable to ckeck
86  * @return true iff local cannot be null for this flow info
87  */

88 public boolean cannotBeNull(LocalVariableBinding local) {
89     return isDefinitelyNonNull(local) || isProtectedNonNull(local);
90 }
91
92 /**
93  * Check whether a given local variable is known to be null, either because it
94  * is definitely null, or because is has been tested against null.
95  * @param local the variable to ckeck
96  * @return true iff local can only be null for this flow info
97  */

98 public boolean canOnlyBeNull(LocalVariableBinding local) {
99     return isDefinitelyNull(local) || isProtectedNull(local);
100 }
101
102 /**
103  * Return a deep copy of the current instance.
104  * @return a deep copy of this flow info
105  */

106     abstract public FlowInfo copy();
107
108     public static UnconditionalFlowInfo initial(int maxFieldCount) {
109         UnconditionalFlowInfo info = new UnconditionalFlowInfo();
110         info.maxFieldCount = maxFieldCount;
111         return info;
112     }
113     
114 /**
115  * Return the flow info that would result from the path associated to the
116  * value false for the condition expression that generated this flow info.
117  * May be this flow info if it is not an instance of {@link
118  * ConditionalFlowInfo}. May have a side effect on subparts of this flow
119  * info (subtrees get merged).
120  * @return the flow info associated to the false branch of the condition
121  * that generated this flow info
122  */

123 abstract public FlowInfo initsWhenFalse();
124
125 /**
126  * Return the flow info that would result from the path associated to the
127  * value true for the condition expression that generated this flow info.
128  * May be this flow info if it is not an instance of {@link
129  * ConditionalFlowInfo}. May have a side effect on subparts of this flow
130  * info (subtrees get merged).
131  * @return the flow info associated to the true branch of the condition
132  * that generated this flow info
133  */

134     abstract public FlowInfo initsWhenTrue();
135
136     /**
137      * Check status of definite assignment for a field.
138      */

139      abstract public boolean isDefinitelyAssigned(FieldBinding field);
140
141     /**
142      * Check status of definite assignment for a local.
143      */

144     public abstract boolean isDefinitelyAssigned(LocalVariableBinding local);
145
146 /**
147  * Check status of definite non-null value for a given local variable.
148  * @param local the variable to ckeck
149  * @return true iff local is definitely non null for this flow info
150  */

151     public abstract boolean isDefinitelyNonNull(LocalVariableBinding local);
152
153 /**
154  * Check status of definite null value for a given local variable.
155  * @param local the variable to ckeck
156  * @return true iff local is definitely null for this flow info
157  */

158 public abstract boolean isDefinitelyNull(LocalVariableBinding local);
159
160 /**
161  * Check status of definite unknown value for a given local variable.
162  * @param local the variable to ckeck
163  * @return true iff local is definitely unknown for this flow info
164  */

165 public abstract boolean isDefinitelyUnknown(LocalVariableBinding local);
166
167     /**
168      * Check status of potential assignment for a field.
169      */

170      abstract public boolean isPotentiallyAssigned(FieldBinding field);
171
172     /**
173      * Check status of potential assignment for a local variable.
174      */

175
176      abstract public boolean isPotentiallyAssigned(LocalVariableBinding field);
177
178 /**
179  * Check status of potential null assignment for a local. Return true if there
180  * is a reasonable expectation that the variable be non null at this point.
181  * @param local LocalVariableBinding - the binding for the checked local
182  * @return true if there is a reasonable expectation that local be non null at
183  * this point
184  */

185 public abstract boolean isPotentiallyNonNull(LocalVariableBinding local);
186     
187 /**
188  * Check status of potential null assignment for a local. Return true if there
189  * is a reasonable expectation that the variable be null at this point. This
190  * includes the protected null case, so as to augment diagnostics, but does not
191  * really check that someone deliberately assigned to null on any specific
192  * path
193  * @param local LocalVariableBinding - the binding for the checked local
194  * @return true if there is a reasonable expectation that local be null at
195  * this point
196  */

197 public abstract boolean isPotentiallyNull(LocalVariableBinding local);
198     
199 /**
200  * Return true if the given local may have been assigned to an unknown value.
201  * @param local the local to check
202  * @return true if the given local may have been assigned to an unknown value
203  */

204 public abstract boolean isPotentiallyUnknown(LocalVariableBinding local);
205
206 /**
207  * Return true if the given local is protected by a test against a non null
208  * value.
209  * @param local the local to check
210  * @return true if the given local is protected by a test against a non null
211  */

212 public abstract boolean isProtectedNonNull(LocalVariableBinding local);
213
214 /**
215  * Return true if the given local is protected by a test against null.
216  * @param local the local to check
217  * @return true if the given local is protected by a test against null
218  */

219 public abstract boolean isProtectedNull(LocalVariableBinding local);
220
221 /**
222  * Record that a local variable got checked to be non null.
223  * @param local the checked local variable
224  */

225 abstract public void markAsComparedEqualToNonNull(LocalVariableBinding local);
226     
227 /**
228  * Record that a local variable got checked to be null.
229  * @param local the checked local variable
230  */

231 abstract public void markAsComparedEqualToNull(LocalVariableBinding local);
232     
233     /**
234      * Record a field got definitely assigned.
235      */

236     abstract public void markAsDefinitelyAssigned(FieldBinding field);
237
238     /**
239      * Record a local got definitely assigned to a non-null value.
240      */

241     abstract public void markAsDefinitelyNonNull(LocalVariableBinding local);
242
243     /**
244      * Record a local got definitely assigned to null.
245      */

246     abstract public void markAsDefinitelyNull(LocalVariableBinding local);
247
248     /**
249      * Record a local got definitely assigned.
250      */

251     abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
252
253 /**
254  * Record a local got definitely assigned to an unknown value.
255  */

256 abstract public void markAsDefinitelyUnknown(LocalVariableBinding local);
257
258 /**
259  * Merge branches using optimized boolean conditions
260  */

261 public static UnconditionalFlowInfo mergedOptimizedBranches(
262         FlowInfo initsWhenTrue, boolean isOptimizedTrue,
263         FlowInfo initsWhenFalse, boolean isOptimizedFalse,
264         boolean allowFakeDeadBranch) {
265     UnconditionalFlowInfo mergedInfo;
266     if (isOptimizedTrue){
267         if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) {
268             mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE).
269                 unconditionalInits();
270         }
271         else {
272             mergedInfo =
273                 initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse.
274                     nullInfoLessUnconditionalCopy()).
275                 unconditionalInits();
276         }
277     }
278     else if (isOptimizedFalse) {
279         if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) {
280             mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE).
281                 unconditionalInits();
282         }
283         else {
284             mergedInfo =
285                 initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue.
286                     nullInfoLessUnconditionalCopy()).
287                 unconditionalInits();
288         }
289     }
290     else {
291         mergedInfo = initsWhenTrue.
292             mergedWith(initsWhenFalse.unconditionalInits());
293     }
294     return mergedInfo;
295 }
296     
297 /**
298  * Return REACHABLE if this flow info is reachable, UNREACHABLE
299  * else.
300  * @return REACHABLE if this flow info is reachable, UNREACHABLE
301  * else
302  */

303 public int reachMode() {
304     return this.tagBits & UNREACHABLE;
305 }
306     
307 /**
308  * Return a flow info that carries the same information as the result of
309  * {@link #initsWhenTrue() initsWhenTrue}, but warrantied to be different
310  * from this.<br>
311  * Caveat: side effects on the result may affect components of this.
312  * @return the result of initsWhenTrue or a copy of it
313  */

314 abstract public FlowInfo safeInitsWhenTrue();
315
316 /**
317  * Set this flow info reach mode and return this.
318  * @param reachMode one of {@link #REACHABLE REACHABLE} or {@link #UNREACHABLE UNREACHABLE}
319  * @return this, with the reach mode set to reachMode
320  */

321 abstract public FlowInfo setReachMode(int reachMode);
322
323 /**
324  * Return the intersection of this and otherInits, that is
325  * one of:<ul>
326  * <li>the receiver updated in the following way:<ul>
327  * <li>intersection of definitely assigned variables,
328  * <li>union of potentially assigned variables,
329  * <li>similar operations for null,</ul>
330  * <li>or the receiver or otherInits if the other one is non
331  * reachable.</ul>
332  * otherInits is not affected, and is not returned either (no
333  * need to protect the result).
334  * @param otherInits the flow info to merge with this
335  * @return the intersection of this and otherInits.
336  */

337 abstract public UnconditionalFlowInfo mergedWith(
338         UnconditionalFlowInfo otherInits);
339
340 /**
341  * Return a copy of this unconditional flow info, deprived from its null
342  * info. {@link #DEAD_END DEAD_END} is returned unmodified.
343  * @return a copy of this unconditional flow info deprived from its null info
344  */

345 abstract public UnconditionalFlowInfo nullInfoLessUnconditionalCopy();
346
347     public String JavaDoc toString(){
348
349         if (this == DEAD_END){
350             return "FlowInfo.DEAD_END"; //$NON-NLS-1$
351
}
352         return super.toString();
353     }
354
355 /**
356  * Return a new flow info that holds the same information as this would after
357  * a call to unconditionalInits, but leaving this info unaffected. Moreover,
358  * the result can be modified without affecting this.
359  * @return a new flow info carrying this unconditional flow info
360  */

361 abstract public UnconditionalFlowInfo unconditionalCopy();
362
363 /**
364  * Return a new flow info that holds the same information as this would after
365  * a call to {@link #unconditionalInits() unconditionalInits} followed by the
366  * erasure of fields specific information, but leaving this flow info unaffected.
367  * @return a new flow info carrying the unconditional flow info for local variables
368  */

369 abstract public UnconditionalFlowInfo unconditionalFieldLessCopy();
370
371 /**
372  * Return a flow info that merges the possible paths of execution described by
373  * this flow info. In case of an unconditional flow info, return this. In case
374  * of a conditional flow info, merge branches recursively. Caveat: this may
375  * be affected, and modifying the result may affect this.
376  * @return a flow info that merges the possible paths of execution described by
377  * this
378  */

379 abstract public UnconditionalFlowInfo unconditionalInits();
380
381 /**
382  * Return a new flow info that holds the same information as this would after
383  * a call to {@link #unconditionalInits() unconditionalInits}, but leaving
384  * this info unaffected. Side effects on the result might affect this though
385  * (consider it as read only).
386  * @return a flow info carrying this unconditional flow info
387  */

388 abstract public UnconditionalFlowInfo unconditionalInitsWithoutSideEffect();
389 }
390
Popular Tags