1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
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.*;
18 public abstract class Statement extends ASTNode {
20 public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
24 * This is used to redirect inter-statements jumps.
26 public void branchChainTo(Label label) {
27 // do nothing by default
30 // Report an error if necessary
31 public boolean complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, boolean didAlreadyComplain) {
33 if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) {
34 this.bits &= ~ASTNode.IsReachableMASK;
35 boolean reported = flowInfo == FlowInfo.DEAD_END;
36 if (!didAlreadyComplain && reported) {
37 scope.problemReporter().unreachableCode(this);
39 return reported; // keep going for fake reachable
45 * Generate invocation arguments, considering varargs methods
47 public void generateArguments(MethodBinding binding, Expression[] arguments, BlockScope currentScope, CodeStream codeStream) {
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);
59 ArrayBinding varArgsType = (ArrayBinding) params[varArgIndex]; // parameterType has to be an array type
60 int argLength = arguments == null ? 0 : arguments.length;
62 generateVarargsArgument: {
63 if (argLength >= paramLength) {
64 // right number of arguments - could be inexact - pass argument as is
65 TypeBinding lastType = arguments[varArgIndex].resolvedType;
66 if (lastType == NullBinding || varArgsType.dimensions() == lastType.dimensions()) {
67 // foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is
68 arguments[varArgIndex].generateCode(currentScope, codeStream, true);
69 break generateVarargsArgument;
71 // right number but not directly compatible or too many arguments - wrap extra into array
72 // called with (argLength - lastIndex) elements : foo(1, 2) or foo(1, 2, 3, 4)
73 // need to gen elements into an array, then gen each remaining element into created array
74 codeStream.generateInlinedValue(argLength - varArgIndex);
75 codeStream.newArray(varArgsType); // create a mono-dimensional array
76 int elementsTypeID = varArgsType.elementsType().id;
77 for (int i = varArgIndex; i < argLength; i++) {
79 codeStream.generateInlinedValue(i - varArgIndex);
80 arguments[i].generateCode(currentScope, codeStream, true);
81 codeStream.arrayAtPut(elementsTypeID, false);
83 } else { // not enough arguments - pass extra empty array
84 // scenario: foo(1) --> foo(1, new int[0])
85 // generate code for an empty array of parameterType
86 codeStream.generateInlinedValue(0);
87 codeStream.newArray(varArgsType); // create a mono-dimensional array
90 } else if (arguments != null) { // standard generation for method arguments
91 for (int i = 0, max = arguments.length; i < max; i++)
92 arguments[i].generateCode(currentScope, codeStream, true);
96 public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
98 public boolean isEmptyBlock() {
102 public boolean isValidJavaStatement() {
103 //the use of this method should be avoid in most cases
104 //and is here mostly for documentation purpose.....
105 //while the parser is responsable for creating
106 //welled formed expression statement, which results
107 //in the fact that java-non-semantic-expression-used-as-statement
108 //should not be parsable...thus not being built.
109 //It sounds like the java grammar as help the compiler job in removing
110 //-by construction- some statement that would have no effect....
111 //(for example all expression that may do side-effects are valid statement
112 // -this is an appromative idea.....-)
117 public StringBuffer print(int indent, StringBuffer output) {
118 return printStatement(indent, output);
120 public abstract StringBuffer printStatement(int indent, StringBuffer output);
122 public abstract void resolve(BlockScope scope);
125 * Returns case constant associated to this statement (NotAConstant if none)
127 public Constant resolveCase(BlockScope scope, TypeBinding testType, SwitchStatement switchStatement) {
128 // statement within a switch that are not case are treated as normal statement....