X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fast%2FCompoundAssignment.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fast%2FCompoundAssignment.java;h=47745f1598e6e507fc4c3ce3fd455c4015bc385c;hb=040fa5af2cd00017cf3575950cdaade34a6d7f6c;hp=0000000000000000000000000000000000000000;hpb=a580fb8376d315d05e4d6bfdff9ff1101a151cd6;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java new file mode 100644 index 0000000..47745f1 --- /dev/null +++ b/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.ast; + +import org.eclipse.jdt.internal.compiler.ASTVisitor; +import org.eclipse.jdt.internal.compiler.codegen.*; +import org.eclipse.jdt.internal.compiler.flow.*; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class CompoundAssignment extends Assignment implements OperatorIds { + public int operator; + public int assignmentImplicitConversion; + + // var op exp is equivalent to var = (varType) var op exp + // assignmentImplicitConversion stores the cast needed for the assignment + + public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) { + //lhs is always a reference by construction , + //but is build as an expression ==> the checkcast cannot fail + + super(lhs, expression, sourceEnd); + lhs.bits &= ~IsStrictlyAssignedMASK; // tag lhs as NON assigned - it is also a read access + lhs.bits |= IsCompoundAssignedMASK; // tag lhs as assigned by compound + this.operator = operator ; + } + + public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { + // record setting a variable: various scenarii are possible, setting an array reference, + // a field reference, a blank final field reference, a field of an enclosing instance or + // just a local variable. + + return ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits(); + } + + public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { + + // various scenarii are possible, setting an array reference, + // a field reference, a blank final field reference, a field of an enclosing instance or + // just a local variable. + + int pc = codeStream.position; + ((Reference) lhs).generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired); + if (valueRequired) { + codeStream.generateImplicitConversion(implicitConversion); + } + codeStream.recordPositionsFrom(pc, this.sourceStart); + } + + public String operatorToString() { + switch (operator) { + case PLUS : + return "+="; //$NON-NLS-1$ + case MINUS : + return "-="; //$NON-NLS-1$ + case MULTIPLY : + return "*="; //$NON-NLS-1$ + case DIVIDE : + return "/="; //$NON-NLS-1$ + case AND : + return "&="; //$NON-NLS-1$ + case OR : + return "|="; //$NON-NLS-1$ + case XOR : + return "^="; //$NON-NLS-1$ + case REMAINDER : + return "%="; //$NON-NLS-1$ + case LEFT_SHIFT : + return "<<="; //$NON-NLS-1$ + case RIGHT_SHIFT : + return ">>="; //$NON-NLS-1$ + case UNSIGNED_RIGHT_SHIFT : + return ">>>="; //$NON-NLS-1$ + } + return "unknown operator"; //$NON-NLS-1$ + } + + public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { + + lhs.printExpression(indent, output).append(' ').append(operatorToString()).append(' '); + return expression.printExpression(0, output) ; + } + + public TypeBinding resolveType(BlockScope scope) { + constant = NotAConstant; + if (!(this.lhs instanceof Reference) || this.lhs.isThis()) { + scope.problemReporter().expressionShouldBeAVariable(this.lhs); + return null; + } + TypeBinding lhsType = lhs.resolveType(scope); + TypeBinding expressionType = expression.resolveType(scope); + if (lhsType == null || expressionType == null) + return null; + + int lhsId = lhsType.id; + int expressionId = expressionType.id; + if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) { + scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType); + return null; + } + if (lhsId > 15 || expressionId > 15) { + if (lhsId != T_String) { // String += Thread is valid whereas Thread += String is not + scope.problemReporter().invalidOperator(this, lhsType, expressionType); + return null; + } + expressionId = T_Object; // use the Object has tag table + } + + // the code is an int + // (cast) left Op (cast) rigth --> result + // 0000 0000 0000 0000 0000 + // <<16 <<12 <<8 <<4 <<0 + + // the conversion is stored INTO the reference (info needed for the code gen) + int result = OperatorExpression.OperatorSignatures[operator][ (lhsId << 4) + expressionId]; + if (result == T_undefined) { + scope.problemReporter().invalidOperator(this, lhsType, expressionType); + return null; + } + if (operator == PLUS){ + if(lhsId == T_JavaLangObject) { + // += is illegal (39248) + scope.problemReporter().invalidOperator(this, lhsType, expressionType); + return null; + } else { + // += is illegal + if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){ + scope.problemReporter().invalidOperator(this, lhsType, expressionType); + return null; + } + } + } + lhs.implicitConversion = result >>> 12; + expression.implicitConversion = (result >>> 4) & 0x000FF; + assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F); + return this.resolvedType = lhsType; + } + + public boolean restrainUsageToNumericTypes(){ + return false ; + } + + public void traverse(ASTVisitor visitor, BlockScope scope) { + if (visitor.visit(this, scope)) { + lhs.traverse(visitor, scope); + expression.traverse(visitor, scope); + } + visitor.endVisit(this, scope); + } +}