X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Expression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Expression.java index 15ba5e3..69bd341 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Expression.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Expression.java @@ -1,23 +1,23 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 + * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation - ******************************************************************************/ + *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; -import net.sourceforge.phpdt.internal.compiler.impl.*; -import net.sourceforge.phpdt.internal.compiler.codegen.*; -import net.sourceforge.phpdt.internal.compiler.flow.*; -import net.sourceforge.phpdt.internal.compiler.lookup.*; -import net.sourceforge.phpdt.internal.compiler.problem.*; -import net.sourceforge.phpdt.internal.compiler.util.Util; +import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; +import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; +import net.sourceforge.phpdt.internal.compiler.impl.Constant; +import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; -public abstract class Expression extends Statement { +public class Expression extends Statement { //some expression may not be used - from a java semantic point //of view only - as statements. Other may. In order to avoid the creation @@ -25,25 +25,34 @@ public abstract class Expression extends Statement { //Expression is a subclass of Statement. See the message isValidJavaStatement() public int implicitConversion; - + public TypeBinding resolvedType; + public Constant constant; public Expression() { super(); } - public FlowInfo analyseCode( - BlockScope currentScope, - FlowContext flowContext, - FlowInfo flowInfo, - boolean valueRequired) { + public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { - return analyseCode(currentScope, flowContext, flowInfo); + return flowInfo; } - public Constant conditionalConstant() { + public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { + + return analyseCode(currentScope, flowContext, flowInfo); + } - return constant; + /** + * Constant usable for bytecode pattern optimizations, but cannot be inlined + * since it is not strictly equivalent to the definition of constant expressions. + * In particular, some side-effects may be required to occur (only the end value + * is known). + * Constant is known to be of boolean type + */ + public Constant optimizedBooleanConstant() { + + return this.constant; } public static final boolean isConstantValueRepresentable( @@ -205,149 +214,149 @@ public abstract class Expression extends Statement { * Expression statements are plain expressions, however they generate like * normal expressions with no value required. * - * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope - * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream + * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope + * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream */ - public void generateCode(BlockScope currentScope, CodeStream codeStream) { - - if ((bits & IsReachableMASK) == 0) { - return; - } - generateCode(currentScope, codeStream, false); - } +// public void generateCode(BlockScope currentScope, CodeStream codeStream) { +// +// if ((bits & IsReachableMASK) == 0) { +// return; +// } +// generateCode(currentScope, codeStream, false); +// } /** * Every expression is responsible for generating its implicit conversion when necessary. * - * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope - * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream + * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope + * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream * @param valueRequired boolean */ - public void generateCode( - BlockScope currentScope, - CodeStream codeStream, - boolean valueRequired) { - - if (constant != NotAConstant) { - // generate a constant expression - int pc = codeStream.position; - codeStream.generateConstant(constant, implicitConversion); - codeStream.recordPositionsFrom(pc, this.sourceStart); - } else { - // actual non-constant code generation - throw new ShouldNotImplement(Util.bind("ast.missingCode")); //$NON-NLS-1$ - } - } +// public void generateCode( +// BlockScope currentScope, +// CodeStream codeStream, +// boolean valueRequired) { +// +// if (constant != NotAConstant) { +// // generate a constant expression +// int pc = codeStream.position; +// codeStream.generateConstant(constant, implicitConversion); +// codeStream.recordPositionsFrom(pc, this.sourceStart); +// } else { +// // actual non-constant code generation +// throw new ShouldNotImplement(ProjectPrefUtil.bind("ast.missingCode")); //$NON-NLS-1$ +// } +// } /** * Default generation of a boolean value */ - public void generateOptimizedBoolean( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - // a label valued to nil means: by default we fall through the case... - // both nil means we leave the value on the stack - - if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) { - int pc = codeStream.position; - if (constant.booleanValue() == true) { - // constant == true - if (valueRequired) { - if (falseLabel == null) { - // implicit falling through the FALSE case - if (trueLabel != null) { - codeStream.goto_(trueLabel); - } - } - } - } else { - if (valueRequired) { - if (falseLabel != null) { - // implicit falling through the TRUE case - if (trueLabel == null) { - codeStream.goto_(falseLabel); - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - generateCode(currentScope, codeStream, valueRequired); - // branching - int position = codeStream.position; - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // Implicit falling through the FALSE case - codeStream.ifne(trueLabel); - } - } else { - if (trueLabel == null) { - // Implicit falling through the TRUE case - codeStream.ifeq(falseLabel); - } else { - // No implicit fall through TRUE/FALSE --> should never occur - } - } - } - // reposition the endPC - codeStream.updateLastRecordedEndPC(position); - } +// public void generateOptimizedBoolean( +// BlockScope currentScope, +// CodeStream codeStream, +// Label trueLabel, +// Label falseLabel, +// boolean valueRequired) { +// +// // a label valued to nil means: by default we fall through the case... +// // both nil means we leave the value on the stack +// +// if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) { +// int pc = codeStream.position; +// if (constant.booleanValue() == true) { +// // constant == true +// if (valueRequired) { +// if (falseLabel == null) { +// // implicit falling through the FALSE case +// if (trueLabel != null) { +// codeStream.goto_(trueLabel); +// } +// } +// } +// } else { +// if (valueRequired) { +// if (falseLabel != null) { +// // implicit falling through the TRUE case +// if (trueLabel == null) { +// codeStream.goto_(falseLabel); +// } +// } +// } +// } +// codeStream.recordPositionsFrom(pc, this.sourceStart); +// return; +// } +// generateCode(currentScope, codeStream, valueRequired); +// // branching +// int position = codeStream.position; +// if (valueRequired) { +// if (falseLabel == null) { +// if (trueLabel != null) { +// // Implicit falling through the FALSE case +// codeStream.ifne(trueLabel); +// } +// } else { +// if (trueLabel == null) { +// // Implicit falling through the TRUE case +// codeStream.ifeq(falseLabel); +// } else { +// // No implicit fall through TRUE/FALSE --> should never occur +// } +// } +// } +// // reposition the endPC +// codeStream.updateLastRecordedEndPC(position); +// } +// +// /* Optimized (java) code generation for string concatenations that involve StringBuffer +// * creation: going through this path means that there is no need for a new StringBuffer +// * creation, further operands should rather be only appended to the current one. +// * By default: no optimization. +// */ +// public void generateOptimizedStringBuffer( +// BlockScope blockScope, +// net.sourceforge.phpdt.internal.compiler.codegen.CodeStream codeStream, +// int typeID) { +// +// generateCode(blockScope, codeStream, true); +// codeStream.invokeStringBufferAppendForType(typeID); +// } /* Optimized (java) code generation for string concatenations that involve StringBuffer * creation: going through this path means that there is no need for a new StringBuffer * creation, further operands should rather be only appended to the current one. - * By default: no optimization. */ - public void generateOptimizedStringBuffer( - BlockScope blockScope, - net.sourceforge.phpdt.internal.compiler.codegen.CodeStream codeStream, - int typeID) { - - generateCode(blockScope, codeStream, true); - codeStream.invokeStringBufferAppendForType(typeID); - } - - /* Optimized (java) code generation for string concatenations that involve StringBuffer - * creation: going through this path means that there is no need for a new StringBuffer - * creation, further operands should rather be only appended to the current one. - */ - public void generateOptimizedStringBufferCreation( - BlockScope blockScope, - CodeStream codeStream, - int typeID) { - - // Optimization only for integers and strings - if (typeID == T_Object) { - // in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object) - // append(Object) returns append(valueOf(Object)), which means that the null case is handled by append(String). - codeStream.newStringBuffer(); - codeStream.dup(); - codeStream.invokeStringBufferDefaultConstructor(); - generateCode(blockScope, codeStream, true); - codeStream.invokeStringBufferAppendForType(T_Object); - return; - } - codeStream.newStringBuffer(); - codeStream.dup(); - if ((typeID == T_String) || (typeID == T_null)) { - if (constant != NotAConstant) { - codeStream.ldc(constant.stringValue()); - } else { - generateCode(blockScope, codeStream, true); - codeStream.invokeStringValueOf(T_Object); - } - } else { - generateCode(blockScope, codeStream, true); - codeStream.invokeStringValueOf(typeID); - } - codeStream.invokeStringBufferStringConstructor(); - } +// public void generateOptimizedStringBufferCreation( +// BlockScope blockScope, +// CodeStream codeStream, +// int typeID) { +// +// // Optimization only for integers and strings +// if (typeID == T_Object) { +// // in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object) +// // append(Object) returns append(valueOf(Object)), which means that the null case is handled by append(String). +// codeStream.newStringBuffer(); +// codeStream.dup(); +// codeStream.invokeStringBufferDefaultConstructor(); +// generateCode(blockScope, codeStream, true); +// codeStream.invokeStringBufferAppendForType(T_Object); +// return; +// } +// codeStream.newStringBuffer(); +// codeStream.dup(); +// if (typeID == T_String || typeID == T_null) { +// if (constant != NotAConstant) { +// codeStream.ldc(constant.stringValue()); +// } else { +// generateCode(blockScope, codeStream, true); +// codeStream.invokeStringValueOf(T_Object); +// } +// } else { +// generateCode(blockScope, codeStream, true); +// codeStream.invokeStringValueOf(typeID); +// } +// codeStream.invokeStringBufferStringConstructor(); +// } // Base types need that the widening is explicitly done by the compiler using some bytecode like i2f public void implicitWidening( @@ -357,15 +366,15 @@ public abstract class Expression extends Statement { if (runtimeTimeType == null || compileTimeType == null) return; - if (compileTimeType.id == T_null) { - // this case is possible only for constant null - // The type of runtime is a reference type - // The code gen use the constant id thus any value - // for the runtime id (akak the <<4) could be used. - // T_Object is used as some general T_reference - implicitConversion = (T_Object << 4) + T_null; - return; - } +// if (compileTimeType.id == T_null) { +// // this case is possible only for constant null +// // The type of runtime is a reference type +// // The code gen use the constant id thus any value +// // for the runtime id (akak the <<4) could be used. +// // T_Object is used as some general T_reference +// implicitConversion = (T_Object << 4) + T_null; +// return; +// } switch (runtimeTimeType.id) { case T_byte : @@ -417,7 +426,19 @@ public abstract class Expression extends Statement { public boolean isTypeReference() { return false; } + public StringBuffer print(int indent, StringBuffer output) { + printIndent(indent, output); + return printExpression(indent, output); + } + public StringBuffer printExpression(int indent, StringBuffer output) { + output.append(super.toString(0)); + return output; + } + + public StringBuffer printStatement(int indent, StringBuffer output) { + return print(indent, output).append(";"); //$NON-NLS-1$ + } public void resolve(BlockScope scope) { // drops the returning expression's type whatever the type is. @@ -433,16 +454,17 @@ public abstract class Expression extends Statement { public TypeBinding resolveTypeExpecting( BlockScope scope, - TypeBinding expectedTb) { - - TypeBinding thisTb = this.resolveType(scope); - if (thisTb == null) - return null; - if (!scope.areTypesCompatible(thisTb, expectedTb)) { - scope.problemReporter().typeMismatchError(thisTb, expectedTb, this); + TypeBinding expectedType) { + + TypeBinding expressionType = this.resolveType(scope); + if (expressionType == null) return null; + if (expressionType == expectedType) return expressionType; + + if (!expressionType.isCompatibleWith(expectedType)) { + scope.problemReporter().typeMismatchError(expressionType, expectedType, this); return null; } - return thisTb; + return expressionType; } public String toString(int tab) { @@ -481,4 +503,4 @@ public abstract class Expression extends Statement { return this; } -} \ No newline at end of file +}