<s> package org . eclipse . jdt . internal . compiler . ast ; import org . eclipse . jdt . internal . compiler . ASTVisitor ; import org . eclipse . jdt . internal . compiler . codegen . CodeStream ; import org . eclipse . jdt . internal . compiler . flow . FlowContext ; import org . eclipse . jdt . internal . compiler . flow . FlowInfo ; import org . eclipse . jdt . internal . compiler . impl . Constant ; import org . eclipse . jdt . internal . compiler . lookup . BlockScope ; import org . eclipse . jdt . internal . compiler . lookup . TypeBinding ; import org . eclipse . jdt . internal . compiler . lookup . TypeIds ; public class CombinedBinaryExpression extends BinaryExpression { public int arity ; public int arityMax ; public static final int ARITY_MAX_MAX = 160 ; public static final int ARITY_MAX_MIN = 20 ; public static int defaultArityMaxStartingValue = ARITY_MAX_MIN ; public BinaryExpression referencesTable [ ] ; public CombinedBinaryExpression ( Expression left , Expression right , int operator , int arity ) { super ( left , right , operator ) ; initArity ( left , arity ) ; } public CombinedBinaryExpression ( CombinedBinaryExpression expression ) { super ( expression ) ; initArity ( expression . left , expression . arity ) ; } public FlowInfo analyseCode ( BlockScope currentScope , FlowContext flowContext , FlowInfo flowInfo ) { if ( this . referencesTable == null ) { return super . analyseCode ( currentScope , flowContext , flowInfo ) ; } BinaryExpression cursor ; if ( ( cursor = this . referencesTable [ 0 ] ) . resolvedType . id != TypeIds . T_JavaLangString ) { cursor . left . checkNPE ( currentScope , flowContext , flowInfo ) ; } flowInfo = cursor . left . analyseCode ( currentScope , flowContext , flowInfo ) . unconditionalInits ( ) ; for ( int i = 0 , end = this . arity ; i < end ; i ++ ) { if ( ( cursor = this . referencesTable [ i ] ) . resolvedType . id != TypeIds . T_JavaLangString ) { cursor . right . checkNPE ( currentScope , flowContext , flowInfo ) ; } flowInfo = cursor . right . analyseCode ( currentScope , flowContext , flowInfo ) . unconditionalInits ( ) ; } if ( this . resolvedType . id != TypeIds . T_JavaLangString ) { this . right . checkNPE ( currentScope , flowContext , flowInfo ) ; } return this . right . analyseCode ( currentScope , flowContext , flowInfo ) . unconditionalInits ( ) ; } public void generateOptimizedStringConcatenation ( BlockScope blockScope , CodeStream codeStream , int typeID ) { if ( this . referencesTable == null ) { super . generateOptimizedStringConcatenation ( blockScope , codeStream , typeID ) ; } else { if ( ( ( ( this . bits & ASTNode . OperatorMASK ) >> ASTNode . OperatorSHIFT ) == OperatorIds . PLUS ) && ( ( this . bits & ASTNode . ReturnTypeIDMASK ) == TypeIds . T_JavaLangString ) ) { if ( this . constant != Constant . NotAConstant ) { codeStream . generateConstant ( this . constant , this . implicitConversion ) ; codeStream . invokeStringConcatenationAppendForType ( this . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; } else { BinaryExpression cursor = this . referencesTable [ 0 ] ; int restart = 0 ; int pc = codeStream . position ; for ( restart = this . arity - 1 ; restart >= 0 ; restart -- ) { if ( ( cursor = this . referencesTable [ restart ] ) . constant != Constant . NotAConstant ) { codeStream . generateConstant ( cursor . constant , cursor . implicitConversion ) ; codeStream . invokeStringConcatenationAppendForType ( cursor . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; break ; } } restart ++ ; if ( restart == 0 ) { cursor . left . generateOptimizedStringConcatenation ( blockScope , codeStream , cursor . left . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; } int pcAux ; for ( int i = restart ; i < this . arity ; i ++ ) { codeStream . recordPositionsFrom ( pc , ( cursor = this . referencesTable [ i ] ) . left . sourceStart ) ; pcAux = codeStream . position ; cursor . right . generateOptimizedStringConcatenation ( blockScope , codeStream , cursor . right . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; codeStream . recordPositionsFrom ( pcAux , cursor . right . sourceStart ) ; } codeStream . recordPositionsFrom ( pc , this . left . sourceStart ) ; pc = codeStream . position ; this . right . generateOptimizedStringConcatenation ( blockScope , codeStream , this . right . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; codeStream . recordPositionsFrom ( pc , this . right . sourceStart ) ; } } else { super . generateOptimizedStringConcatenation ( blockScope , codeStream , typeID ) ; } } } public void generateOptimizedStringConcatenationCreation ( BlockScope blockScope , CodeStream codeStream , int typeID ) { if ( this . referencesTable == null ) { super . generateOptimizedStringConcatenationCreation ( blockScope , codeStream , typeID ) ; } else { if ( ( ( ( this . bits & ASTNode . OperatorMASK ) >> ASTNode . OperatorSHIFT ) == OperatorIds . PLUS ) && ( ( this . bits & ASTNode . ReturnTypeIDMASK ) == TypeIds . T_JavaLangString ) && this . constant == Constant . NotAConstant ) { int pc = codeStream . position ; BinaryExpression cursor = this . referencesTable [ this . arity - 1 ] ; int restart = 0 ; for ( restart = this . arity - 1 ; restart >= 0 ; restart -- ) { if ( ( ( ( ( cursor = this . referencesTable [ restart ] ) . bits & ASTNode . OperatorMASK ) >> ASTNode . OperatorSHIFT ) == OperatorIds . PLUS ) && ( ( cursor . bits & ASTNode . ReturnTypeIDMASK ) == TypeIds . T_JavaLangString ) ) { if ( cursor . constant != Constant . NotAConstant ) { codeStream . newStringContatenation ( ) ; codeStream . dup ( ) ; codeStream . ldc ( cursor . constant . stringValue ( ) ) ; codeStream . invokeStringConcatenationStringConstructor ( ) ; break ; } } else { cursor . generateOptimizedStringConcatenationCreation ( blockScope , codeStream , cursor . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; break ; } } restart ++ ; if ( restart == 0 ) { cursor . left . generateOptimizedStringConcatenationCreation ( blockScope , codeStream , cursor . left . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; } int pcAux ; for ( int i = restart ; i < this . arity ; i ++ ) { codeStream . recordPositionsFrom ( pc , ( cursor = this . referencesTable [ i ] ) . left . sourceStart ) ; pcAux = codeStream . position ; cursor . right . generateOptimizedStringConcatenation ( blockScope , codeStream , cursor . right . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; codeStream . recordPositionsFrom ( pcAux , cursor . right . sourceStart ) ; } codeStream . recordPositionsFrom ( pc , this . left . sourceStart ) ; pc = codeStream . position ; this . right . generateOptimizedStringConcatenation ( blockScope , codeStream , this . right . implicitConversion & TypeIds . COMPILE_TYPE_MASK ) ; codeStream . recordPositionsFrom ( pc , this . right . sourceStart ) ; } else { super . generateOptimizedStringConcatenationCreation ( blockScope , codeStream , typeID ) ; } } } private void initArity ( Expression expression , int value ) { this . arity = value ; if ( value > 1 ) { this . referencesTable = new BinaryExpression [ value ] ; this . referencesTable [ value - 1 ] = ( BinaryExpression ) expression ; for ( int i = value - 1 ; i > 0 ; i -- ) { this . referencesTable [ i - 1 ] = ( BinaryExpression ) this . referencesTable [ i ] . left ; } } else { this . arityMax = defaultArityMaxStartingValue ; } } public StringBuffer printExpressionNoParenthesis ( int indent , StringBuffer output ) { if ( this . referencesTable == null ) { return super . printExpressionNoParenthesis ( indent , output ) ; } String operatorString = operatorToString ( ) ; for ( int i = this . arity - 1 ; i >= 0 ; i -- ) { output . append ( '(' ) ; } output = this . referencesTable [ 0 ] . left . printExpression ( indent , output ) ; for ( int i = 0 , end = this . arity ; i < end ; i ++ ) { output . append ( ' ' ) . append ( operatorString ) . append ( ' ' ) ; output = this . referencesTable [ i ] . right . printExpression ( 0 , output ) ; output . append ( ')' ) ; } output . append ( ' ' ) . append ( operatorString ) . append ( ' ' ) ; return this . right . printExpression ( 0 , output ) ; } public TypeBinding resolveType ( BlockScope scope ) { if ( this . referencesTable == null ) { return super . resolveType ( scope ) ; } BinaryExpression cursor ; if ( ( cursor = this . referencesTable [ 0 ] ) . left instanceof CastExpression ) { cursor . left . bits |= ASTNode . DisableUnnecessaryCastCheck ; } cursor . left . resolveType ( scope ) ; for ( int i = 0 , end = this . arity ; i < end ; i ++ ) { this . referencesTable [ i ] . nonRecursiveResolveTypeUpwards ( scope ) ; } nonRecursiveResolveTypeUpwards ( scope ) ; return this . resolvedType ; } public void traverse ( ASTVisitor visitor , BlockScope scope ) { if ( this . referencesTable == null ) { super . traverse ( visitor , scope ) ; } else { if ( visitor . visit ( this , scope ) ) { int restart ; for ( restart = this . arity - 1 ; restart >= 0 ; restart -- ) { if ( ! visitor . visit ( this . referencesTable [ restart ] , scope ) ) { visitor . endVisit ( this . referencesTable [ restart ] , scope ) ; break ; } } restart ++ ; if ( restart == 0 ) { this . referencesTable [ 0 ] . left . traverse ( visitor , scope ) ; } for ( int i = restart , end = this . arity ; i < end ; i ++ ) { this . referencesTable [ i ] . right . traverse ( visitor , scope ) ; visitor . endVisit ( this . referencesTable [ i ] , scope ) ; } this . right . traverse ( visitor , scope ) ; } visitor . endVisit ( this , scope ) ; } } public void tuneArityMax ( ) { if ( this . arityMax < ARITY_MAX_MAX ) { this . arityMax *= 2 ; } } } </s>