KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > ast > Conditional_c


1 package polyglot.ext.jl.ast;
2
3 import polyglot.ast.*;
4 import polyglot.visit.*;
5 import polyglot.types.*;
6 import polyglot.util.*;
7 import java.util.*;
8
9 /**
10  * A <code>Conditional</code> is a representation of a Java ternary
11  * expression. That is, <code>(cond ? consequent : alternative)</code>.
12  */

13 public class Conditional_c extends Expr_c implements Conditional
14 {
15     protected Expr cond;
16     protected Expr consequent;
17     protected Expr alternative;
18
19     public Conditional_c(Position pos, Expr cond, Expr consequent, Expr alternative) {
20     super(pos);
21     this.cond = cond;
22     this.consequent = consequent;
23     this.alternative = alternative;
24     }
25
26     /** Get the precedence of the expression. */
27     public Precedence precedence() {
28     return Precedence.CONDITIONAL;
29     }
30
31     /** Get the conditional of the expression. */
32     public Expr cond() {
33     return this.cond;
34     }
35
36     /** Set the conditional of the expression. */
37     public Conditional cond(Expr cond) {
38     Conditional_c n = (Conditional_c) copy();
39     n.cond = cond;
40     return n;
41     }
42
43     /** Get the consequent of the expression. */
44     public Expr consequent() {
45     return this.consequent;
46     }
47
48     /** Set the consequent of the expression. */
49     public Conditional consequent(Expr consequent) {
50     Conditional_c n = (Conditional_c) copy();
51     n.consequent = consequent;
52     return n;
53     }
54
55     /** Get the alternative of the expression. */
56     public Expr alternative() {
57     return this.alternative;
58     }
59
60     /** Set the alternative of the expression. */
61     public Conditional alternative(Expr alternative) {
62     Conditional_c n = (Conditional_c) copy();
63     n.alternative = alternative;
64     return n;
65     }
66
67     /** Reconstruct the expression. */
68     protected Conditional_c reconstruct(Expr cond, Expr consequent, Expr alternative) {
69     if (cond != this.cond || consequent != this.consequent || alternative != this.alternative) {
70         Conditional_c n = (Conditional_c) copy();
71         n.cond = cond;
72         n.consequent = consequent;
73         n.alternative = alternative;
74         return n;
75     }
76
77     return this;
78     }
79
80     /** Visit the children of the expression. */
81     public Node visitChildren(NodeVisitor v) {
82     Expr cond = (Expr) visitChild(this.cond, v);
83     Expr consequent = (Expr) visitChild(this.consequent, v);
84     Expr alternative = (Expr) visitChild(this.alternative, v);
85     return reconstruct(cond, consequent, alternative);
86     }
87
88     /** Type check the expression. */
89     public Node typeCheck(TypeChecker tc) throws SemanticException {
90     TypeSystem ts = tc.typeSystem();
91
92     if (! ts.equals(cond.type(), ts.Boolean())) {
93          throw new SemanticException(
94          "Condition of ternary expression must be of type boolean.",
95          cond.position());
96     }
97
98     Expr e1 = consequent;
99     Expr e2 = alternative;
100     Type t1 = e1.type();
101     Type t2 = e2.type();
102
103     // From the JLS, section:
104
// If the second and third operands have the same type (which may be
105
// the null type), then that is the type of the conditional expression.
106
if (ts.equals(t1, t2)) {
107         return type(t1);
108     }
109
110     // Otherwise, if the second and third operands have numeric type, then
111
// there are several cases:
112
if (t1.isNumeric() && t2.isNumeric()) {
113         // - If one of the operands is of type byte and the other is of
114
// type short, then the type of the conditional expression is
115
// short.
116
if (t1.isByte() && t2.isShort() || t1.isShort() && t2.isByte()) {
117             return type(ts.Short());
118         }
119
120         // - If one of the operands is of type T where T is byte, short, or
121
// char, and the other operand is a constant expression of type int
122
// whose value is representable in type T, then the type of the
123
// conditional expression is T.
124

125             if (t1.isIntOrLess() &&
126                 t2.isInt() &&
127                 ts.numericConversionValid(t1, e2.constantValue())) {
128                 return type(t1);
129         }
130
131             if (t2.isIntOrLess() &&
132                 t1.isInt() &&
133                 ts.numericConversionValid(t2, e1.constantValue())) {
134                 return type(t2);
135         }
136
137         // - Otherwise, binary numeric promotion (§5.6.2) is applied to the
138
// operand types, and the type of the conditional expression is the
139
// promoted type of the second and third operands. Note that binary
140
// numeric promotion performs value set conversion (§5.1.8).
141
return type(ts.promote(t1, t2));
142     }
143
144     // If one of the second and third operands is of the null type and the
145
// type of the other is a reference type, then the type of the
146
// conditional expression is that reference type.
147
if (t1.isNull() && t2.isReference()) return type(t2);
148     if (t2.isNull() && t1.isReference()) return type(t1);
149
150     // If the second and third operands are of different reference types,
151
// then it must be possible to convert one of the types to the other
152
// type (call this latter type T) by assignment conversion (§5.2); the
153
// type of the conditional expression is T. It is a compile-time error
154
// if neither type is assignment compatible with the other type.
155

156     if (t1.isReference() && t2.isReference()) {
157         if (ts.isImplicitCastValid(t1, t2)) {
158         return type(t2);
159         }
160         if (ts.isImplicitCastValid(t2, t1)) {
161         return type(t1);
162         }
163     }
164
165     throw new SemanticException(
166         "Could not find a type for ternary conditional expression.",
167         position());
168     }
169
170     public Type childExpectedType(Expr child, AscriptionVisitor av) {
171         TypeSystem ts = av.typeSystem();
172
173         if (child == cond) {
174             return ts.Boolean();
175         }
176
177         if (child == consequent || child == alternative) {
178             return type();
179         }
180
181         return child.type();
182     }
183
184     public String JavaDoc toString() {
185     return cond + " ? " + consequent + " : " + alternative;
186     }
187
188     /** Write the expression to an output file. */
189     public void prettyPrint(CodeWriter w, PrettyPrinter tr)
190     {
191     printSubExpr(cond, false, w, tr);
192     w.write(" ? ");
193     printSubExpr(consequent, false, w, tr);
194     w.write(" : ");
195     printSubExpr(alternative, false, w, tr);
196     }
197
198     public Term entry() {
199         return cond.entry();
200     }
201
202     public List acceptCFG(CFGBuilder v, List succs) {
203         v.visitCFG(cond, FlowGraph.EDGE_KEY_TRUE, consequent.entry(),
204                          FlowGraph.EDGE_KEY_FALSE, alternative.entry());
205         v.visitCFG(consequent, this);
206         v.visitCFG(alternative, this);
207
208         return succs;
209     }
210     
211     public boolean isConstant() {
212     return cond.isConstant() && consequent.isConstant() && alternative.isConstant();
213     }
214
215     public Object JavaDoc constantValue() {
216         Object JavaDoc cond_ = cond.constantValue();
217         Object JavaDoc then_ = consequent.constantValue();
218         Object JavaDoc else_ = alternative.constantValue();
219
220         if (cond_ instanceof Boolean JavaDoc && then_ != null && else_ != null) {
221             boolean c = ((Boolean JavaDoc) cond_).booleanValue();
222             if (c) {
223                 return then_;
224             }
225             else {
226                 return else_;
227             }
228         }
229
230         return null;
231     }
232 }
233
Popular Tags