KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > Statement


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.ast;
12
13 import org.eclipse.jdt.internal.compiler.codegen.*;
14 import org.eclipse.jdt.internal.compiler.flow.*;
15 import org.eclipse.jdt.internal.compiler.impl.Constant;
16 import org.eclipse.jdt.internal.compiler.lookup.*;
17
18 public abstract class Statement extends ASTNode {
19     
20     public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
21     
22     /**
23      * INTERNAL USE ONLY.
24      * This is used to redirect inter-statements jumps.
25      */

26     public void branchChainTo(BranchLabel label) {
27         // do nothing by default
28
}
29     
30     // Report an error if necessary
31
public boolean complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, boolean didAlreadyComplain) {
32     
33         if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) {
34             this.bits &= ~ASTNode.IsReachable;
35             boolean reported = flowInfo == FlowInfo.DEAD_END;
36             if (!didAlreadyComplain && reported) {
37                 scope.problemReporter().unreachableCode(this);
38             }
39             return reported; // keep going for fake reachable
40
}
41         return false;
42     }
43
44     /**
45      * Generate invocation arguments, considering varargs methods
46      */

47     public void generateArguments(MethodBinding binding, Expression[] arguments, BlockScope currentScope, CodeStream codeStream) {
48         
49         if (binding.isVarargs()) {
50             // 5 possibilities exist for a call to the vararg method foo(int i, int ... value) :
51
// foo(1), foo(1, null), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new int[] {1, 2})
52
TypeBinding[] params = binding.parameters;
53             int paramLength = params.length;
54             int varArgIndex = paramLength - 1;
55             for (int i = 0; i < varArgIndex; i++) {
56                 arguments[i].generateCode(currentScope, codeStream, true);
57             }
58
59             ArrayBinding varArgsType = (ArrayBinding) params[varArgIndex]; // parameterType has to be an array type
60
ArrayBinding codeGenVarArgsType = (ArrayBinding) binding.parameters[varArgIndex].erasure();
61             int elementsTypeID = varArgsType.elementsType().id;
62             int argLength = arguments == null ? 0 : arguments.length;
63
64             if (argLength > paramLength) {
65                 // right number but not directly compatible or too many arguments - wrap extra into array
66
// called with (argLength - lastIndex) elements : foo(1, 2) or foo(1, 2, 3, 4)
67
// need to gen elements into an array, then gen each remaining element into created array
68
codeStream.generateInlinedValue(argLength - varArgIndex);
69                 codeStream.newArray(codeGenVarArgsType); // create a mono-dimensional array
70
for (int i = varArgIndex; i < argLength; i++) {
71                     codeStream.dup();
72                     codeStream.generateInlinedValue(i - varArgIndex);
73                     arguments[i].generateCode(currentScope, codeStream, true);
74                     codeStream.arrayAtPut(elementsTypeID, false);
75                 }
76             } else if (argLength == paramLength) {
77                 // right number of arguments - could be inexact - pass argument as is
78
TypeBinding lastType = arguments[varArgIndex].resolvedType;
79                 if (lastType == TypeBinding.NULL
80                     || (varArgsType.dimensions() == lastType.dimensions()
81                         && lastType.isCompatibleWith(varArgsType))) {
82                     // foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is
83
arguments[varArgIndex].generateCode(currentScope, codeStream, true);
84                 } else {
85                     // right number but not directly compatible or too many arguments - wrap extra into array
86
// need to gen elements into an array, then gen each remaining element into created array
87
codeStream.generateInlinedValue(1);
88                     codeStream.newArray(codeGenVarArgsType); // create a mono-dimensional array
89
codeStream.dup();
90                     codeStream.generateInlinedValue(0);
91                     arguments[varArgIndex].generateCode(currentScope, codeStream, true);
92                     codeStream.arrayAtPut(elementsTypeID, false);
93                 }
94             } else { // not enough arguments - pass extra empty array
95
// scenario: foo(1) --> foo(1, new int[0])
96
// generate code for an empty array of parameterType
97
codeStream.generateInlinedValue(0);
98                 codeStream.newArray(codeGenVarArgsType); // create a mono-dimensional array
99
}
100         } else if (arguments != null) { // standard generation for method arguments
101
for (int i = 0, max = arguments.length; i < max; i++)
102                 arguments[i].generateCode(currentScope, codeStream, true);
103         }
104     }
105
106     public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
107     
108     public boolean isEmptyBlock() {
109         return false;
110     }
111     
112     public boolean isValidJavaStatement() {
113         //the use of this method should be avoid in most cases
114
//and is here mostly for documentation purpose.....
115
//while the parser is responsable for creating
116
//welled formed expression statement, which results
117
//in the fact that java-non-semantic-expression-used-as-statement
118
//should not be parsable...thus not being built.
119
//It sounds like the java grammar as help the compiler job in removing
120
//-by construction- some statement that would have no effect....
121
//(for example all expression that may do side-effects are valid statement
122
// -this is an appromative idea.....-)
123

124         return true;
125     }
126     
127     public StringBuffer JavaDoc print(int indent, StringBuffer JavaDoc output) {
128         return printStatement(indent, output);
129     }
130     public abstract StringBuffer JavaDoc printStatement(int indent, StringBuffer JavaDoc output);
131
132     public abstract void resolve(BlockScope scope);
133     
134     /**
135      * Returns case constant associated to this statement (NotAConstant if none)
136      */

137     public Constant resolveCase(BlockScope scope, TypeBinding testType, SwitchStatement switchStatement) {
138         // statement within a switch that are not case are treated as normal statement....
139

140         resolve(scope);
141         return Constant.NotAConstant;
142     }
143
144 }
145
Popular Tags