private void visitBinaryOperator ( Token op , Node n ) { Node left = n . getFirstChild ( ) ; JSType leftType = getJSType ( left ) ; Node right = n . getLastChild ( ) ; JSType rightType = getJSType ( right ) ; switch ( op ) { case ASSIGN_LSH : case ASSIGN_RSH : case LSH : case RSH : case ASSIGN_URSH : case URSH : String opStr = NodeUtil . opToStr ( n . getToken ( ) ) ; if ( ! leftType . matchesNumberContext ( ) ) { report ( left , BIT_OPERATION , opStr , leftType . toString ( ) ) ; } else { this . validator . expectNumberStrict ( n , leftType , "operator " + opStr ) ; } if ( ! rightType . matchesNumberContext ( ) ) { report ( right , BIT_OPERATION , opStr , rightType . toString ( ) ) ; } else { this . validator . expectNumberStrict ( n , rightType , "operator " + opStr ) ; } break ; case ASSIGN_DIV : case ASSIGN_MOD : case ASSIGN_MUL : case ASSIGN_SUB : case ASSIGN_EXPONENT : case DIV : case MOD : case MUL : case SUB : case EXPONENT : validator . expectNumber ( left , leftType , "left operand" ) ; validator . expectNumber ( right , rightType , "right operand" ) ; break ; case ASSIGN_BITAND : case ASSIGN_BITXOR : case ASSIGN_BITOR : case BITAND : case BITXOR : case BITOR : validator . expectBitwiseable ( left , leftType , "bad left operand to bitwise operator" ) ; validator . expectBitwiseable ( right , rightType , "bad right operand to bitwise operator" ) ; break ; case ASSIGN_ADD : case ADD : break ; default : report ( n , UNEXPECTED_TOKEN , op . toString ( ) ) ; } ensureTyped ( n ) ; }
This function unifies the type checking involved in the core binary operators and the corresponding assignment operators . The representation used internally is such that common code can handle both kinds of operators easily .