Source Code Cross Referenced for ConditionalExpression.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » compiler » ast » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.compiler.ast 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012:        import org.eclipse.jdt.internal.compiler.ASTVisitor;
013:        import org.eclipse.jdt.internal.compiler.impl.*;
014:        import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
015:        import org.eclipse.jdt.internal.compiler.codegen.*;
016:        import org.eclipse.jdt.internal.compiler.flow.*;
017:        import org.eclipse.jdt.internal.compiler.lookup.*;
018:
019:        public class ConditionalExpression extends OperatorExpression {
020:
021:            public Expression condition, valueIfTrue, valueIfFalse;
022:            public Constant optimizedBooleanConstant;
023:            public Constant optimizedIfTrueConstant;
024:            public Constant optimizedIfFalseConstant;
025:
026:            // for local variables table attributes
027:            int trueInitStateIndex = -1;
028:            int falseInitStateIndex = -1;
029:            int mergedInitStateIndex = -1;
030:
031:            public ConditionalExpression(Expression condition,
032:                    Expression valueIfTrue, Expression valueIfFalse) {
033:                this .condition = condition;
034:                this .valueIfTrue = valueIfTrue;
035:                this .valueIfFalse = valueIfFalse;
036:                sourceStart = condition.sourceStart;
037:                sourceEnd = valueIfFalse.sourceEnd;
038:            }
039:
040:            public FlowInfo analyseCode(BlockScope currentScope,
041:                    FlowContext flowContext, FlowInfo flowInfo) {
042:                Constant cst = this .condition.optimizedBooleanConstant();
043:                boolean isConditionOptimizedTrue = cst != Constant.NotAConstant
044:                        && cst.booleanValue() == true;
045:                boolean isConditionOptimizedFalse = cst != Constant.NotAConstant
046:                        && cst.booleanValue() == false;
047:
048:                int mode = flowInfo.reachMode();
049:                flowInfo = condition.analyseCode(currentScope, flowContext,
050:                        flowInfo, cst == Constant.NotAConstant);
051:
052:                // process the if-true part
053:                FlowInfo trueFlowInfo = flowInfo.initsWhenTrue().copy();
054:                if (isConditionOptimizedFalse) {
055:                    trueFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
056:                }
057:                trueInitStateIndex = currentScope.methodScope()
058:                        .recordInitializationStates(trueFlowInfo);
059:                trueFlowInfo = valueIfTrue.analyseCode(currentScope,
060:                        flowContext, trueFlowInfo);
061:
062:                // process the if-false part
063:                FlowInfo falseFlowInfo = flowInfo.initsWhenFalse().copy();
064:                if (isConditionOptimizedTrue) {
065:                    falseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
066:                }
067:                falseInitStateIndex = currentScope.methodScope()
068:                        .recordInitializationStates(falseFlowInfo);
069:                falseFlowInfo = valueIfFalse.analyseCode(currentScope,
070:                        flowContext, falseFlowInfo);
071:
072:                // merge if-true & if-false initializations
073:                FlowInfo mergedInfo;
074:                if (isConditionOptimizedTrue) {
075:                    mergedInfo = trueFlowInfo
076:                            .addPotentialInitializationsFrom(falseFlowInfo);
077:                } else if (isConditionOptimizedFalse) {
078:                    mergedInfo = falseFlowInfo
079:                            .addPotentialInitializationsFrom(trueFlowInfo);
080:                } else {
081:                    // if ((t && (v = t)) ? t : t && (v = f)) r = v;  -- ok
082:                    cst = this .optimizedIfTrueConstant;
083:                    boolean isValueIfTrueOptimizedTrue = cst != null
084:                            && cst != Constant.NotAConstant
085:                            && cst.booleanValue() == true;
086:                    boolean isValueIfTrueOptimizedFalse = cst != null
087:                            && cst != Constant.NotAConstant
088:                            && cst.booleanValue() == false;
089:
090:                    cst = this .optimizedIfFalseConstant;
091:                    boolean isValueIfFalseOptimizedTrue = cst != null
092:                            && cst != Constant.NotAConstant
093:                            && cst.booleanValue() == true;
094:                    boolean isValueIfFalseOptimizedFalse = cst != null
095:                            && cst != Constant.NotAConstant
096:                            && cst.booleanValue() == false;
097:
098:                    UnconditionalFlowInfo trueInfoWhenTrue = trueFlowInfo
099:                            .initsWhenTrue().unconditionalCopy();
100:                    UnconditionalFlowInfo falseInfoWhenTrue = falseFlowInfo
101:                            .initsWhenTrue().unconditionalCopy();
102:                    UnconditionalFlowInfo trueInfoWhenFalse = trueFlowInfo
103:                            .initsWhenFalse().unconditionalInits();
104:                    UnconditionalFlowInfo falseInfoWhenFalse = falseFlowInfo
105:                            .initsWhenFalse().unconditionalInits();
106:                    if (isValueIfTrueOptimizedFalse)
107:                        trueInfoWhenTrue.setReachMode(FlowInfo.UNREACHABLE);
108:                    if (isValueIfFalseOptimizedFalse)
109:                        falseInfoWhenTrue.setReachMode(FlowInfo.UNREACHABLE);
110:                    if (isValueIfTrueOptimizedTrue)
111:                        trueInfoWhenFalse.setReachMode(FlowInfo.UNREACHABLE);
112:                    if (isValueIfFalseOptimizedTrue)
113:                        falseInfoWhenFalse.setReachMode(FlowInfo.UNREACHABLE);
114:
115:                    mergedInfo = FlowInfo.conditional(trueInfoWhenTrue
116:                            .mergedWith(falseInfoWhenTrue), trueInfoWhenFalse
117:                            .mergedWith(falseInfoWhenFalse));
118:                }
119:                mergedInitStateIndex = currentScope.methodScope()
120:                        .recordInitializationStates(mergedInfo);
121:                mergedInfo.setReachMode(mode);
122:                return mergedInfo;
123:            }
124:
125:            /**
126:             * Code generation for the conditional operator ?:
127:             *
128:             * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
129:             * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
130:             * @param valueRequired boolean
131:             */
132:            public void generateCode(BlockScope currentScope,
133:                    CodeStream codeStream, boolean valueRequired) {
134:
135:                int pc = codeStream.position;
136:                BranchLabel endifLabel, falseLabel;
137:                if (constant != Constant.NotAConstant) {
138:                    if (valueRequired)
139:                        codeStream.generateConstant(constant,
140:                                implicitConversion);
141:                    codeStream.recordPositionsFrom(pc, this .sourceStart);
142:                    return;
143:                }
144:                Constant cst = condition.optimizedBooleanConstant();
145:                boolean needTruePart = !(cst != Constant.NotAConstant && cst
146:                        .booleanValue() == false);
147:                boolean needFalsePart = !(cst != Constant.NotAConstant && cst
148:                        .booleanValue() == true);
149:                endifLabel = new BranchLabel(codeStream);
150:
151:                // Generate code for the condition
152:                falseLabel = new BranchLabel(codeStream);
153:                falseLabel.tagBits |= BranchLabel.USED;
154:                condition.generateOptimizedBoolean(currentScope, codeStream,
155:                        null, falseLabel, cst == Constant.NotAConstant);
156:
157:                if (trueInitStateIndex != -1) {
158:                    codeStream.removeNotDefinitelyAssignedVariables(
159:                            currentScope, trueInitStateIndex);
160:                    codeStream.addDefinitelyAssignedVariables(currentScope,
161:                            trueInitStateIndex);
162:                }
163:                // Then code generation
164:                if (needTruePart) {
165:                    valueIfTrue.generateCode(currentScope, codeStream,
166:                            valueRequired);
167:                    if (needFalsePart) {
168:                        // Jump over the else part
169:                        int position = codeStream.position;
170:                        codeStream.goto_(endifLabel);
171:                        codeStream.updateLastRecordedEndPC(currentScope,
172:                                position);
173:                        // Tune codestream stack size
174:                        if (valueRequired) {
175:                            codeStream
176:                                    .decrStackSize(this .resolvedType == TypeBinding.LONG
177:                                            || this .resolvedType == TypeBinding.DOUBLE ? 2
178:                                            : 1);
179:                        }
180:                    }
181:                }
182:                if (needFalsePart) {
183:                    if (falseInitStateIndex != -1) {
184:                        codeStream.removeNotDefinitelyAssignedVariables(
185:                                currentScope, falseInitStateIndex);
186:                        codeStream.addDefinitelyAssignedVariables(currentScope,
187:                                falseInitStateIndex);
188:                    }
189:                    if (falseLabel.forwardReferenceCount() > 0) {
190:                        falseLabel.place();
191:                    }
192:                    valueIfFalse.generateCode(currentScope, codeStream,
193:                            valueRequired);
194:                    if (valueRequired) {
195:                        codeStream.recordExpressionType(this .resolvedType);
196:                    }
197:                    if (needTruePart) {
198:                        // End of if statement
199:                        endifLabel.place();
200:                    }
201:                }
202:                // May loose some local variable initializations : affecting the local variable attributes
203:                if (mergedInitStateIndex != -1) {
204:                    codeStream.removeNotDefinitelyAssignedVariables(
205:                            currentScope, mergedInitStateIndex);
206:                }
207:                // implicit conversion
208:                if (valueRequired)
209:                    codeStream.generateImplicitConversion(implicitConversion);
210:                codeStream.recordPositionsFrom(pc, this .sourceStart);
211:            }
212:
213:            /**
214:             * Optimized boolean code generation for the conditional operator ?:
215:             */
216:            public void generateOptimizedBoolean(BlockScope currentScope,
217:                    CodeStream codeStream, BranchLabel trueLabel,
218:                    BranchLabel falseLabel, boolean valueRequired) {
219:
220:                if ((constant != Constant.NotAConstant)
221:                        && (constant.typeID() == T_boolean) // constant
222:                        || ((valueIfTrue.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_boolean) { // non boolean values
223:                    super .generateOptimizedBoolean(currentScope, codeStream,
224:                            trueLabel, falseLabel, valueRequired);
225:                    return;
226:                }
227:                Constant cst = condition.constant;
228:                Constant condCst = condition.optimizedBooleanConstant();
229:                boolean needTruePart = !(((cst != Constant.NotAConstant) && (cst
230:                        .booleanValue() == false)) || ((condCst != Constant.NotAConstant) && (condCst
231:                        .booleanValue() == false)));
232:                boolean needFalsePart = !(((cst != Constant.NotAConstant) && (cst
233:                        .booleanValue() == true)) || ((condCst != Constant.NotAConstant) && (condCst
234:                        .booleanValue() == true)));
235:
236:                BranchLabel internalFalseLabel, endifLabel = new BranchLabel(
237:                        codeStream);
238:
239:                // Generate code for the condition
240:                boolean needConditionValue = (cst == Constant.NotAConstant)
241:                        && (condCst == Constant.NotAConstant);
242:                condition.generateOptimizedBoolean(currentScope, codeStream,
243:                        null, internalFalseLabel = new BranchLabel(codeStream),
244:                        needConditionValue);
245:
246:                if (trueInitStateIndex != -1) {
247:                    codeStream.removeNotDefinitelyAssignedVariables(
248:                            currentScope, trueInitStateIndex);
249:                    codeStream.addDefinitelyAssignedVariables(currentScope,
250:                            trueInitStateIndex);
251:                }
252:                // Then code generation
253:                if (needTruePart) {
254:                    valueIfTrue.generateOptimizedBoolean(currentScope,
255:                            codeStream, trueLabel, falseLabel, valueRequired);
256:
257:                    if (needFalsePart) {
258:                        // Jump over the else part
259:                        JumpEndif: {
260:                            if (falseLabel == null) {
261:                                if (trueLabel != null) {
262:                                    // implicit falling through the FALSE case
263:                                    cst = this .optimizedIfTrueConstant;
264:                                    boolean isValueIfTrueOptimizedTrue = cst != null
265:                                            && cst != Constant.NotAConstant
266:                                            && cst.booleanValue() == true;
267:                                    if (isValueIfTrueOptimizedTrue)
268:                                        break JumpEndif; // no need to jump over, since branched to true already
269:                                }
270:                            } else {
271:                                // implicit falling through the TRUE case
272:                                if (trueLabel == null) {
273:                                    cst = this .optimizedIfTrueConstant;
274:                                    boolean isValueIfTrueOptimizedFalse = cst != null
275:                                            && cst != Constant.NotAConstant
276:                                            && cst.booleanValue() == false;
277:                                    if (isValueIfTrueOptimizedFalse)
278:                                        break JumpEndif; // no need to jump over, since branched to false already
279:                                } else {
280:                                    // no implicit fall through TRUE/FALSE --> should never occur
281:                                }
282:                            }
283:                            int position = codeStream.position;
284:                            codeStream.goto_(endifLabel);
285:                            codeStream.updateLastRecordedEndPC(currentScope,
286:                                    position);
287:                        }
288:                        // No need to decrement codestream stack size
289:                        // since valueIfTrue was already consumed by branch bytecode
290:                    }
291:                }
292:                if (needFalsePart) {
293:                    internalFalseLabel.place();
294:                    if (falseInitStateIndex != -1) {
295:                        codeStream.removeNotDefinitelyAssignedVariables(
296:                                currentScope, falseInitStateIndex);
297:                        codeStream.addDefinitelyAssignedVariables(currentScope,
298:                                falseInitStateIndex);
299:                    }
300:                    valueIfFalse.generateOptimizedBoolean(currentScope,
301:                            codeStream, trueLabel, falseLabel, valueRequired);
302:
303:                    // End of if statement
304:                    endifLabel.place();
305:                }
306:                // May loose some local variable initializations : affecting the local variable attributes
307:                if (mergedInitStateIndex != -1) {
308:                    codeStream.removeNotDefinitelyAssignedVariables(
309:                            currentScope, mergedInitStateIndex);
310:                }
311:                // no implicit conversion for boolean values
312:                codeStream.updateLastRecordedEndPC(currentScope,
313:                        codeStream.position);
314:            }
315:
316:            public int nullStatus(FlowInfo flowInfo) {
317:                Constant cst = this .condition.optimizedBooleanConstant();
318:                if (cst != Constant.NotAConstant) {
319:                    if (cst.booleanValue()) {
320:                        return valueIfTrue.nullStatus(flowInfo);
321:                    }
322:                    return valueIfFalse.nullStatus(flowInfo);
323:                }
324:                int ifTrueNullStatus = valueIfTrue.nullStatus(flowInfo), ifFalseNullStatus = valueIfFalse
325:                        .nullStatus(flowInfo);
326:                if (ifTrueNullStatus == ifFalseNullStatus) {
327:                    return ifTrueNullStatus;
328:                }
329:                return FlowInfo.UNKNOWN;
330:                // cannot decide which branch to take, and they disagree
331:            }
332:
333:            public Constant optimizedBooleanConstant() {
334:
335:                return this .optimizedBooleanConstant == null ? this .constant
336:                        : this .optimizedBooleanConstant;
337:            }
338:
339:            public StringBuffer printExpressionNoParenthesis(int indent,
340:                    StringBuffer output) {
341:
342:                condition.printExpression(indent, output).append(" ? "); //$NON-NLS-1$
343:                valueIfTrue.printExpression(0, output).append(" : "); //$NON-NLS-1$
344:                return valueIfFalse.printExpression(0, output);
345:            }
346:
347:            public TypeBinding resolveType(BlockScope scope) {
348:                // JLS3 15.25
349:                constant = Constant.NotAConstant;
350:                LookupEnvironment env = scope.environment();
351:                boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
352:                TypeBinding conditionType = condition.resolveTypeExpecting(
353:                        scope, TypeBinding.BOOLEAN);
354:                condition.computeConversion(scope, TypeBinding.BOOLEAN,
355:                        conditionType);
356:
357:                if (valueIfTrue instanceof  CastExpression)
358:                    valueIfTrue.bits |= DisableUnnecessaryCastCheck; // will check later on
359:                TypeBinding originalValueIfTrueType = valueIfTrue
360:                        .resolveType(scope);
361:
362:                if (valueIfFalse instanceof  CastExpression)
363:                    valueIfFalse.bits |= DisableUnnecessaryCastCheck; // will check later on
364:                TypeBinding originalValueIfFalseType = valueIfFalse
365:                        .resolveType(scope);
366:
367:                if (conditionType == null || originalValueIfTrueType == null
368:                        || originalValueIfFalseType == null)
369:                    return null;
370:
371:                TypeBinding valueIfTrueType = originalValueIfTrueType;
372:                TypeBinding valueIfFalseType = originalValueIfFalseType;
373:                if (use15specifics && valueIfTrueType != valueIfFalseType) {
374:                    if (valueIfTrueType.isBaseType()) {
375:                        if (valueIfFalseType.isBaseType()) {
376:                            // bool ? baseType : baseType
377:                            if (valueIfTrueType == TypeBinding.NULL) { // bool ? null : 12 --> Integer
378:                                valueIfFalseType = env
379:                                        .computeBoxingType(valueIfFalseType); // boxing
380:                            } else if (valueIfFalseType == TypeBinding.NULL) { // bool ? 12 : null --> Integer
381:                                valueIfTrueType = env
382:                                        .computeBoxingType(valueIfTrueType); // boxing
383:                            }
384:                        } else {
385:                            // bool ? baseType : nonBaseType
386:                            TypeBinding unboxedIfFalseType = valueIfFalseType
387:                                    .isBaseType() ? valueIfFalseType : env
388:                                    .computeBoxingType(valueIfFalseType);
389:                            if (valueIfTrueType.isNumericType()
390:                                    && unboxedIfFalseType.isNumericType()) {
391:                                valueIfFalseType = unboxedIfFalseType; // unboxing
392:                            } else if (valueIfTrueType != TypeBinding.NULL) { // bool ? 12 : new Integer(12) --> int
393:                                valueIfFalseType = env
394:                                        .computeBoxingType(valueIfFalseType); // unboxing
395:                            }
396:                        }
397:                    } else if (valueIfFalseType.isBaseType()) {
398:                        // bool ? nonBaseType : baseType
399:                        TypeBinding unboxedIfTrueType = valueIfTrueType
400:                                .isBaseType() ? valueIfTrueType : env
401:                                .computeBoxingType(valueIfTrueType);
402:                        if (unboxedIfTrueType.isNumericType()
403:                                && valueIfFalseType.isNumericType()) {
404:                            valueIfTrueType = unboxedIfTrueType; // unboxing
405:                        } else if (valueIfFalseType != TypeBinding.NULL) { // bool ? new Integer(12) : 12 --> int
406:                            valueIfTrueType = env
407:                                    .computeBoxingType(valueIfTrueType); // unboxing
408:                        }
409:                    } else {
410:                        // bool ? nonBaseType : nonBaseType
411:                        TypeBinding unboxedIfTrueType = env
412:                                .computeBoxingType(valueIfTrueType);
413:                        TypeBinding unboxedIfFalseType = env
414:                                .computeBoxingType(valueIfFalseType);
415:                        if (unboxedIfTrueType.isNumericType()
416:                                && unboxedIfFalseType.isNumericType()) {
417:                            valueIfTrueType = unboxedIfTrueType;
418:                            valueIfFalseType = unboxedIfFalseType;
419:                        }
420:                    }
421:                }
422:                // Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
423:                Constant condConstant, trueConstant, falseConstant;
424:                if ((condConstant = condition.constant) != Constant.NotAConstant
425:                        && (trueConstant = valueIfTrue.constant) != Constant.NotAConstant
426:                        && (falseConstant = valueIfFalse.constant) != Constant.NotAConstant) {
427:                    // all terms are constant expression so we can propagate the constant
428:                    // from valueIFTrue or valueIfFalse to the receiver constant
429:                    constant = condConstant.booleanValue() ? trueConstant
430:                            : falseConstant;
431:                }
432:                if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion 
433:                    valueIfTrue.computeConversion(scope, valueIfTrueType,
434:                            originalValueIfTrueType);
435:                    valueIfFalse.computeConversion(scope, valueIfFalseType,
436:                            originalValueIfFalseType);
437:                    if (valueIfTrueType == TypeBinding.BOOLEAN) {
438:                        this .optimizedIfTrueConstant = valueIfTrue
439:                                .optimizedBooleanConstant();
440:                        this .optimizedIfFalseConstant = valueIfFalse
441:                                .optimizedBooleanConstant();
442:                        if (this .optimizedIfTrueConstant != Constant.NotAConstant
443:                                && this .optimizedIfFalseConstant != Constant.NotAConstant
444:                                && this .optimizedIfTrueConstant.booleanValue() == this .optimizedIfFalseConstant
445:                                        .booleanValue()) {
446:                            // a ? true : true  /   a ? false : false
447:                            this .optimizedBooleanConstant = optimizedIfTrueConstant;
448:                        } else if ((condConstant = condition
449:                                .optimizedBooleanConstant()) != Constant.NotAConstant) { // Propagate the optimized boolean constant if possible
450:                            this .optimizedBooleanConstant = condConstant
451:                                    .booleanValue() ? this .optimizedIfTrueConstant
452:                                    : this .optimizedIfFalseConstant;
453:                        }
454:                    }
455:                    return this .resolvedType = valueIfTrueType;
456:                }
457:                // Determine the return type depending on argument types
458:                // Numeric types
459:                if (valueIfTrueType.isNumericType()
460:                        && valueIfFalseType.isNumericType()) {
461:                    // (Short x Byte) or (Byte x Short)"
462:                    if ((valueIfTrueType == TypeBinding.BYTE && valueIfFalseType == TypeBinding.SHORT)
463:                            || (valueIfTrueType == TypeBinding.SHORT && valueIfFalseType == TypeBinding.BYTE)) {
464:                        valueIfTrue.computeConversion(scope, TypeBinding.SHORT,
465:                                originalValueIfTrueType);
466:                        valueIfFalse.computeConversion(scope,
467:                                TypeBinding.SHORT, originalValueIfFalseType);
468:                        return this .resolvedType = TypeBinding.SHORT;
469:                    }
470:                    // <Byte|Short|Char> x constant(Int)  ---> <Byte|Short|Char>   and reciprocally
471:                    if ((valueIfTrueType == TypeBinding.BYTE
472:                            || valueIfTrueType == TypeBinding.SHORT || valueIfTrueType == TypeBinding.CHAR)
473:                            && (valueIfFalseType == TypeBinding.INT && valueIfFalse
474:                                    .isConstantValueOfTypeAssignableToType(
475:                                            valueIfFalseType, valueIfTrueType))) {
476:                        valueIfTrue.computeConversion(scope, valueIfTrueType,
477:                                originalValueIfTrueType);
478:                        valueIfFalse.computeConversion(scope, valueIfTrueType,
479:                                originalValueIfFalseType);
480:                        return this .resolvedType = valueIfTrueType;
481:                    }
482:                    if ((valueIfFalseType == TypeBinding.BYTE
483:                            || valueIfFalseType == TypeBinding.SHORT || valueIfFalseType == TypeBinding.CHAR)
484:                            && (valueIfTrueType == TypeBinding.INT && valueIfTrue
485:                                    .isConstantValueOfTypeAssignableToType(
486:                                            valueIfTrueType, valueIfFalseType))) {
487:                        valueIfTrue.computeConversion(scope, valueIfFalseType,
488:                                originalValueIfTrueType);
489:                        valueIfFalse.computeConversion(scope, valueIfFalseType,
490:                                originalValueIfFalseType);
491:                        return this .resolvedType = valueIfFalseType;
492:                    }
493:                    // Manual binary numeric promotion
494:                    // int
495:                    if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_int)
496:                            && BaseTypeBinding.isNarrowing(valueIfFalseType.id,
497:                                    T_int)) {
498:                        valueIfTrue.computeConversion(scope, TypeBinding.INT,
499:                                originalValueIfTrueType);
500:                        valueIfFalse.computeConversion(scope, TypeBinding.INT,
501:                                originalValueIfFalseType);
502:                        return this .resolvedType = TypeBinding.INT;
503:                    }
504:                    // long
505:                    if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long)
506:                            && BaseTypeBinding.isNarrowing(valueIfFalseType.id,
507:                                    T_long)) {
508:                        valueIfTrue.computeConversion(scope, TypeBinding.LONG,
509:                                originalValueIfTrueType);
510:                        valueIfFalse.computeConversion(scope, TypeBinding.LONG,
511:                                originalValueIfFalseType);
512:                        return this .resolvedType = TypeBinding.LONG;
513:                    }
514:                    // float
515:                    if (BaseTypeBinding
516:                            .isNarrowing(valueIfTrueType.id, T_float)
517:                            && BaseTypeBinding.isNarrowing(valueIfFalseType.id,
518:                                    T_float)) {
519:                        valueIfTrue.computeConversion(scope, TypeBinding.FLOAT,
520:                                originalValueIfTrueType);
521:                        valueIfFalse.computeConversion(scope,
522:                                TypeBinding.FLOAT, originalValueIfFalseType);
523:                        return this .resolvedType = TypeBinding.FLOAT;
524:                    }
525:                    // double
526:                    valueIfTrue.computeConversion(scope, TypeBinding.DOUBLE,
527:                            originalValueIfTrueType);
528:                    valueIfFalse.computeConversion(scope, TypeBinding.DOUBLE,
529:                            originalValueIfFalseType);
530:                    return this .resolvedType = TypeBinding.DOUBLE;
531:                }
532:                // Type references (null null is already tested)
533:                if (valueIfTrueType.isBaseType()
534:                        && valueIfTrueType != TypeBinding.NULL) {
535:                    if (use15specifics) {
536:                        valueIfTrueType = env
537:                                .computeBoxingType(valueIfTrueType);
538:                    } else {
539:                        scope.problemReporter()
540:                                .conditionalArgumentsIncompatibleTypes(this ,
541:                                        valueIfTrueType, valueIfFalseType);
542:                        return null;
543:                    }
544:                }
545:                if (valueIfFalseType.isBaseType()
546:                        && valueIfFalseType != TypeBinding.NULL) {
547:                    if (use15specifics) {
548:                        valueIfFalseType = env
549:                                .computeBoxingType(valueIfFalseType);
550:                    } else {
551:                        scope.problemReporter()
552:                                .conditionalArgumentsIncompatibleTypes(this ,
553:                                        valueIfTrueType, valueIfFalseType);
554:                        return null;
555:                    }
556:                }
557:                if (use15specifics) {
558:                    // >= 1.5 : LUB(operand types) must exist
559:                    TypeBinding commonType = null;
560:                    if (valueIfTrueType == TypeBinding.NULL) {
561:                        commonType = valueIfFalseType;
562:                    } else if (valueIfFalseType == TypeBinding.NULL) {
563:                        commonType = valueIfTrueType;
564:                    } else {
565:                        commonType = scope.lowerUpperBound(new TypeBinding[] {
566:                                valueIfTrueType, valueIfFalseType });
567:                    }
568:                    if (commonType != null) {
569:                        valueIfTrue.computeConversion(scope, commonType,
570:                                originalValueIfTrueType);
571:                        valueIfFalse.computeConversion(scope, commonType,
572:                                originalValueIfFalseType);
573:                        return this .resolvedType = commonType.capture(scope,
574:                                this .sourceEnd);
575:                    }
576:                } else {
577:                    // < 1.5 : one operand must be convertible to the other
578:                    if (valueIfFalseType.isCompatibleWith(valueIfTrueType)) {
579:                        valueIfTrue.computeConversion(scope, valueIfTrueType,
580:                                originalValueIfTrueType);
581:                        valueIfFalse.computeConversion(scope, valueIfTrueType,
582:                                originalValueIfFalseType);
583:                        return this .resolvedType = valueIfTrueType;
584:                    } else if (valueIfTrueType
585:                            .isCompatibleWith(valueIfFalseType)) {
586:                        valueIfTrue.computeConversion(scope, valueIfFalseType,
587:                                originalValueIfTrueType);
588:                        valueIfFalse.computeConversion(scope, valueIfFalseType,
589:                                originalValueIfFalseType);
590:                        return this .resolvedType = valueIfFalseType;
591:                    }
592:                }
593:                scope.problemReporter().conditionalArgumentsIncompatibleTypes(
594:                        this , valueIfTrueType, valueIfFalseType);
595:                return null;
596:            }
597:
598:            public void traverse(ASTVisitor visitor, BlockScope scope) {
599:                if (visitor.visit(this, scope)) {
600:                    condition.traverse(visitor, scope);
601:                    valueIfTrue.traverse(visitor, scope);
602:                    valueIfFalse.traverse(visitor, scope);
603:                }
604:                visitor.endVisit(this, scope);
605:            }
606:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.