import org.eclipse.ui.internal.dialogs.ResourceSorter; replaced by import org.eclips...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / Assignment.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
20
21 public class Assignment extends Expression {
22
23         public Reference lhs;
24         public Expression expression;
25         public TypeBinding lhsType;
26         
27         public Assignment(Expression lhs, Expression expression, int sourceEnd) {
28                 //lhs is always a reference by construction ,
29                 //but is build as an expression ==> the checkcast cannot fail
30
31                 this.lhs = (Reference) lhs;
32                 this.expression = expression;
33
34                 this.sourceStart = lhs.sourceStart;
35                 this.sourceEnd = sourceEnd;
36         }
37
38         public FlowInfo analyseCode(
39                 BlockScope currentScope,
40                 FlowContext flowContext,
41                 FlowInfo flowInfo) {
42                 // record setting a variable: various scenarii are possible, setting an array reference, 
43                 // a field reference, a blank final field reference, a field of an enclosing instance or 
44                 // just a local variable.
45
46                 return lhs
47                         .analyseAssignment(currentScope, flowContext, flowInfo, this, false)
48                         .unconditionalInits();
49         }
50
51         public void generateCode(
52                 BlockScope currentScope,
53                 CodeStream codeStream,
54                 boolean valueRequired) {
55
56                 // various scenarii are possible, setting an array reference, 
57                 // a field reference, a blank final field reference, a field of an enclosing instance or 
58                 // just a local variable.
59
60                 int pc = codeStream.position;
61                 lhs.generateAssignment(currentScope, codeStream, this, valueRequired);
62                 // variable may have been optimized out
63                 // the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment.
64                 codeStream.recordPositionsFrom(pc, this.sourceStart);
65         }
66
67         public TypeBinding resolveType(BlockScope scope) {
68
69                 // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
70                 constant = NotAConstant;
71                 this.lhsType = lhs.resolveType(scope);
72                 TypeBinding expressionTb = expression.resolveType(scope);
73                 if (this.lhsType == null || expressionTb == null)
74                         return null;
75
76                 // Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
77                 // may require to widen the rhs expression at runtime
78                 if ((expression.isConstantValueOfTypeAssignableToType(expressionTb, this.lhsType)
79                         || (this.lhsType.isBaseType() && BaseTypeBinding.isWidening(this.lhsType.id, expressionTb.id)))
80                         || (BlockScope.areTypesCompatible(expressionTb, this.lhsType))) {
81                         expression.implicitWidening(this.lhsType, expressionTb);
82                         return this.lhsType;
83                 }
84                 scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
85                         expression,
86                         expressionTb,
87                         this.lhsType);
88                 return null;
89         }
90
91         public String toString(int tab) {
92
93                 //no () when used as a statement 
94                 return tabString(tab) + toStringExpressionNoParenthesis();
95         }
96
97         public String toStringExpression() {
98
99                 //subclass redefine toStringExpressionNoParenthesis()
100                 return "(" + toStringExpressionNoParenthesis() + ")"; //$NON-NLS-2$ //$NON-NLS-1$
101         } 
102         
103         public String toStringExpressionNoParenthesis() {
104
105                 return lhs.toStringExpression() + " " //$NON-NLS-1$
106                         + "=" //$NON-NLS-1$
107                         + ((expression.constant != null) && (expression.constant != NotAConstant)
108                                 ? " /*cst:" + expression.constant.toString() + "*/ " //$NON-NLS-1$ //$NON-NLS-2$
109                                 : " ")  //$NON-NLS-1$
110                         + expression.toStringExpression();
111         }
112         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
113                 
114                 if (visitor.visit(this, scope)) {
115                         lhs.traverse(visitor, scope);
116                         expression.traverse(visitor, scope);
117                 }
118                 visitor.endVisit(this, scope);
119         }
120 }