X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ArrayInitializer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ArrayInitializer.java index 42ab9e4..b184c17 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ArrayInitializer.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ArrayInitializer.java @@ -1,72 +1,239 @@ +/*********************************************************************************************************************************** + * 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 v1.0 which accompanies this distribution, and is available at + * 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.ast.declarations.VariableUsage; +import net.sourceforge.phpdt.internal.compiler.ASTVisitor; +import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; +import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; +import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; -import java.util.List; -import java.util.ArrayList; - -/** - * an array initializer. - * array('a','b','c') or array('a' => 2,'b' = '3'); - * @author Matthieu Casanova - */ public class ArrayInitializer extends Expression { + public Expression[] expressions; + + public ArrayBinding binding; // the type of the { , , , } + + /** + * ArrayInitializer constructor comment. + */ + public ArrayInitializer() { + super(); + } + + public FlowInfo analyseCode(BlockScope currentScope, + FlowContext flowContext, FlowInfo flowInfo) { + if (expressions != null) { + for (int i = 0, max = expressions.length; i < max; i++) { + flowInfo = expressions[i].analyseCode(currentScope, + flowContext, flowInfo).unconditionalInits(); + } + } + return flowInfo; + } + + /** + * Code generation for a array initializer + */ + // public void generateCode(BlockScope currentScope, CodeStream codeStream, + // boolean valueRequired) { + // // Flatten the values and compute the dimensions, by iterating in depth + // into nested array initializers + // + // int pc = codeStream.position; + // int expressionLength = (expressions == null) ? 0: expressions.length; + // codeStream.generateInlinedValue(expressionLength); + // codeStream.newArray(currentScope, binding); + // if (expressions != null) { + // // binding is an ArrayType, so I can just deal with the dimension + // int elementsTypeID = binding.dimensions > 1 ? -1 : + // binding.leafComponentType.id; + // for (int i = 0; i < expressionLength; i++) { + // Expression expr; + // if ((expr = expressions[i]).constant != NotAConstant) { + // switch (elementsTypeID) { // filter out initializations to default values + // case T_int : + // case T_short : + // case T_byte : + // case T_char : + // case T_long : + // if (expr.constant.longValue() != 0) { + // codeStream.dup(); + // codeStream.generateInlinedValue(i); + // expr.generateCode(currentScope, codeStream, true); + // codeStream.arrayAtPut(elementsTypeID, false); + // } + // break; + // case T_float : + // case T_double : + // double constantValue = expr.constant.doubleValue(); + // if (constantValue == -0.0 || constantValue != 0) { + // codeStream.dup(); + // codeStream.generateInlinedValue(i); + // expr.generateCode(currentScope, codeStream, true); + // codeStream.arrayAtPut(elementsTypeID, false); + // } + // break; + // case T_boolean : + // if (expr.constant.booleanValue() != false) { + // codeStream.dup(); + // codeStream.generateInlinedValue(i); + // expr.generateCode(currentScope, codeStream, true); + // codeStream.arrayAtPut(elementsTypeID, false); + // } + // break; + // default : + // if (!(expr instanceof NullLiteral)) { + // codeStream.dup(); + // codeStream.generateInlinedValue(i); + // expr.generateCode(currentScope, codeStream, true); + // codeStream.arrayAtPut(elementsTypeID, false); + // } + // } + // } else if (!(expr instanceof NullLiteral)) { + // codeStream.dup(); + // codeStream.generateInlinedValue(i); + // expr.generateCode(currentScope, codeStream, true); + // codeStream.arrayAtPut(elementsTypeID, false); + // } + // } + // } + // if (!valueRequired) { + // codeStream.pop(); + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // } + public StringBuffer printExpression(int indent, StringBuffer output) { + + output.append('{'); + if (expressions != null) { + int j = 20; + for (int i = 0; i < expressions.length; i++) { + if (i > 0) + output.append(", "); //$NON-NLS-1$ + expressions[i].printExpression(0, output); + j--; + if (j == 0) { + output.append('\n'); + printIndent(indent + 1, output); + j = 20; + } + } + } + return output.append('}'); + } + + public TypeBinding resolveTypeExpecting(BlockScope scope, + TypeBinding expectedTb) { + // Array initializers can only occur on the right hand side of an + // assignment + // expression, therefore the expected type contains the valid + // information + // concerning the type that must be enforced by the elements of the + // array initializer. + + // this method is recursive... (the test on isArrayType is the stop + // case) - public ArrayVariableDeclaration[] vars; + constant = NotAConstant; + if (expectedTb.isArrayType()) { + binding = (ArrayBinding) expectedTb; + if (expressions == null) + return binding; + TypeBinding expectedElementsTb = binding.elementsType(scope); + if (expectedElementsTb.isBaseType()) { + for (int i = 0, length = expressions.length; i < length; i++) { + Expression expression = expressions[i]; + TypeBinding expressionTb = (expression instanceof ArrayInitializer) ? expression + .resolveTypeExpecting(scope, expectedElementsTb) + : expression.resolveType(scope); + if (expressionTb == null) + return null; - public ArrayInitializer(final ArrayVariableDeclaration[] vars, - final int sourceStart, - final int sourceEnd) { - super(sourceStart, sourceEnd); - this.vars = vars; - } + // Compile-time conversion required? + if (expression.isConstantValueOfTypeAssignableToType( + expressionTb, expectedElementsTb)) { + expression.implicitWidening(expectedElementsTb, + expressionTb); + } else if (BaseTypeBinding.isWidening( + expectedElementsTb.id, expressionTb.id)) { + expression.implicitWidening(expectedElementsTb, + expressionTb); + } else { + scope.problemReporter() + .typeMismatchErrorActualTypeExpectedType( + expression, expressionTb, + expectedElementsTb); + return null; + } + } + } else { + for (int i = 0, length = expressions.length; i < length; i++) + if (expressions[i].resolveTypeExpecting(scope, + expectedElementsTb) == null) + return null; + } + return binding; + } - /** - * Return the expression as String. - * @return the expression - */ - public String toStringExpression() { - final StringBuffer buff = new StringBuffer("array("); - for (int i = 0; i < vars.length; i++) { - final ArrayVariableDeclaration var = vars[i]; - if (i != 0) { - buff.append(","); - } - buff.append(var.toStringExpression()); - } - buff.append(")"); - return buff.toString(); - } + // infer initializer type for error reporting based on first element + TypeBinding leafElementType = null; + int dim = 1; + if (expressions == null) { + leafElementType = scope.getJavaLangObject(); + } else { + Expression currentExpression = expressions[0]; + while (currentExpression != null + && currentExpression instanceof ArrayInitializer) { + dim++; + Expression[] subExprs = ((ArrayInitializer) currentExpression).expressions; + if (subExprs == null) { + leafElementType = scope.getJavaLangObject(); + currentExpression = null; + break; + } + currentExpression = ((ArrayInitializer) currentExpression).expressions[0]; + } + if (currentExpression != null) { + leafElementType = currentExpression.resolveType(scope); + } + } + if (leafElementType != null) { + TypeBinding probableTb = scope.createArray(leafElementType, dim); + scope.problemReporter().typeMismatchErrorActualTypeExpectedType( + this, probableTb, expectedTb); + } + return null; + } - /** - * Get the variables from outside (parameters, globals ...) - * @return the variables from outside - */ - public List getOutsideVariable() { - return new ArrayList(1); - } + public String toStringExpression() { - /** - * get the modified variables. - * @return the variables from we change value - */ - public List getModifiedVariable() { - final ArrayList list = new ArrayList(); - for (int i = 0; i < vars.length; i++) { - list.addAll(vars[i].getModifiedVariable()); - } - return list; - } + String s = "{"; //$NON-NLS-1$ + if (expressions != null) { + int j = 20; + for (int i = 0; i < expressions.length; i++) { + s = s + expressions[i].toStringExpression() + ","; //$NON-NLS-1$ + j--; + if (j == 0) { + s = s + "\n ";j = 20;}}}; //$NON-NLS-1$ + s = s + "}"; //$NON-NLS-1$ + return s; + } - /** - * Get the variables used. - * @return the variables used - */ - public List getUsedVariable() { - final ArrayList list = new ArrayList(); - for (int i = 0; i < vars.length; i++) { - list.addAll(vars[i].getUsedVariable()); - } - return list; - } -} + public void traverse(ASTVisitor visitor, BlockScope scope) { + if (visitor.visit(this, scope)) { + if (expressions != null) { + int expressionsLength = expressions.length; + for (int i = 0; i < expressionsLength; i++) + expressions[i].traverse(visitor, scope); + } + } + visitor.endVisit(this, scope); + } +} \ No newline at end of file