Ejemplo n.º 1
0
 public BinaryOperatorSignature(BinaryOperatorKind kind, TypeSymbol returnType, TypeSymbol leftParameterType, TypeSymbol rightParameterType)
 {
     Kind = kind;
     ReturnType = returnType;
     _leftParameterType = leftParameterType;
     _rightParameterType = rightParameterType;
 }
            internal SingleValueNode Parse(Lexer lexer)
            {
                while (lexer.MoveNext())
                {
                    var token = lexer.Current;

                    switch (token.TokenType)
                    {
                        case TokenType.And:
                            this.nextBinaryOperatorKind = BinaryOperatorKind.And;
                            this.UpdateExpressionTree();
                            break;

                        case TokenType.Or:
                            this.nextBinaryOperatorKind = BinaryOperatorKind.Or;
                            this.UpdateExpressionTree();
                            break;

                        default:
                            this.tokens.Enqueue(token);
                            break;
                    }
                }

                this.nextBinaryOperatorKind = BinaryOperatorKind.None;
                this.UpdateExpressionTree();

                return this.nodeStack.Pop();
            }
Ejemplo n.º 3
0
        /// <summary>
        /// Compute the result type of a binary operator based on the type of its operands and the operator kind.
        /// </summary>
        /// <param name="typeReference">The type reference of the operators.</param>
        /// <param name="operatorKind">The kind of operator.</param>
        /// <returns>The result type reference of the binary operator.</returns>
        internal static IEdmPrimitiveTypeReference GetBinaryOperatorResultType(IEdmPrimitiveTypeReference typeReference, BinaryOperatorKind operatorKind)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(typeReference != null, "type != null");

            switch (operatorKind)
            {
                case BinaryOperatorKind.Or:                 // fall through
                case BinaryOperatorKind.And:                // fall through
                case BinaryOperatorKind.Equal:              // fall through
                case BinaryOperatorKind.NotEqual:           // fall through
                case BinaryOperatorKind.GreaterThan:        // fall through
                case BinaryOperatorKind.GreaterThanOrEqual: // fall through
                case BinaryOperatorKind.LessThan:           // fall through
                case BinaryOperatorKind.LessThanOrEqual:
                    return EdmCoreModel.Instance.GetBoolean(typeReference.IsNullable);

                case BinaryOperatorKind.Add:        // fall through
                case BinaryOperatorKind.Subtract:   // fall through
                case BinaryOperatorKind.Multiply:   // fall through
                case BinaryOperatorKind.Divide:     // fall through
                case BinaryOperatorKind.Modulo:
                    return typeReference;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.QueryNodeUtils_BinaryOperatorResultType_UnreachableCodepath));
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Compute the result type of a binary operator based on the type of its operands and the operator kind.
        /// </summary>
        /// <param name="type">The type of the operators.</param>
        /// <param name="operatorKind">The kind of operator.</param>
        /// <returns>The result type of the binary operator.</returns>
        internal static ResourceType GetBinaryOperatorResultType(ResourceType type, BinaryOperatorKind operatorKind)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(type != null, "type != null");

            switch (operatorKind)
            {
                case BinaryOperatorKind.Or:                 // fall through
                case BinaryOperatorKind.And:                // fall through
                case BinaryOperatorKind.Equal:              // fall through
                case BinaryOperatorKind.NotEqual:           // fall through
                case BinaryOperatorKind.GreaterThan:        // fall through
                case BinaryOperatorKind.GreaterThanOrEqual: // fall through
                case BinaryOperatorKind.LessThan:           // fall through
                case BinaryOperatorKind.LessThanOrEqual:
                    Type resultType = Nullable.GetUnderlyingType(type.InstanceType) == null
                        ? typeof(bool)
                        : typeof(bool?);
                    return ResourceType.GetPrimitiveResourceType(resultType);

                case BinaryOperatorKind.Add:        // fall through
                case BinaryOperatorKind.Subtract:   // fall through
                case BinaryOperatorKind.Multiply:   // fall through
                case BinaryOperatorKind.Divide:     // fall through
                case BinaryOperatorKind.Modulo:
                    return type;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.QueryNodeUtils_BinaryOperatorResultType_UnreachableCodepath));
            }
        }
Ejemplo n.º 5
0
 public static AndConstraint<BinaryOperatorToken> ShouldBeBinaryOperatorQueryToken(this QueryToken token, BinaryOperatorKind expectedOperatorKind)
 {
     token.Should().BeOfType<BinaryOperatorToken>();
     var propertyAccessQueryToken = token.As<BinaryOperatorToken>();
     propertyAccessQueryToken.Kind.Should().Be(QueryTokenKind.BinaryOperator);
     propertyAccessQueryToken.OperatorKind.Should().Be(expectedOperatorKind);
     return new AndConstraint<BinaryOperatorToken>(propertyAccessQueryToken);
 }
Ejemplo n.º 6
0
 public BoundAssignmentExpression(BoundExpression left, BinaryOperatorKind? operatorKind, BoundExpression right)
     : base(BoundNodeKind.AssignmentExpression)
 {
     OperatorKind = operatorKind;
     Left = left;
     Right = right;
     Type = left.Type;
 }
Ejemplo n.º 7
0
 public BoundBinaryExpression(BinaryOperatorKind operatorKind, BoundExpression left, BoundExpression right, OverloadResolutionResult<BinaryOperatorSignature> result)
     : base(BoundNodeKind.BinaryExpression)
 {
     OperatorKind = operatorKind;
     Left = left;
     Right = right;
     Result = result;
 }
 public BoundBinaryExpression(BinaryExpressionSyntax syntax, BinaryOperatorKind operatorKind, BoundExpression left, BoundExpression right, TypeSymbol type)
     : base(BoundNodeKind.BinaryExpression, syntax)
 {
     OperatorKind = operatorKind;
     Left = left;
     Right = right;
     Type = type;
 }
Ejemplo n.º 9
0
 public BinaryOperatorSignature(BinaryOperatorKind kind, TypeSymbol leftType, TypeSymbol rightType, TypeSymbol returnType, MethodSymbol method = null)
 {
     this.Kind = kind;
     this.LeftType = leftType;
     this.RightType = rightType;
     this.ReturnType = returnType;
     this.Method = method;
 }
Ejemplo n.º 10
0
 public override void PromoteBinaryOperandTypes(
     BinaryOperatorKind binaryOperatorKind,
     ref SingleValueNode leftNode,
     ref SingleValueNode rightNode,
     out IEdmTypeReference typeReference)
 {
     stringAsEnum.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
 }
Ejemplo n.º 11
0
        private static OverloadResolutionResult<BinaryOperatorSignature> ResolveOverloads(BinaryOperatorKind kind, TypeSymbol leftOperandType, TypeSymbol rightOperandType)
        {
            var builtInSignatures = GetBuiltInSignatures(kind);

            if (BothTypesBuiltIn(leftOperandType, rightOperandType))
                return OverloadResolution.Perform(builtInSignatures, leftOperandType, rightOperandType);

            return OverloadResolutionResult<BinaryOperatorSignature>.None;
        }
Ejemplo n.º 12
0
 /// <summary>
 /// Promote the left and right operand types
 /// </summary>
 /// <param name="binaryOperatorKind">the operator kind</param>
 /// <param name="leftNode">the left operand</param>
 /// <param name="rightNode">the right operand</param>
 /// <param name="typeReference">type reference for the result BinaryOperatorNode.</param>
 public virtual void PromoteBinaryOperandTypes(
        BinaryOperatorKind binaryOperatorKind,
        ref SingleValueNode leftNode,
        ref SingleValueNode rightNode,
        out IEdmTypeReference typeReference)
 {
     typeReference = null;
     BinaryOperatorBinder.PromoteOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode);
 }
        /// <summary>
        /// Create a new BinaryOperatorQueryToken given the operator, left and right query.
        /// </summary>
        /// <param name="operatorKind">The operator represented by this node.</param>
        /// <param name="left">The left operand.</param>
        /// <param name="right">The right operand.</param>
        public BinaryOperatorQueryToken(BinaryOperatorKind operatorKind, QueryToken left, QueryToken right)
        {
            ExceptionUtils.CheckArgumentNotNull(left, "left");
            ExceptionUtils.CheckArgumentNotNull(right, "right");

            this.operatorKind = operatorKind;
            this.left = left;
            this.right = right;
        }
 private BoundExpression MakeBinaryOperator(
     CSharpSyntaxNode syntax,
     BinaryOperatorKind operatorKind,
     BoundExpression loweredLeft,
     BoundExpression loweredRight,
     TypeSymbol type,
     MethodSymbol method,
     bool isPointerElementAccess = false,
     bool isCompoundAssignment = false,
     BoundUnaryOperator applyParentUnaryOperator = null)
 {
     return MakeBinaryOperator(null, syntax, operatorKind, loweredLeft, loweredRight, type, method, isPointerElementAccess, isCompoundAssignment, applyParentUnaryOperator);
 }
Ejemplo n.º 15
0
        /// <summary>
        /// Promote the left and right operand types
        /// </summary>
        /// <param name="binaryOperatorKind">the operator kind</param>
        /// <param name="left">the left operand</param>
        /// <param name="right">the right operand</param>
        internal static void PromoteOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode left, ref SingleValueNode right)
        {
            IEdmTypeReference leftType;
            IEdmTypeReference rightType;
            if (!TypePromotionUtils.PromoteOperandTypes(binaryOperatorKind, left, right, out leftType, out rightType))
            {
                string leftTypeName = left.TypeReference == null ? "<null>" : left.TypeReference.FullName();
                string rightTypeName = right.TypeReference == null ? "<null>" : right.TypeReference.FullName();
                throw new ODataException(ODataErrorStrings.MetadataBinder_IncompatibleOperandsError(leftTypeName, rightTypeName, binaryOperatorKind));
            }

            left = MetadataBindingUtils.ConvertToTypeIfNeeded(left, leftType);
            right = MetadataBindingUtils.ConvertToTypeIfNeeded(right, rightType);
        }
        //$filter=EnterpriseName%20eq%20%27DIEGO_520%27
        public BinaryOperatorResolver(BinaryOperatorNode binaryOperator)
        {
            if (binaryOperator != null)
            {
                var property = binaryOperator.Left as SingleValuePropertyAccessNode ?? binaryOperator.Right as SingleValuePropertyAccessNode;
                var constant = binaryOperator.Left as ConstantNode ?? binaryOperator.Right as ConstantNode;

                if (property != null && property.Property != null && constant != null && constant.Value != null)
                {
                    Property = property.Property.Name;
                    Operator = binaryOperator.OperatorKind;
                    Value = constant.LiteralText;
                }
            }
        }
        private void AddDelegateOperation(BinaryOperatorKind kind, TypeSymbol delegateType,
            ArrayBuilder<BinaryOperatorSignature> operators)
        {
            switch (kind)
            {
                case BinaryOperatorKind.Equal:
                case BinaryOperatorKind.NotEqual:
                    operators.Add(new BinaryOperatorSignature(kind | BinaryOperatorKind.Delegate, delegateType, delegateType, Compilation.GetSpecialType(SpecialType.System_Boolean)));
                    break;

                case BinaryOperatorKind.Addition:
                case BinaryOperatorKind.Subtraction:
                default:
                    operators.Add(new BinaryOperatorSignature(kind | BinaryOperatorKind.Delegate, delegateType, delegateType, delegateType));
                    break;
            }
        }
Ejemplo n.º 18
0
 private static IEnumerable<BinaryOperatorSignature> GetBuiltInSignatures(BinaryOperatorKind kind)
 {
     switch (kind)
     {
         case BinaryOperatorKind.Multiply:
             return BuiltInMultiplySignatures;
         case BinaryOperatorKind.Divide:
             return BuiltInDivideSignatures;
         case BinaryOperatorKind.Modulo:
             return BuiltInModulusSignatures;
         case BinaryOperatorKind.Add:
             return BuiltInAddSignatures;
         case BinaryOperatorKind.Subtract:
             return BuiltInSubSignatures;
         case BinaryOperatorKind.Equal:
             return BuiltInEqualSignatures;
         case BinaryOperatorKind.NotEqual:
             return BuiltInNotEqualSignatures;
         case BinaryOperatorKind.Less:
             return BuiltInLessSignatures;
         case BinaryOperatorKind.LessEqual:
             return BuiltInLessOrEqualSignatures;
         case BinaryOperatorKind.Greater:
             return BuiltInGreaterSignatures;
         case BinaryOperatorKind.GreaterEqual:
             return BuiltInGreaterOrEqualSignatures;
         case BinaryOperatorKind.BitwiseXor:
             return BuiltInBitXorSignatures;
         case BinaryOperatorKind.BitwiseAnd:
             return BuiltInBitAndSignatures;
         case BinaryOperatorKind.BitwiseOr:
             return BuiltInBitOrSignatures;
         case BinaryOperatorKind.LeftShift:
             return BuiltInLeftShiftSignatures;
         case BinaryOperatorKind.RightShift:
             return BuiltInRightShiftSignatures;
         case BinaryOperatorKind.LogicalAnd:
             return BuiltInLogicalAndSignatures;
         case BinaryOperatorKind.LogicalOr:
             return BuiltInLogicalOrSignatures;
         default:
             throw new ArgumentOutOfRangeException(nameof(kind), kind.ToString());
     }
 }
Ejemplo n.º 19
0
        public override void PromoteBinaryOperandTypes(
            BinaryOperatorKind binaryOperatorKind,
            ref SingleValueNode leftNode,
            ref SingleValueNode rightNode,
            out IEdmTypeReference typeReference)
        {
            if (binaryOperatorKind == BinaryOperatorKind.Multiply
                && leftNode.TypeReference != null
                && leftNode.TypeReference.IsString()
                && rightNode.TypeReference != null
                && rightNode.TypeReference.IsInt32())
            {
                // The result type should be Edm.String, as it could be nullable or not, we just took the left
                // node's type reference.
                typeReference = leftNode.TypeReference;
                return;
            }

            // fallback
            base.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Promote the left and right operand types, supports enum property and string constant scenario.
        /// </summary>
        /// <param name="binaryOperatorKind">the operator kind</param>
        /// <param name="leftNode">the left operand</param>
        /// <param name="rightNode">the right operand</param>
        /// <param name="typeReference">type reference for the result BinaryOperatorNode.</param>
        public override void PromoteBinaryOperandTypes(
               BinaryOperatorKind binaryOperatorKind,
               ref SingleValueNode leftNode,
               ref SingleValueNode rightNode,
               out IEdmTypeReference typeReference)
        {
            typeReference = null;

            if (leftNode.TypeReference != null && rightNode.TypeReference != null)
            {
                if ((leftNode.TypeReference.IsEnum()) && (rightNode.TypeReference.IsString()) && rightNode is ConstantNode)
                {
                    string text = ((ConstantNode)rightNode).Value as string;
                    ODataEnumValue val;
                    IEdmTypeReference typeRef = leftNode.TypeReference;

                    if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val))
                    {
                        rightNode = new ConstantNode(val, text, typeRef);
                        return;
                    }
                }
                else if ((rightNode.TypeReference.IsEnum()) && (leftNode.TypeReference.IsString()) && leftNode is ConstantNode)
                {
                    string text = ((ConstantNode)leftNode).Value as string;
                    ODataEnumValue val;
                    IEdmTypeReference typeRef = rightNode.TypeReference;
                    if (TryParseEnum(typeRef.Definition as IEdmEnumType, text, out val))
                    {
                        leftNode = new ConstantNode(val, text, typeRef);
                        return;
                    }
                }
            }

            // fallback
            base.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
        }
Ejemplo n.º 21
0
        private BoundExpression RewritePointerNumericOperator(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind kind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            TypeSymbol returnType,
            bool isPointerElementAccess,
            bool isLeftPointer)
        {
            if (isLeftPointer)
            {
                loweredRight = MakeSizeOfMultiplication(loweredRight, (PointerTypeSymbol)loweredLeft.Type, kind.IsChecked());
            }
            else
            {
                loweredLeft = MakeSizeOfMultiplication(loweredLeft, (PointerTypeSymbol)loweredRight.Type, kind.IsChecked());
            }

            if (isPointerElementAccess)
            {
                Debug.Assert(kind.Operator() == BinaryOperatorKind.Addition);

                // NOTE: This is here to persist a bug in Dev10.  checked(p[n]) should be equivalent to checked(*(p + n)),
                // but Dev10 omits the check on the addition (though it retains the check on the multiplication of n by
                // the size).
                kind = kind & ~BinaryOperatorKind.Checked;
            }

            return new BoundBinaryOperator(
                            syntax,
                            kind,
                            loweredLeft,
                            loweredRight,
                            ConstantValue.NotAvailable,
                            null,
                            LookupResultKind.Viable,
                            returnType);
        }
Ejemplo n.º 22
0
        internal void GetSimpleBuiltInOperators(BinaryOperatorKind kind, ArrayBuilder <BinaryOperatorSignature> operators)
        {
            if (builtInOperators == null)
            {
                var logicalOperators = new ImmutableArray <BinaryOperatorSignature>[]
                {
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //multiplication
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //addition
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //subtraction
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //division
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //remainder
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //left shift
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //right shift
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //equal
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //not equal
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //greater than
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //less than
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //greater than or equal
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //less than or equal
                    ImmutableArray.Create <BinaryOperatorSignature>(GetSignature(BinaryOperatorKind.LogicalBoolAnd)), //and
                    ImmutableArray <BinaryOperatorSignature> .Empty,                                                  //xor
                    ImmutableArray.Create <BinaryOperatorSignature>(GetSignature(BinaryOperatorKind.LogicalBoolOr)),  //or
                };

                var nonLogicalOperators = new ImmutableArray <BinaryOperatorSignature>[]
                {
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntMultiplication),
                        GetSignature(BinaryOperatorKind.UIntMultiplication),
                        GetSignature(BinaryOperatorKind.LongMultiplication),
                        GetSignature(BinaryOperatorKind.ULongMultiplication),
                        GetSignature(BinaryOperatorKind.FloatMultiplication),
                        GetSignature(BinaryOperatorKind.DoubleMultiplication),
                        GetSignature(BinaryOperatorKind.DecimalMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedIntMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedUIntMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedLongMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedULongMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedFloatMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedDoubleMultiplication),
                        GetSignature(BinaryOperatorKind.LiftedDecimalMultiplication),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntAddition),
                        GetSignature(BinaryOperatorKind.UIntAddition),
                        GetSignature(BinaryOperatorKind.LongAddition),
                        GetSignature(BinaryOperatorKind.ULongAddition),
                        GetSignature(BinaryOperatorKind.FloatAddition),
                        GetSignature(BinaryOperatorKind.DoubleAddition),
                        GetSignature(BinaryOperatorKind.DecimalAddition),
                        GetSignature(BinaryOperatorKind.LiftedIntAddition),
                        GetSignature(BinaryOperatorKind.LiftedUIntAddition),
                        GetSignature(BinaryOperatorKind.LiftedLongAddition),
                        GetSignature(BinaryOperatorKind.LiftedULongAddition),
                        GetSignature(BinaryOperatorKind.LiftedFloatAddition),
                        GetSignature(BinaryOperatorKind.LiftedDoubleAddition),
                        GetSignature(BinaryOperatorKind.LiftedDecimalAddition),
                        GetSignature(BinaryOperatorKind.StringConcatenation),
                        GetSignature(BinaryOperatorKind.StringAndObjectConcatenation),
                        GetSignature(BinaryOperatorKind.ObjectAndStringConcatenation),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntSubtraction),
                        GetSignature(BinaryOperatorKind.UIntSubtraction),
                        GetSignature(BinaryOperatorKind.LongSubtraction),
                        GetSignature(BinaryOperatorKind.ULongSubtraction),
                        GetSignature(BinaryOperatorKind.FloatSubtraction),
                        GetSignature(BinaryOperatorKind.DoubleSubtraction),
                        GetSignature(BinaryOperatorKind.DecimalSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedIntSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedUIntSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedLongSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedULongSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedFloatSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedDoubleSubtraction),
                        GetSignature(BinaryOperatorKind.LiftedDecimalSubtraction),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntDivision),
                        GetSignature(BinaryOperatorKind.UIntDivision),
                        GetSignature(BinaryOperatorKind.LongDivision),
                        GetSignature(BinaryOperatorKind.ULongDivision),
                        GetSignature(BinaryOperatorKind.FloatDivision),
                        GetSignature(BinaryOperatorKind.DoubleDivision),
                        GetSignature(BinaryOperatorKind.DecimalDivision),
                        GetSignature(BinaryOperatorKind.LiftedIntDivision),
                        GetSignature(BinaryOperatorKind.LiftedUIntDivision),
                        GetSignature(BinaryOperatorKind.LiftedLongDivision),
                        GetSignature(BinaryOperatorKind.LiftedULongDivision),
                        GetSignature(BinaryOperatorKind.LiftedFloatDivision),
                        GetSignature(BinaryOperatorKind.LiftedDoubleDivision),
                        GetSignature(BinaryOperatorKind.LiftedDecimalDivision),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntRemainder),
                        GetSignature(BinaryOperatorKind.UIntRemainder),
                        GetSignature(BinaryOperatorKind.LongRemainder),
                        GetSignature(BinaryOperatorKind.ULongRemainder),
                        GetSignature(BinaryOperatorKind.FloatRemainder),
                        GetSignature(BinaryOperatorKind.DoubleRemainder),
                        GetSignature(BinaryOperatorKind.DecimalRemainder),
                        GetSignature(BinaryOperatorKind.LiftedIntRemainder),
                        GetSignature(BinaryOperatorKind.LiftedUIntRemainder),
                        GetSignature(BinaryOperatorKind.LiftedLongRemainder),
                        GetSignature(BinaryOperatorKind.LiftedULongRemainder),
                        GetSignature(BinaryOperatorKind.LiftedFloatRemainder),
                        GetSignature(BinaryOperatorKind.LiftedDoubleRemainder),
                        GetSignature(BinaryOperatorKind.LiftedDecimalRemainder),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntLeftShift),
                        GetSignature(BinaryOperatorKind.UIntLeftShift),
                        GetSignature(BinaryOperatorKind.LongLeftShift),
                        GetSignature(BinaryOperatorKind.ULongLeftShift),
                        GetSignature(BinaryOperatorKind.LiftedIntLeftShift),
                        GetSignature(BinaryOperatorKind.LiftedUIntLeftShift),
                        GetSignature(BinaryOperatorKind.LiftedLongLeftShift),
                        GetSignature(BinaryOperatorKind.LiftedULongLeftShift),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntRightShift),
                        GetSignature(BinaryOperatorKind.UIntRightShift),
                        GetSignature(BinaryOperatorKind.LongRightShift),
                        GetSignature(BinaryOperatorKind.ULongRightShift),
                        GetSignature(BinaryOperatorKind.LiftedIntRightShift),
                        GetSignature(BinaryOperatorKind.LiftedUIntRightShift),
                        GetSignature(BinaryOperatorKind.LiftedLongRightShift),
                        GetSignature(BinaryOperatorKind.LiftedULongRightShift),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntEqual),
                        GetSignature(BinaryOperatorKind.UIntEqual),
                        GetSignature(BinaryOperatorKind.LongEqual),
                        GetSignature(BinaryOperatorKind.ULongEqual),
                        GetSignature(BinaryOperatorKind.FloatEqual),
                        GetSignature(BinaryOperatorKind.DoubleEqual),
                        GetSignature(BinaryOperatorKind.DecimalEqual),
                        GetSignature(BinaryOperatorKind.BoolEqual),
                        GetSignature(BinaryOperatorKind.LiftedIntEqual),
                        GetSignature(BinaryOperatorKind.LiftedUIntEqual),
                        GetSignature(BinaryOperatorKind.LiftedLongEqual),
                        GetSignature(BinaryOperatorKind.LiftedULongEqual),
                        GetSignature(BinaryOperatorKind.LiftedFloatEqual),
                        GetSignature(BinaryOperatorKind.LiftedDoubleEqual),
                        GetSignature(BinaryOperatorKind.LiftedDecimalEqual),
                        GetSignature(BinaryOperatorKind.LiftedBoolEqual),
                        GetSignature(BinaryOperatorKind.ObjectEqual),
                        GetSignature(BinaryOperatorKind.StringEqual),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntNotEqual),
                        GetSignature(BinaryOperatorKind.UIntNotEqual),
                        GetSignature(BinaryOperatorKind.LongNotEqual),
                        GetSignature(BinaryOperatorKind.ULongNotEqual),
                        GetSignature(BinaryOperatorKind.FloatNotEqual),
                        GetSignature(BinaryOperatorKind.DoubleNotEqual),
                        GetSignature(BinaryOperatorKind.DecimalNotEqual),
                        GetSignature(BinaryOperatorKind.BoolNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedIntNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedUIntNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedLongNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedULongNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedFloatNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedDoubleNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedDecimalNotEqual),
                        GetSignature(BinaryOperatorKind.LiftedBoolNotEqual),
                        GetSignature(BinaryOperatorKind.ObjectNotEqual),
                        GetSignature(BinaryOperatorKind.StringNotEqual),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntGreaterThan),
                        GetSignature(BinaryOperatorKind.UIntGreaterThan),
                        GetSignature(BinaryOperatorKind.LongGreaterThan),
                        GetSignature(BinaryOperatorKind.ULongGreaterThan),
                        GetSignature(BinaryOperatorKind.FloatGreaterThan),
                        GetSignature(BinaryOperatorKind.DoubleGreaterThan),
                        GetSignature(BinaryOperatorKind.DecimalGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedIntGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedUIntGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedLongGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedULongGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedFloatGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedDoubleGreaterThan),
                        GetSignature(BinaryOperatorKind.LiftedDecimalGreaterThan),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntLessThan),
                        GetSignature(BinaryOperatorKind.UIntLessThan),
                        GetSignature(BinaryOperatorKind.LongLessThan),
                        GetSignature(BinaryOperatorKind.ULongLessThan),
                        GetSignature(BinaryOperatorKind.FloatLessThan),
                        GetSignature(BinaryOperatorKind.DoubleLessThan),
                        GetSignature(BinaryOperatorKind.DecimalLessThan),
                        GetSignature(BinaryOperatorKind.LiftedIntLessThan),
                        GetSignature(BinaryOperatorKind.LiftedUIntLessThan),
                        GetSignature(BinaryOperatorKind.LiftedLongLessThan),
                        GetSignature(BinaryOperatorKind.LiftedULongLessThan),
                        GetSignature(BinaryOperatorKind.LiftedFloatLessThan),
                        GetSignature(BinaryOperatorKind.LiftedDoubleLessThan),
                        GetSignature(BinaryOperatorKind.LiftedDecimalLessThan),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.UIntGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LongGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.ULongGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.FloatGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.DoubleGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.DecimalGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedIntGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedUIntGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedLongGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedULongGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedFloatGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedDoubleGreaterThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedDecimalGreaterThanOrEqual),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.UIntLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LongLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.ULongLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.FloatLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.DoubleLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.DecimalLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedIntLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedUIntLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedLongLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedULongLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedFloatLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedDoubleLessThanOrEqual),
                        GetSignature(BinaryOperatorKind.LiftedDecimalLessThanOrEqual),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntAnd),
                        GetSignature(BinaryOperatorKind.UIntAnd),
                        GetSignature(BinaryOperatorKind.LongAnd),
                        GetSignature(BinaryOperatorKind.ULongAnd),
                        GetSignature(BinaryOperatorKind.BoolAnd),
                        GetSignature(BinaryOperatorKind.LiftedIntAnd),
                        GetSignature(BinaryOperatorKind.LiftedUIntAnd),
                        GetSignature(BinaryOperatorKind.LiftedLongAnd),
                        GetSignature(BinaryOperatorKind.LiftedULongAnd),
                        GetSignature(BinaryOperatorKind.LiftedBoolAnd),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntXor),
                        GetSignature(BinaryOperatorKind.UIntXor),
                        GetSignature(BinaryOperatorKind.LongXor),
                        GetSignature(BinaryOperatorKind.ULongXor),
                        GetSignature(BinaryOperatorKind.BoolXor),
                        GetSignature(BinaryOperatorKind.LiftedIntXor),
                        GetSignature(BinaryOperatorKind.LiftedUIntXor),
                        GetSignature(BinaryOperatorKind.LiftedLongXor),
                        GetSignature(BinaryOperatorKind.LiftedULongXor),
                        GetSignature(BinaryOperatorKind.LiftedBoolXor),
                    }).AsImmutableOrNull(),
                    (new []
                    {
                        GetSignature(BinaryOperatorKind.IntOr),
                        GetSignature(BinaryOperatorKind.UIntOr),
                        GetSignature(BinaryOperatorKind.LongOr),
                        GetSignature(BinaryOperatorKind.ULongOr),
                        GetSignature(BinaryOperatorKind.BoolOr),
                        GetSignature(BinaryOperatorKind.LiftedIntOr),
                        GetSignature(BinaryOperatorKind.LiftedUIntOr),
                        GetSignature(BinaryOperatorKind.LiftedLongOr),
                        GetSignature(BinaryOperatorKind.LiftedULongOr),
                        GetSignature(BinaryOperatorKind.LiftedBoolOr),
                    }).AsImmutableOrNull(),
                };

                var allOperators = new[] { nonLogicalOperators, logicalOperators };

                Interlocked.CompareExchange(ref builtInOperators, allOperators, null);
            }

            operators.AddRange(builtInOperators[kind.IsLogical() ? 1 : 0][kind.OperatorIndex()]);
        }
Ejemplo n.º 23
0
        private BoundExpression MakeBuiltInIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            BoundExpression result;
            // If we have a built-in increment or decrement then things get a bit trickier. Suppose for example we have
            // a user-defined conversion from X to short and from short to X, but no user-defined increment operator on
            // X.  The increment portion of "++x" is then: (X)(short)((int)(short)x + 1). That is, first x must be
            // converted to short via an implicit user- defined conversion, then to int via an implicit numeric
            // conversion, then the addition is performed in integers. The resulting integer is converted back to short,
            // and then the short is converted to X.

            // This is the input and output type of the unary increment operator we're going to call.
            // That is, "short" in the example above.
            TypeSymbol unaryOperandType = GetUnaryOperatorType(node);

            // This is the kind of binary operator that we're going to realize the unary operator
            // as. That is, "int + int --> int" in the example above.
            BinaryOperatorKind binaryOperatorKind = GetCorrespondingBinaryOperator(node);

            binaryOperatorKind |= IsIncrement(node) ? BinaryOperatorKind.Addition : BinaryOperatorKind.Subtraction;

            // The "1" in the example above.
            ConstantValue constantOne = GetConstantOneForBinOp(binaryOperatorKind);

            Debug.Assert(constantOne != null);
            Debug.Assert(constantOne.SpecialType != SpecialType.None);
            Debug.Assert(binaryOperatorKind.OperandTypes() != 0);

            // The intput/output type of the binary operand. "int" in the example.
            TypeSymbol binaryOperandType = compilation.GetSpecialType(constantOne.SpecialType);

            // 1
            BoundExpression boundOne = MakeLiteral(
                syntax: node.Syntax,
                constantValue: constantOne,
                type: binaryOperandType);

            if (binaryOperatorKind.IsLifted())
            {
                binaryOperandType = compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(binaryOperandType);
                MethodSymbol ctor = GetNullableMethod(node.Syntax, binaryOperandType, SpecialMember.System_Nullable_T__ctor);
                boundOne = new BoundObjectCreationExpression(node.Syntax, ctor, boundOne);
            }

            // Now we construct the other operand to the binary addition. We start with just plain "x".
            BoundExpression binaryOperand = rewrittenValueToIncrement;

            bool @checked = node.OperatorKind.IsChecked();

            // If we need to make a conversion from the original operand type to the operand type of the
            // underlying increment operation, do it now.
            if (!node.OperandConversion.IsIdentity)
            {
                // (short)x
                binaryOperand = MakeConversion(
                    syntax: node.Syntax,
                    rewrittenOperand: binaryOperand,
                    conversion: node.OperandConversion,
                    rewrittenType: unaryOperandType,
                    @checked: @checked);
            }

            // Early-out for pointer increment - we don't need to convert the operands to a common type.
            if (node.OperatorKind.OperandTypes() == UnaryOperatorKind.Pointer)
            {
                Debug.Assert(binaryOperatorKind.OperandTypes() == BinaryOperatorKind.PointerAndInt);
                Debug.Assert(binaryOperand.Type.IsPointerType());
                Debug.Assert(boundOne.Type.SpecialType == SpecialType.System_Int32);
                return(MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperand.Type, method: null));
            }

            // If we need to make a conversion from the unary operator type to the binary operator type,
            // do it now.

            // (int)(short)x
            binaryOperand = MakeConversion(binaryOperand, binaryOperandType, @checked);

            // Perform the addition.

            // (int)(short)x + 1
            BoundExpression binOp;

            if (unaryOperandType.SpecialType == SpecialType.System_Decimal)
            {
                binOp = MakeDecimalIncDecOperator(node.Syntax, binaryOperatorKind, binaryOperand);
            }
            else if (unaryOperandType.IsNullableType() && unaryOperandType.GetNullableUnderlyingType().SpecialType == SpecialType.System_Decimal)
            {
                binOp = MakeLiftedDecimalIncDecOperator(node.Syntax, binaryOperatorKind, binaryOperand);
            }
            else
            {
                binOp = MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperandType, method: null);
            }

            // Generate the conversion back to the type of the unary operator.

            // (short)((int)(short)x + 1)
            result = MakeConversion(binOp, unaryOperandType, @checked);
            return(result);
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Produces a chain of equality (or inequality) checks combined logically with AND (or OR)
        /// </summary>
        private BoundExpression RewriteNonNullableNestedTupleOperators(TupleBinaryOperatorInfo.Multiple operators,
                                                                       BoundExpression left, BoundExpression right, TypeSymbol type,
                                                                       ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> effects, BinaryOperatorKind operatorKind)
        {
            ImmutableArray <TupleBinaryOperatorInfo> nestedOperators = operators.Operators;

            BoundExpression currentResult = null;

            for (int i = 0; i < nestedOperators.Length; i++)
            {
                BoundExpression leftElement        = GetTuplePart(left, i);
                BoundExpression rightElement       = GetTuplePart(right, i);
                BoundExpression nextLogicalOperand = RewriteTupleOperator(nestedOperators[i], leftElement, rightElement, type, temps, operatorKind);
                if (currentResult is null)
                {
                    currentResult = nextLogicalOperand;
                }
                else
                {
                    var logicalOperator = operatorKind == BinaryOperatorKind.Equal ? BinaryOperatorKind.LogicalBoolAnd : BinaryOperatorKind.LogicalBoolOr;
                    currentResult = _factory.Binary(logicalOperator, type, currentResult, nextLogicalOperand);
                }
            }

            return(currentResult);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Produce an element-wise comparison and logic to ensure the result is a bool type.
        ///
        /// If an element-wise comparison doesn't return bool, then:
        /// - if it is dynamic, we'll do `!(comparisonResult.false)` or `comparisonResult.true`
        /// - if it implicitly converts to bool, we'll just do the conversion
        /// - otherwise, we'll do `!(comparisonResult.false)` or `comparisonResult.true` (as we'd do for `if` or `while`)
        /// </summary>
        private BoundExpression RewriteTupleSingleOperator(TupleBinaryOperatorInfo.Single single,
                                                           BoundExpression left, BoundExpression right, TypeSymbol boolType, BinaryOperatorKind operatorKind)
        {
            if (single.Kind.IsDynamic())
            {
                // Produce
                // !((left == right).op_false)
                // (left != right).op_true

                BoundExpression dynamicResult = _dynamicFactory.MakeDynamicBinaryOperator(single.Kind, left, right, isCompoundAssignment: false, _compilation.DynamicType).ToExpression();
                if (operatorKind == BinaryOperatorKind.Equal)
                {
                    return(_factory.Not(MakeUnaryOperator(UnaryOperatorKind.DynamicFalse, left.Syntax, method: null, dynamicResult, boolType)));
                }
                else
                {
                    return(MakeUnaryOperator(UnaryOperatorKind.DynamicTrue, left.Syntax, method: null, dynamicResult, boolType));
                }
            }

            if (left.IsLiteralNull() && right.IsLiteralNull())
            {
                // For `null == null` this is special-cased during initial binding
                return(new BoundLiteral(left.Syntax, ConstantValue.Create(operatorKind == BinaryOperatorKind.Equal), boolType));
            }

            // We leave both operands in nullable-null conversions unconverted, MakeBinaryOperator has special for null-literal
            bool            isNullableNullConversion = single.Kind.OperandTypes() == BinaryOperatorKind.NullableNull;
            BoundExpression convertedLeft            = isNullableNullConversion
                ? left
                : MakeConversionNode(left.Syntax, left, single.LeftConversion, single.LeftConvertedTypeOpt, @checked: false);

            BoundExpression convertedRight = isNullableNullConversion
                ? right
                : MakeConversionNode(right.Syntax, right, single.RightConversion, single.RightConvertedTypeOpt, @checked: false);

            BoundExpression        binary         = MakeBinaryOperator(_factory.Syntax, single.Kind, convertedLeft, convertedRight, single.MethodSymbolOpt?.ReturnType ?? boolType, single.MethodSymbolOpt);
            UnaryOperatorSignature boolOperator   = single.BoolOperator;
            Conversion             boolConversion = single.ConversionForBool;

            BoundExpression result;

            if (boolOperator.Kind != UnaryOperatorKind.Error)
            {
                // Produce
                // !((left == right).op_false)
                // (left != right).op_true
                BoundExpression convertedBinary = MakeConversionNode(_factory.Syntax, binary, boolConversion, boolOperator.OperandType, @checked: false);

                Debug.Assert(boolOperator.ReturnType.SpecialType == SpecialType.System_Boolean);
                result = MakeUnaryOperator(boolOperator.Kind, binary.Syntax, boolOperator.Method, convertedBinary, boolType);

                if (operatorKind == BinaryOperatorKind.Equal)
                {
                    result = _factory.Not(result);
                }
            }
            else if (!boolConversion.IsIdentity)
            {
                // Produce
                // (bool)(left == right)
                // (bool)(left != right)
                result = MakeConversionNode(_factory.Syntax, binary, boolConversion, boolType, @checked: false);
            }
            else
            {
                result = binary;
            }

            return(result);
        }
Ejemplo n.º 26
0
 public static bool IsLogical(this BinaryOperatorKind kind)
 {
     return(0 != (kind & BinaryOperatorKind.Logical));
 }
Ejemplo n.º 27
0
 public static bool IsDynamic(this BinaryOperatorKind kind)
 {
     return(kind.OperandTypes() == BinaryOperatorKind.Dynamic);
 }
Ejemplo n.º 28
0
        private string BuildFromPropertyNode(SingleValuePropertyAccessNode left, SingleValueNode right, BinaryOperatorKind operatorKind)
        {
            string result = string.Empty;

            if (right is ConstantNode)
            {
                result = BuildSingleClause(left, right as ConstantNode, operatorKind);
            }

            var rightSource = (right as ConvertNode)?.Source;

            if (rightSource is ConstantNode)
            {
                result = BuildSingleClause(left, rightSource as ConstantNode, operatorKind);
            }

            return(result);
        }
Ejemplo n.º 29
0
        private string BuildSingleClause(SingleValuePropertyAccessNode propertyNode, ConstantNode valueNode, BinaryOperatorKind operatorKind)
        {
            string operatorString = string.Empty;

            switch (operatorKind)
            {
            case BinaryOperatorKind.Equal:
                operatorString = "=";
                break;

            case BinaryOperatorKind.NotEqual:
                operatorString = "!=";
                break;

            case BinaryOperatorKind.GreaterThan:
                operatorString = ">";
                break;

            case BinaryOperatorKind.GreaterThanOrEqual:
                operatorString = ">=";
                break;

            case BinaryOperatorKind.LessThan:
                operatorString = "<";
                break;

            case BinaryOperatorKind.LessThanOrEqual:
                operatorString = "<=";
                break;
            }

            string valueString = valueNode.Value?.ToString() ?? "null";

            if (valueNode.Value == null)
            {
                if (operatorKind == BinaryOperatorKind.Equal)
                {
                    return($"({propertyNode.Property.Name} IS NULL)");
                }

                if (operatorKind == BinaryOperatorKind.NotEqual)
                {
                    return($"({propertyNode.Property.Name} IS NOT NULL)");
                }
            }

            return($"({propertyNode.Property.Name} {operatorString} {valueString})");
        }
Ejemplo n.º 30
0
        private static IEnumerable <BinaryOperatorSignature> GetBuiltInSignatures(BinaryOperatorKind kind)
        {
            switch (kind)
            {
            case BinaryOperatorKind.Multiply:
                return(BuiltInMultiplySignatures);

            case BinaryOperatorKind.Divide:
                return(BuiltInDivideSignatures);

            case BinaryOperatorKind.Modulo:
                return(BuiltInModulusSignatures);

            case BinaryOperatorKind.Add:
                return(BuiltInAddSignatures);

            case BinaryOperatorKind.Subtract:
                return(BuiltInSubSignatures);

            case BinaryOperatorKind.Equal:
                return(BuiltInEqualSignatures);

            case BinaryOperatorKind.NotEqual:
                return(BuiltInNotEqualSignatures);

            case BinaryOperatorKind.Less:
                return(BuiltInLessSignatures);

            case BinaryOperatorKind.LessEqual:
                return(BuiltInLessOrEqualSignatures);

            case BinaryOperatorKind.Greater:
                return(BuiltInGreaterSignatures);

            case BinaryOperatorKind.GreaterEqual:
                return(BuiltInGreaterOrEqualSignatures);

            case BinaryOperatorKind.BitwiseXor:
                return(BuiltInBitXorSignatures);

            case BinaryOperatorKind.BitwiseAnd:
                return(BuiltInBitAndSignatures);

            case BinaryOperatorKind.BitwiseOr:
                return(BuiltInBitOrSignatures);

            case BinaryOperatorKind.LeftShift:
                return(BuiltInLeftShiftSignatures);

            case BinaryOperatorKind.RightShift:
                return(BuiltInRightShiftSignatures);

            case BinaryOperatorKind.LogicalAnd:
                return(BuiltInLogicalAndSignatures);

            case BinaryOperatorKind.LogicalOr:
                return(BuiltInLogicalOrSignatures);

            default:
                throw new ArgumentOutOfRangeException(nameof(kind), kind.ToString());
            }
        }
Ejemplo n.º 31
0
        private static OverloadResolutionResult <BinaryOperatorSignature> ResolveOverloads(BinaryOperatorKind kind, TypeSymbol leftOperandType, TypeSymbol rightOperandType)
        {
            var builtInSignatures = GetBuiltInSignatures(kind);

            if (BothTypesBuiltIn(leftOperandType, rightOperandType))
            {
                return(OverloadResolution.Perform(builtInSignatures, leftOperandType, rightOperandType));
            }

            return(OverloadResolutionResult <BinaryOperatorSignature> .None);
        }
Ejemplo n.º 32
0
 public static OverloadResolutionResult <BinaryOperatorSignature> Resolve(BinaryOperatorKind kind, TypeSymbol leftOperandType, TypeSymbol rightOperandType)
 {
     return(ResolveOverloads(kind, leftOperandType, rightOperandType));
 }
Ejemplo n.º 33
0
            private QueryNode ParsePropertyAccessNode()
            {
                QueryNode result = null;

                QueryNode          leftNode     = null;
                BinaryOperatorKind operatorKind = BinaryOperatorKind.None;
                QueryNode          rightNode    = null;

                while (this.tokens.Count > 0)
                {
                    var token = this.tokens.Dequeue();

                    switch (token.TokenType)
                    {
                    case TokenType.BinaryOperator:
                        if (operatorKind != BinaryOperatorKind.None)
                        {
                            result    = new BinaryOperatorNode(leftNode, operatorKind, rightNode);
                            leftNode  = null;
                            rightNode = null;
                        }

                        operatorKind = token.Value.ToBinaryOperatorKind();
                        break;

                    case TokenType.OpenParentheses:
                        this.groupingDepth++;
                        break;

                    case TokenType.CloseParentheses:
                        this.groupingDepth--;
                        break;

                    case TokenType.FunctionName:
                        if (leftNode == null)
                        {
                            leftNode = new FunctionCallNode(token.Value);
                        }
                        else if (rightNode == null)
                        {
                            rightNode = new FunctionCallNode(token.Value);
                        }

                        break;

                    case TokenType.PropertyName:
                        var propertyAccessNode = new PropertyAccessNode(this.model.GetProperty(token.Value));

                        if (leftNode == null)
                        {
                            leftNode = propertyAccessNode;
                        }
                        else if (rightNode == null)
                        {
                            rightNode = propertyAccessNode;
                        }

                        break;

                    case TokenType.Date:
                    case TokenType.DateTimeOffset:
                    case TokenType.Decimal:
                    case TokenType.Double:
                    case TokenType.Duration:
                    case TokenType.Enum:
                    case TokenType.False:
                    case TokenType.Guid:
                    case TokenType.Integer:
                    case TokenType.Null:
                    case TokenType.Single:
                    case TokenType.String:
                    case TokenType.TimeOfDay:
                    case TokenType.True:
                        rightNode = ConstantNodeParser.ParseConstantNode(token);
                        break;
                    }
                }

                result = result == null
                    ? new BinaryOperatorNode(leftNode, operatorKind, rightNode)
                    : new BinaryOperatorNode(result, operatorKind, leftNode ?? rightNode);

                return(result);
            }
Ejemplo n.º 34
0
 public BinaryOperatorSearcherItemData(BinaryOperatorKind kind)
 {
     Kind = kind;
 }
Ejemplo n.º 35
0
 public static bool IsLifted(this BinaryOperatorKind kind)
 {
     return(0 != (kind & BinaryOperatorKind.Lifted));
 }
Ejemplo n.º 36
0
        private BoundExpression RewriteLiftedBinaryOperator(CSharpSyntaxNode syntax, BinaryOperatorKind operatorKind, BoundExpression loweredLeft, BoundExpression loweredRight, TypeSymbol type, MethodSymbol method)
        {
            var conditionalLeft = loweredLeft as BoundLoweredConditionalAccess;

            // NOTE: we could in theory handle side-effecting loweredRight here too
            //       by including it as a part of whenNull, but there is a concern 
            //       that it can lead to code duplication
            var optimize = conditionalLeft != null &&
                !ReadIsSideeffecting(loweredRight) &&
                (conditionalLeft.WhenNullOpt == null || conditionalLeft.WhenNullOpt.IsDefaultValue());

            if (optimize)
            {
                loweredLeft = conditionalLeft.WhenNotNull;
            }

            var result = operatorKind.IsComparison() ?
                            operatorKind.IsUserDefined() ?
                                LowerLiftedUserDefinedComparisonOperator(syntax, operatorKind, loweredLeft, loweredRight, method) :
                                LowerLiftedBuiltInComparisonOperator(syntax, operatorKind, loweredLeft, loweredRight) :
                            LowerLiftedBinaryArithmeticOperator(syntax, operatorKind, loweredLeft, loweredRight, type, method);

            if (optimize)
            {
                BoundExpression whenNullOpt = null;

                // for all operators null-in means null-out
                // except for the Equal/NotEqual since null == null ==> true
                if (operatorKind.Operator() == BinaryOperatorKind.NotEqual ||
                    operatorKind.Operator() == BinaryOperatorKind.Equal)
                {
                    whenNullOpt = RewriteLiftedBinaryOperator(syntax, operatorKind, _factory.Default(loweredLeft.Type), loweredRight, type, method);
                }

                result = conditionalLeft.Update(
                    conditionalLeft.Receiver,
                    conditionalLeft.HasValueMethodOpt,
                    whenNotNull: result,
                    whenNullOpt: whenNullOpt,
                    id: conditionalLeft.Id,
                    type: result.Type
                );
            }

            return result;
        }
Ejemplo n.º 37
0
 public static bool IsChecked(this BinaryOperatorKind kind)
 {
     return(0 != (kind & BinaryOperatorKind.Checked));
 }
Ejemplo n.º 38
0
        private BoundExpression LowerUserDefinedBinaryOperator(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind operatorKind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            TypeSymbol type,
            MethodSymbol method)
        {
            Debug.Assert(!operatorKind.IsLogical());

            if (operatorKind.IsLifted())
            {
                return RewriteLiftedBinaryOperator(syntax, operatorKind, loweredLeft, loweredRight, type, method);
            }

            // Otherwise, nothing special here.
            Debug.Assert((object)method != null);
            Debug.Assert(method.ReturnType == type);
            return BoundCall.Synthesized(syntax, null, method, loweredLeft, loweredRight);
        }
Ejemplo n.º 39
0
        private BoundExpression RewriteTupleOperator(TupleBinaryOperatorInfo @operator,
                                                     BoundExpression left, BoundExpression right, TypeSymbol boolType,
                                                     ArrayBuilder <LocalSymbol> temps, BinaryOperatorKind operatorKind)
        {
            switch (@operator.InfoKind)
            {
            case TupleBinaryOperatorInfoKind.Multiple:
                return(RewriteTupleNestedOperators((TupleBinaryOperatorInfo.Multiple)@operator, left, right, boolType, temps, operatorKind));

            case TupleBinaryOperatorInfoKind.Single:
                return(RewriteTupleSingleOperator((TupleBinaryOperatorInfo.Single)@operator, left, right, boolType, operatorKind));

            case TupleBinaryOperatorInfoKind.NullNull:
                var nullnull = (TupleBinaryOperatorInfo.NullNull)@operator;
                return(new BoundLiteral(left.Syntax, ConstantValue.Create(nullnull.Kind == BinaryOperatorKind.Equal), boolType));

            default:
                throw ExceptionUtilities.UnexpectedValue(@operator.InfoKind);
            }
        }
Ejemplo n.º 40
0
        private BoundExpression LowerLiftedBuiltInComparisonOperator(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind kind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight)
        {
            // SPEC: For the equality operators == != :
            // SPEC: The lifted operator considers two null values equal and a null value unequal to
            // SPEC: any non-null value. If both operands are non-null the lifted operator unwraps
            // SPEC: the operands and applies the underlying operator to produce the bool result.
            // SPEC:
            // SPEC: For the relational operators < > <= >= :
            // SPEC: The lifted operator produces the value false if one or both operands
            // SPEC: are null. Otherwise the lifted operator unwraps the operands and
            // SPEC: applies the underlying operator to produce the bool result.

            // Note that this means that x == y is true but x <= y is false if both are null.
            // x <= y is not the same as (x < y) || (x == y).

            // Start with some simple optimizations for cases like one side being null.
            BoundExpression optimized = TrivialLiftedComparisonOperatorOptimizations(syntax, kind, loweredLeft, loweredRight, null);
            if (optimized != null)
            {
                return optimized;
            }

            // We rewrite x == y as 
            //
            // tempx = x; 
            // tempy = y;
            // result = tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue == tempy.HasValue : 
            //          false;
            //
            // and x != y as
            //
            // tempx = x; 
            // tempy = y;
            // result = tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue != tempy.HasValue : 
            //          true;
            //
            // Otherwise, we rewrite x OP y as
            //
            // tempx = x;
            // tempy = y;
            // result = tempx.GetValueOrDefault() OP tempy.GetValueOrDefault() ?
            //          tempx.HasValue & tempy.HasValue :
            //          false;
            //
            // Note that there is no reason to generate "&&" over "&"; the cost of
            // the added code for the conditional branch would be about the same as simply doing 
            // the bitwise & in the first place.
            //
            // We have not yet optimized the case where we have a known-not-null value on one side, 
            // and an unknown value on the other. In those cases we will still generate a temp, but
            // we will not generate the call to the unnecessary nullable ctor or to GetValueOrDefault.
            // Rather, we will generate the value's temp instead of a call to GetValueOrDefault, and generate
            // literal true for HasValue. The tree construction methods we call will use those constants
            // to eliminate unnecessary branches.

            BoundExpression xNonNull = NullableAlwaysHasValue(loweredLeft);
            BoundExpression yNonNull = NullableAlwaysHasValue(loweredRight);

            BoundAssignmentOperator tempAssignmentX;
            BoundLocal boundTempX = _factory.StoreToTemp(xNonNull ?? loweredLeft, out tempAssignmentX);
            BoundAssignmentOperator tempAssignmentY;
            BoundLocal boundTempY = _factory.StoreToTemp(yNonNull ?? loweredRight, out tempAssignmentY);

            BoundExpression callX_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempX);
            BoundExpression callY_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempY);
            BoundExpression callX_HasValue = MakeOptimizedHasValue(syntax, boundTempX);
            BoundExpression callY_HasValue = MakeOptimizedHasValue(syntax, boundTempY);

            // tempx.GetValueOrDefault() == tempy.GetValueOrDefault()
            BinaryOperatorKind operatorKind = kind.Operator();
            BinaryOperatorKind conditionOperator = operatorKind == BinaryOperatorKind.NotEqual ?
                BinaryOperatorKind.Equal :
                operatorKind;
            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression condition = MakeBinaryOperator(
                syntax: syntax,
                operatorKind: conditionOperator.WithType(kind.OperandTypes()),
                loweredLeft: callX_GetValueOrDefault,
                loweredRight: callY_GetValueOrDefault,
                type: boolType,
                method: null);

            BinaryOperatorKind consequenceOperator;
            switch (operatorKind)
            {
                case BinaryOperatorKind.Equal:
                    consequenceOperator = BinaryOperatorKind.BoolEqual;
                    break;
                case BinaryOperatorKind.NotEqual:
                    consequenceOperator = BinaryOperatorKind.BoolNotEqual;
                    break;
                default:
                    consequenceOperator = BinaryOperatorKind.BoolAnd;
                    break;
            }

            // tempx.HasValue == tempy.HasValue
            BoundExpression consequence = MakeBinaryOperator(
                syntax: syntax,
                operatorKind: consequenceOperator,
                loweredLeft: callX_HasValue,
                loweredRight: callY_HasValue,
                type: boolType,
                method: null);

            // false
            BoundExpression alternative = this.MakeBooleanConstant(syntax, operatorKind == BinaryOperatorKind.NotEqual);

            // tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue == tempy.HasValue : 
            //          false;
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: boolType);

            // tempx = x; 
            // tempy = y;
            // result = tempx.GetValueOrDefault() == tempy.GetValueOrDefault() ? 
            //          tempx.HasValue == tempy.HasValue : 
            //          false;
            return new BoundSequence(
                syntax: syntax,
                locals: ImmutableArray.Create<LocalSymbol>(boundTempX.LocalSymbol, boundTempY.LocalSymbol),
                sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignmentX, tempAssignmentY),
                value: conditionalExpression,
                type: boolType);
        }
Ejemplo n.º 41
0
        private BoundExpression MakeLiftedDecimalIncDecOperator(CSharpSyntaxNode syntax, BinaryOperatorKind oper, BoundExpression operand)
        {
            Debug.Assert(operand.Type.IsNullableType() && operand.Type.GetNullableUnderlyingType().SpecialType == SpecialType.System_Decimal);

            // This method assumes that operand is already a temporary and so there is no need to copy it again.
            MethodSymbol method            = GetDecimalIncDecOperator(oper);
            MethodSymbol hasValue          = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T_get_HasValue);
            MethodSymbol getValueOrDefault = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
            MethodSymbol ctor = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T__ctor);

            // x.HasValue
            BoundExpression condition = BoundCall.Synthesized(syntax, operand, hasValue);
            // x.GetValueOrDefault()
            BoundExpression getValueCall = BoundCall.Synthesized(syntax, operand, getValueOrDefault);
            // op_Inc(x.GetValueOrDefault())
            BoundExpression methodCall = BoundCall.Synthesized(syntax, null, method, getValueCall);
            // new decimal?(op_Inc(x.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, methodCall);
            // default(decimal?)
            BoundExpression alternative = new BoundDefaultOperator(syntax, null, operand.Type);

            // x.HasValue ? new decimal?(op_Inc(x.GetValueOrDefault())) : default(decimal?)
            return(RewriteConditionalOperator(syntax, condition, consequence, alternative, ConstantValue.NotAvailable, operand.Type));
        }
Ejemplo n.º 42
0
        /// <summary>Checks that the operands (possibly promoted) are valid for the specified operation.</summary>
        /// <param name="operatorKind">The operator kind to promote the operand types for.</param>
        /// <param name="leftNode">The left operand node.</param>
        /// <param name="rightNode">The right operand node.</param>
        /// <param name="left">The left operand type after promotion.</param>
        /// <param name="right">The right operand type after promotion.</param>
        /// <returns>True if a valid function signature was found that matches the given types after any necessary promotions are made.
        /// False if there is no binary operators </returns>
        internal static bool PromoteOperandTypes(BinaryOperatorKind operatorKind, SingleValueNode leftNode, SingleValueNode rightNode, out IEdmTypeReference left, out IEdmTypeReference right)
        {
            left = leftNode.TypeReference;
            right = rightNode.TypeReference;

            // The types for the operands can be null
            // if they (a) represent the null literal or (b) represent an open type/property.
            // If both argument types are null we lack type information on both sides and cannot promote arguments.
            if (left == null && right == null)
            {
                // if we find null literals or open properties on both sides we cannot promote; the result type will also be null
                return true;
            }

            if (operatorKind == BinaryOperatorKind.NotEqual || operatorKind == BinaryOperatorKind.Equal)
            {
                if (TryHandleEqualityOperatorForEntityOrComplexTypes(ref left, ref right))
                {
                    return true;
                }

                // enum and spatial type support equality operator for null operand:
                if ((left == null) && (right != null) && (right.IsEnum() || right is IEdmSpatialTypeReference))
                {
                    left = right;
                    return true;
                }

                if ((right == null) && (left != null) && (left.IsEnum() || left is IEdmSpatialTypeReference))
                {
                    right = left;
                    return true;
                }
            }

            // enum support, check type full names
            if (left != null && right != null && left.IsEnum() && right.IsEnum())
            {
                return string.Equals(left.FullName(), right.FullName(), StringComparison.Ordinal);
            }

            // type definition support, treat type definitions as their underlying types.
            if (left != null && left.IsTypeDefinition())
            {
                left = left.AsPrimitive();
            }

            if (right != null && right.IsTypeDefinition())
            {
                right = right.AsPrimitive();
            }

            // Except for above, binary operators are only supported on primitive types
            if (left != null && !left.IsODataPrimitiveTypeKind() || right != null && !right.IsODataPrimitiveTypeKind())
            {
                return false;
            }

            // The following will match primitive argument types to build in function signatures, choosing the best one possible.
            FunctionSignature[] signatures = GetFunctionSignatures(operatorKind);

            SingleValueNode[] argumentNodes = new SingleValueNode[] { leftNode, rightNode };
            IEdmTypeReference[] argumentTypes = new IEdmTypeReference[] { left, right };
            bool success = FindBestSignature(signatures, argumentNodes, argumentTypes) == 1;

            if (success)
            {
                left = argumentTypes[0];
                right = argumentTypes[1];

                if (left == null)
                {
                    left = right;
                }
                else if (right == null)
                {
                    right = left;
                }
            }

            return success;
        }
Ejemplo n.º 43
0
        private BoundExpression RewriteTupleNestedOperators(TupleBinaryOperatorInfo.Multiple operators, BoundExpression left, BoundExpression right,
                                                            TypeSymbol boolType, ArrayBuilder <LocalSymbol> temps, BinaryOperatorKind operatorKind)
        {
            left  = Binder.GiveTupleTypeToDefaultLiteralIfNeeded(left, right.Type);
            right = Binder.GiveTupleTypeToDefaultLiteralIfNeeded(right, left.Type);

            // If either left or right is nullable, produce:
            //
            //      // outer sequence
            //      leftHasValue = left.HasValue; (or true if !leftNullable)
            //      leftHasValue == right.HasValue (or true if !rightNullable)
            //          ? leftHasValue ? ... inner sequence ... : true/false
            //          : false/true
            //
            // where inner sequence is:
            //      leftValue = left.GetValueOrDefault(); (or left if !leftNullable)
            //      rightValue = right.GetValueOrDefault(); (or right if !rightNullable)
            //      ... logical expression using leftValue and rightValue ...
            //
            // and true/false and false/true depend on operatorKind (== vs. !=)
            //
            // But if neither is nullable, then just produce the inner sequence.
            //
            // Note: all the temps are created in a single bucket (rather than different scopes of applicability) for simplicity

            var outerEffects = ArrayBuilder <BoundExpression> .GetInstance();

            var innerEffects = ArrayBuilder <BoundExpression> .GetInstance();

            BoundExpression leftHasValue, leftValue;
            bool            isLeftNullable;

            MakeNullableParts(left, temps, innerEffects, outerEffects, saveHasValue: true, out leftHasValue, out leftValue, out isLeftNullable);

            BoundExpression rightHasValue, rightValue;
            bool            isRightNullable;

            // no need for local for right.HasValue since used once
            MakeNullableParts(right, temps, innerEffects, outerEffects, saveHasValue: false, out rightHasValue, out rightValue, out isRightNullable);

            // Produces:
            //     ... logical expression using leftValue and rightValue ...
            BoundExpression logicalExpression = RewriteNonNullableNestedTupleOperators(operators, leftValue, rightValue, boolType, temps, innerEffects, operatorKind);

            // Produces:
            //     leftValue = left.GetValueOrDefault(); (or left if !leftNullable)
            //     rightValue = right.GetValueOrDefault(); (or right if !rightNullable)
            //     ... logical expression using leftValue and rightValue ...
            BoundExpression innerSequence = MakeSequenceOrResultValue(locals: ImmutableArray <LocalSymbol> .Empty, innerEffects.ToImmutableAndFree(), logicalExpression);

            if (!isLeftNullable && !isRightNullable)
            {
                // The outer sequence degenerates when we know that both `leftHasValue` and `rightHasValue` are true
                return(innerSequence);
            }

            bool boolValue = operatorKind == BinaryOperatorKind.Equal; // true/false

            if (rightHasValue.ConstantValue == ConstantValue.False)
            {
                // The outer sequence degenerates when we known that `rightHasValue` is false
                // Produce: !leftHasValue (or leftHasValue for inequality comparison)
                return(MakeSequenceOrResultValue(ImmutableArray <LocalSymbol> .Empty, outerEffects.ToImmutableAndFree(),
                                                 returnValue: boolValue?_factory.Not(leftHasValue) : leftHasValue));
            }

            if (leftHasValue.ConstantValue == ConstantValue.False)
            {
                // The outer sequence degenerates when we known that `leftHasValue` is false
                // Produce: !rightHasValue (or rightHasValue for inequality comparison)
                return(MakeSequenceOrResultValue(ImmutableArray <LocalSymbol> .Empty, outerEffects.ToImmutableAndFree(),
                                                 returnValue: boolValue?_factory.Not(rightHasValue) : rightHasValue));
            }

            // outer sequence:
            //      leftHasValue == rightHasValue
            //          ? leftHasValue ? ... inner sequence ... : true/false
            //          : false/true
            BoundExpression outerSequence =
                MakeSequenceOrResultValue(ImmutableArray <LocalSymbol> .Empty, outerEffects.ToImmutableAndFree(),
                                          _factory.Conditional(
                                              _factory.Binary(BinaryOperatorKind.Equal, boolType, leftHasValue, rightHasValue),
                                              _factory.Conditional(leftHasValue, innerSequence, MakeBooleanConstant(right.Syntax, boolValue), boolType),
                                              MakeBooleanConstant(right.Syntax, !boolValue),
                                              boolType));

            return(outerSequence);
        }
Ejemplo n.º 44
0
        public static Expression <Func <TModel, bool> > FilterObjectSet(SingleValuePropertyAccessNode rule, ConstantNode constant, BinaryOperatorKind kind, string name = "model")
        {
            Type type = typeof(TModel);
            var  par  = Expression.Parameter(type, name);

            Type       fieldPropertyType;
            Expression fieldPropertyExpression;

            FieldInfo fieldInfo = type.GetField(rule.Property.Name);

            if (fieldInfo == null)
            {
                PropertyInfo propertyInfo = type.GetProperty(rule.Property.Name);

                if (propertyInfo == null)
                {
                    throw new Exception();
                }

                fieldPropertyType       = propertyInfo.PropertyType;
                fieldPropertyExpression = Expression.Property(par, propertyInfo);
            }
            else
            {
                fieldPropertyType       = fieldInfo.FieldType;
                fieldPropertyExpression = Expression.Field(par, fieldInfo);
            }
            object data2 = null;

            if (fieldPropertyType.IsGenericType && fieldPropertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                System.ComponentModel.TypeConverter conv = System.ComponentModel.TypeDescriptor.GetConverter(fieldPropertyType);
                data2 = conv.ConvertFrom(constant.LiteralText);
                //data2 = Convert.ChangeType(constant.LiteralText, Nullable.GetUnderlyingType());
            }
            else
            {
                data2 = Convert.ChangeType(constant.LiteralText, fieldPropertyType);
            }

            if (fieldPropertyType == typeof(string))
            {
                data2 = data2.ToString().Replace("'", "");
            }
            BinaryExpression eq = null;

            switch (kind)
            {
            case BinaryOperatorKind.Or:
                eq = Expression.Or(fieldPropertyExpression,
                                   Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.And:
                eq = Expression.And(fieldPropertyExpression,
                                    Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Equal:
                eq = Expression.Equal(fieldPropertyExpression,
                                      Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.NotEqual:
                eq = Expression.NotEqual(fieldPropertyExpression,
                                         Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.GreaterThan:
                eq = Expression.GreaterThan(fieldPropertyExpression,
                                            Expression.Constant(data2));
                break;

            case BinaryOperatorKind.GreaterThanOrEqual:
                eq = Expression.GreaterThanOrEqual(fieldPropertyExpression,
                                                   Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.LessThan:
                eq = Expression.LessThan(fieldPropertyExpression,
                                         Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.LessThanOrEqual:
                eq = Expression.LessThanOrEqual(fieldPropertyExpression,
                                                Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Add:
                eq = Expression.Add(fieldPropertyExpression,
                                    Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Subtract:
                eq = Expression.Subtract(fieldPropertyExpression,
                                         Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Multiply:
                eq = Expression.Multiply(fieldPropertyExpression,
                                         Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Divide:
                eq = Expression.Divide(fieldPropertyExpression,
                                       Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Modulo:
                eq = Expression.Modulo(fieldPropertyExpression,
                                       Expression.Constant(data2, fieldPropertyType));
                break;

            case BinaryOperatorKind.Has:
                break;
            }
            ;
            return(Expression.Lambda <Func <TModel, bool> >(eq, par));
        }
Ejemplo n.º 45
0
        private BoundExpression MakeNullCheck(CSharpSyntaxNode syntax, BoundExpression rewrittenExpr, BinaryOperatorKind operatorKind)
        {
            Debug.Assert((operatorKind == BinaryOperatorKind.Equal) || (operatorKind == BinaryOperatorKind.NotEqual) ||
                (operatorKind == BinaryOperatorKind.NullableNullEqual) || (operatorKind == BinaryOperatorKind.NullableNullNotEqual));

            TypeSymbol exprType = rewrittenExpr.Type;

            // Don't even call this method if the expression isn't nullable.
            Debug.Assert(
                (object)exprType == null ||
                exprType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T ||
                !exprType.IsValueType ||
                exprType.IsPointerType());

            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            // Fold compile-time comparisons.
            if (rewrittenExpr.ConstantValue != null)
            {
                switch (operatorKind)
                {
                    case BinaryOperatorKind.Equal:
                        return MakeLiteral(syntax, ConstantValue.Create(rewrittenExpr.ConstantValue.IsNull, ConstantValueTypeDiscriminator.Boolean), boolType);
                    case BinaryOperatorKind.NotEqual:
                        return MakeLiteral(syntax, ConstantValue.Create(!rewrittenExpr.ConstantValue.IsNull, ConstantValueTypeDiscriminator.Boolean), boolType);
                }
            }

            TypeSymbol objectType = _compilation.GetSpecialType(SpecialType.System_Object);

            if ((object)exprType != null)
            {
                if (exprType.Kind == SymbolKind.TypeParameter)
                {
                    // Box type parameters.
                    rewrittenExpr = MakeConversionNode(syntax, rewrittenExpr, Conversion.Boxing, objectType, @checked: false);
                }
                else if (exprType.IsNullableType())
                {
                    operatorKind |= BinaryOperatorKind.NullableNull;
                }
            }

            return MakeBinaryOperator(
                syntax,
                operatorKind,
                rewrittenExpr,
                MakeLiteral(syntax, ConstantValue.Null, objectType),
                boolType,
                null);
        }
Ejemplo n.º 46
0
        private void CheckForBitwiseOrSignExtend(BoundExpression node, BinaryOperatorKind operatorKind, BoundExpression leftOperand, BoundExpression rightOperand)
        {
            // We wish to give a warning for situations where an unexpected sign extension wipes
            // out some bits. For example:
            //
            // int x = 0x0ABC0000;
            // short y = -2; // 0xFFFE
            // int z = x | y;
            //
            // The user might naively expect the result to be 0x0ABCFFFE. But the short is sign-extended
            // when it is converted to int before the bitwise or, so this is in fact the same as:
            //
            // int x = 0x0ABC0000;
            // short y = -2; // 0xFFFE
            // int ytemp = y; // 0xFFFFFFFE
            // int z = x | ytemp;
            //
            // Which gives 0xFFFFFFFE, not 0x0ABCFFFE.
            //
            // However, we wish to suppress the warning if:
            //
            // * The sign extension is "expected" -- for instance, because there was an explicit cast
            //   from short to int:  "int z = x | (int)y;" should not produce the warning.
            //   Note that "uint z = (uint)x | (uint)y;" should still produce the warning because
            //   the user might not realize that converting y to uint does a sign extension.
            //
            // * There is the same amount of sign extension on both sides. For example, when
            //   doing "short | sbyte", both sides are sign extended. The left creates two FF bytes
            //   and the right creates three, so we are potentially wiping out information from the
            //   left side. But "short | short" adds two FF bytes on both sides, so no information is lost.
            //
            // The native compiler also suppresses this warning in a bizarre and inconsistent way. If
            // the side whose bits are going to be wiped out by sign extension is a *constant*, then the
            // warning is suppressed *if the constant, when converted to a signed long, fits into the
            // range of the type that is being sign-extended.*
            //
            // Consider the effects of this rule:
            //
            // (uint)0xFFFF0000 | y -- gives the warning because 0xFFFF0000 as a long is not in the range of a short,
            //                         *even though the result will not be affected by the sign extension*.
            // (ulong)0xFFFFFFFFFFFFFFFF | y -- suppresses the warning, because 0xFFFFFFFFFFFFFFFF as a signed long fits into a short.
            // (int)0x0000ABCD | y -- suppresses the warning, even though the 0000 is going to be wiped out by the sign extension.
            //
            // It seems clear that the intention of the heuristic is to *suppress the warning when the bits being hammered
            // on are either all zero, or all one.*  Therefore that is the heuristic we will *actually* implement here.
            //

            switch (operatorKind)
            {
            case BinaryOperatorKind.LiftedUIntOr:
            case BinaryOperatorKind.LiftedIntOr:
            case BinaryOperatorKind.LiftedULongOr:
            case BinaryOperatorKind.LiftedLongOr:
            case BinaryOperatorKind.UIntOr:
            case BinaryOperatorKind.IntOr:
            case BinaryOperatorKind.ULongOr:
            case BinaryOperatorKind.LongOr:
                break;

            default:
                return;
            }

            // The native compiler skips this warning if both sides of the operator are constants.
            //
            // CONSIDER: Is that sensible? It seems reasonable that if we would warn on int | short
            // when they are non-constants, or when one is a constant, that we would similarly warn
            // when both are constants.

            if (node.ConstantValue != null)
            {
                return;
            }

            // Start by determining *which bits on each side are going to be unexpectedly turned on*.

            ulong left  = FindSurprisingSignExtensionBits(leftOperand);
            ulong right = FindSurprisingSignExtensionBits(rightOperand);

            // If they are all the same then there's no warning to give.

            if (left == right)
            {
                return;
            }

            // Suppress the warning if one side is a constant, and either all the unexpected
            // bits are already off, or all the unexpected bits are already on.

            ConstantValue constVal = GetConstantValueForBitwiseOrCheck(leftOperand);

            if (constVal != null)
            {
                ulong val = constVal.UInt64Value;
                if ((val & right) == right || (~val & right) == right)
                {
                    return;
                }
            }

            constVal = GetConstantValueForBitwiseOrCheck(rightOperand);
            if (constVal != null)
            {
                ulong val = constVal.UInt64Value;
                if ((val & left) == left || (~val & left) == left)
                {
                    return;
                }
            }

            // CS0675: Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first
            Error(ErrorCode.WRN_BitwiseOrSignExtend, node);
        }
Ejemplo n.º 47
0
        public static Expression <Func <T, bool> > CombineExpression <T>(Expression <Func <T, bool> > expr1, Expression <Func <T, bool> > expr2, BinaryOperatorKind kind, string name = "model")
        {
            var parameter = Expression.Parameter(typeof(T), name);

            var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
            var left        = leftVisitor.Visit(expr1.Body);

            var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
            var right        = rightVisitor.Visit(expr2.Body);

            switch (kind)
            {
            case BinaryOperatorKind.Or:
                return(Expression.Lambda <Func <T, bool> >(Expression.Or(left, right), parameter));

            case BinaryOperatorKind.And:
                return(Expression.Lambda <Func <T, bool> >(Expression.AndAlso(left, right), parameter));

            case BinaryOperatorKind.Equal:
                break;

            case BinaryOperatorKind.NotEqual:
                break;

            case BinaryOperatorKind.GreaterThan:
                break;

            case BinaryOperatorKind.GreaterThanOrEqual:
                break;

            case BinaryOperatorKind.LessThan:
                break;

            case BinaryOperatorKind.LessThanOrEqual:
                break;

            case BinaryOperatorKind.Add:
                break;

            case BinaryOperatorKind.Subtract:
                break;

            case BinaryOperatorKind.Multiply:
                break;

            case BinaryOperatorKind.Divide:
                break;

            case BinaryOperatorKind.Modulo:
                break;

            case BinaryOperatorKind.Has:
                break;

            default:
                break;
            }
            return(null);
        }
Ejemplo n.º 48
0
 public static BinaryOperatorKind Operator(this BinaryOperatorKind kind)
 {
     return(kind & BinaryOperatorKind.OpMask);
 }
Ejemplo n.º 49
0
 public static BinaryOperatorKind Unlifted(this BinaryOperatorKind kind)
 {
     return(kind & ~BinaryOperatorKind.Lifted);
 }
Ejemplo n.º 50
0
 public static BinaryOperatorKind OperatorWithLogical(this BinaryOperatorKind kind)
 {
     return(kind & (BinaryOperatorKind.OpMask | BinaryOperatorKind.Logical));
 }
Ejemplo n.º 51
0
        /// <summary>
        /// Spec section 7.9: if the left operand is int or uint, mask the right operand with 0x1F;
        /// if the left operand is long or ulong, mask the right operand with 0x3F.
        /// </summary>
        private BoundExpression RewriteBuiltInShiftOperation(
            BoundBinaryOperator oldNode,
            CSharpSyntaxNode syntax,
            BinaryOperatorKind operatorKind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            TypeSymbol type,
            int rightMask)
        {
            CSharpSyntaxNode rightSyntax = loweredRight.Syntax;
            ConstantValue rightConstantValue = loweredRight.ConstantValue;
            TypeSymbol rightType = loweredRight.Type;
            Debug.Assert(rightType.SpecialType == SpecialType.System_Int32);

            if (rightConstantValue != null && rightConstantValue.IsIntegral)
            {
                int shiftAmount = rightConstantValue.Int32Value & rightMask;
                if (shiftAmount == 0)
                {
                    return loweredLeft;
                }

                loweredRight = MakeLiteral(rightSyntax, ConstantValue.Create(shiftAmount), rightType);
            }
            else
            {
                BinaryOperatorKind andOperatorKind = (operatorKind & ~BinaryOperatorKind.OpMask) | BinaryOperatorKind.And;
                loweredRight = new BoundBinaryOperator(
                    rightSyntax,
                    andOperatorKind,
                    loweredRight,
                    MakeLiteral(rightSyntax, ConstantValue.Create(rightMask), rightType),
                    null,
                    null,
                    LookupResultKind.Viable,
                    rightType);
            }

            return oldNode == null
                ? new BoundBinaryOperator(
                    syntax,
                    operatorKind,
                    loweredLeft,
                    loweredRight,
                    null,
                    null,
                    LookupResultKind.Viable,
                    type)
                : oldNode.Update(
                    operatorKind,
                    loweredLeft,
                    loweredRight,
                    null,
                    null,
                    oldNode.ResultKind,
                    type);
        }
Ejemplo n.º 52
0
 public static BinaryOperatorKind WithType(this BinaryOperatorKind kind, BinaryOperatorKind type)
 {
     Debug.Assert(kind == (kind & ~BinaryOperatorKind.TypeMask));
     Debug.Assert(type == (type & BinaryOperatorKind.TypeMask));
     return(kind | type);
 }
Ejemplo n.º 53
0
        private BoundExpression RewritePointerSubtraction(
            BinaryOperatorKind kind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            TypeSymbol returnType)
        {
            Debug.Assert(loweredLeft.Type.IsPointerType());
            Debug.Assert(loweredRight.Type.IsPointerType());
            Debug.Assert(returnType.SpecialType == SpecialType.System_Int64);

            PointerTypeSymbol pointerType = (PointerTypeSymbol)loweredLeft.Type;
            var sizeOfExpression = _factory.Sizeof(pointerType.PointedAtType);

            // NOTE: to match dev10, the result of the subtraction is treated as an IntPtr
            // and then the result of the division is converted to long.
            // NOTE: dev10 doesn't optimize away division by 1.
            return _factory.Convert(
                returnType,
                _factory.Binary(
                    BinaryOperatorKind.Division,
                    _factory.SpecialType(SpecialType.System_IntPtr),
                    _factory.Binary(
                        kind & ~BinaryOperatorKind.Checked, // For some reason, dev10 never checks for subtraction overflow.
                        returnType,
                        loweredLeft,
                        loweredRight),
                    sizeOfExpression),
                Conversion.PointerToInteger);
        }
Ejemplo n.º 54
0
 public bool All(BinaryOperatorKind relation, uint value)
 {
     if (_hasLarge && relation switch { LessThan => true, LessThanOrEqual => true, _ => false })
Ejemplo n.º 55
0
        private BoundExpression MakeDynamicLogicalBinaryOperator(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind operatorKind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            MethodSymbol leftTruthOperator,
            TypeSymbol type,
            bool isCompoundAssignment,
            BoundUnaryOperator applyParentUnaryOperator)
        {
            Debug.Assert(operatorKind.Operator() == BinaryOperatorKind.And || operatorKind.Operator() == BinaryOperatorKind.Or);

            // Dynamic logical && and || operators are lowered as follows:
            //   left && right  ->  IsFalse(left) ? left : And(left, right)
            //   left || right  ->  IsTrue(left) ? left : Or(left, right)
            // 
            // Optimization: If the binary AND/OR is directly contained in IsFalse/IsTrue operator (parentUnaryOperator != null)
            // we can avoid calling IsFalse/IsTrue twice on the same object.
            //   IsFalse(left && right)  ->  IsFalse(left) || IsFalse(And(left, right))
            //   IsTrue(left || right)   ->  IsTrue(left) || IsTrue(Or(left, right))

            bool isAnd = operatorKind.Operator() == BinaryOperatorKind.And;

            // Operator to be used to test the left operand:
            var testOperator = isAnd ? UnaryOperatorKind.DynamicFalse : UnaryOperatorKind.DynamicTrue;

            // VisitUnaryOperator ensures we are never called with parentUnaryOperator != null when we can't perform the optimization.
            Debug.Assert(applyParentUnaryOperator == null || applyParentUnaryOperator.OperatorKind == testOperator);

            ConstantValue constantLeft = loweredLeft.ConstantValue ?? UnboxConstant(loweredLeft);
            if (testOperator == UnaryOperatorKind.DynamicFalse && constantLeft == ConstantValue.False ||
                testOperator == UnaryOperatorKind.DynamicTrue && constantLeft == ConstantValue.True)
            {
                Debug.Assert(leftTruthOperator == null);

                if (applyParentUnaryOperator != null)
                {
                    // IsFalse(false && right) -> true
                    // IsTrue(true || right)   -> true
                    return _factory.Literal(true);
                }
                else
                {
                    // false && right  ->  box(false)
                    // true || right   ->  box(true)
                    return MakeConversionNode(loweredLeft, type, @checked: false);
                }
            }

            BoundExpression result;
            var boolean = _compilation.GetSpecialType(SpecialType.System_Boolean);

            // Store left to local if needed. If constant or already local we don't need a temp 
            // since the value of left can't change until right is evaluated.
            BoundAssignmentOperator tempAssignment;
            BoundLocal temp;
            if (constantLeft == null && loweredLeft.Kind != BoundKind.Local && loweredLeft.Kind != BoundKind.Parameter)
            {
                BoundAssignmentOperator assignment;
                var local = _factory.StoreToTemp(loweredLeft, out assignment);
                loweredLeft = local;
                tempAssignment = assignment;
                temp = local;
            }
            else
            {
                tempAssignment = null;
                temp = null;
            }

            var op = _dynamicFactory.MakeDynamicBinaryOperator(operatorKind, loweredLeft, loweredRight, isCompoundAssignment, type).ToExpression();

            // IsFalse(true) or IsTrue(false) are always false:
            bool leftTestIsConstantFalse = testOperator == UnaryOperatorKind.DynamicFalse && constantLeft == ConstantValue.True ||
                                           testOperator == UnaryOperatorKind.DynamicTrue && constantLeft == ConstantValue.False;

            if (applyParentUnaryOperator != null)
            {
                // IsFalse(left && right)  ->  IsFalse(left) || IsFalse(And(left, right))
                // IsTrue(left || right)   ->  IsTrue(left) || IsTrue(Or(left, right))

                result = _dynamicFactory.MakeDynamicUnaryOperator(testOperator, op, boolean).ToExpression();
                if (!leftTestIsConstantFalse)
                {
                    BoundExpression leftTest = MakeTruthTestForDynamicLogicalOperator(syntax, loweredLeft, boolean, leftTruthOperator, negative: isAnd);
                    result = _factory.Binary(BinaryOperatorKind.LogicalOr, boolean, leftTest, result);
                }
            }
            else
            {
                // left && right  ->  IsFalse(left) ? left : And(left, right)
                // left || right  ->  IsTrue(left) ? left : Or(left, right)

                if (leftTestIsConstantFalse)
                {
                    result = op;
                }
                else
                {
                    // We might need to box.
                    BoundExpression leftTest = MakeTruthTestForDynamicLogicalOperator(syntax, loweredLeft, boolean, leftTruthOperator, negative: isAnd);
                    var convertedLeft = MakeConversionNode(loweredLeft, type, @checked: false);
                    result = _factory.Conditional(leftTest, convertedLeft, op, type);
                }
            }

            if (tempAssignment != null)
            {
                return _factory.Sequence(ImmutableArray.Create(temp.LocalSymbol), ImmutableArray.Create<BoundExpression>(tempAssignment), result);
            }

            return result;
        }
Ejemplo n.º 56
0
        private static void VerifyBinaryOperatorToken <T>(string expectedEndPathIdentifier, BinaryOperatorKind expectedOperator, T expectedLiteralValue, BinaryOperatorToken actual)
        {
            actual.Should().NotBeNull();
            actual.OperatorKind.Should().Be(expectedOperator);

            var left = actual.Left as EndPathToken;

            left.Should().NotBeNull();
            left.Identifier.Should().Be(expectedEndPathIdentifier);

            var right = actual.Right as LiteralToken;

            right.Should().NotBeNull();
            right.Value.Should().Be(expectedLiteralValue);
        }
Ejemplo n.º 57
0
        private BoundExpression TrivialLiftedComparisonOperatorOptimizations(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind kind,
            BoundExpression left,
            BoundExpression right,
            MethodSymbol method)
        {
            Debug.Assert(left != null);
            Debug.Assert(right != null);

            // Optimization #1: if both sides are null then the result 
            // is either true (for equality) or false (for everything else.)

            bool leftAlwaysNull = NullableNeverHasValue(left);
            bool rightAlwaysNull = NullableNeverHasValue(right);

            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            if (leftAlwaysNull && rightAlwaysNull)
            {
                return MakeLiteral(syntax, ConstantValue.Create(kind.Operator() == BinaryOperatorKind.Equal), boolType);
            }

            // Optimization #2: If both sides are non-null then we can again eliminate the lifting entirely.

            BoundExpression leftNonNull = NullableAlwaysHasValue(left);
            BoundExpression rightNonNull = NullableAlwaysHasValue(right);

            if (leftNonNull != null && rightNonNull != null)
            {
                return MakeBinaryOperator(
                    syntax: syntax,
                    operatorKind: kind.Unlifted(),
                    loweredLeft: leftNonNull,
                    loweredRight: rightNonNull,
                    type: boolType,
                    method: method);
            }

            // Optimization #3: If one side is null and the other is definitely not, then we generate the side effects
            // of the non-null side and result in true (for not-equals) or false (for everything else.)

            BinaryOperatorKind operatorKind = kind.Operator();

            if (leftAlwaysNull && rightNonNull != null || rightAlwaysNull && leftNonNull != null)
            {
                BoundExpression result = MakeLiteral(syntax, ConstantValue.Create(operatorKind == BinaryOperatorKind.NotEqual), boolType);

                BoundExpression nonNull = leftAlwaysNull ? rightNonNull : leftNonNull;

                if (ReadIsSideeffecting(nonNull))
                {
                    result = new BoundSequence(
                                    syntax: syntax,
                                    locals: ImmutableArray<LocalSymbol>.Empty,
                                    sideEffects: ImmutableArray.Create<BoundExpression>(nonNull),
                                    value: result,
                                    type: boolType);
                }

                return result;
            }

            // Optimization #4: If one side is null and the other is unknown, then we have three cases:
            // #4a: If we have x == null then that becomes !x.HasValue.
            // #4b: If we have x != null then that becomes x.HasValue.
            // #4c: If we have x OP null then that becomes side effects of x, result in false.

            if (leftAlwaysNull || rightAlwaysNull)
            {
                BoundExpression maybeNull = leftAlwaysNull ? right : left;

                if (operatorKind == BinaryOperatorKind.Equal || operatorKind == BinaryOperatorKind.NotEqual)
                {
                    BoundExpression callHasValue = MakeNullableHasValue(syntax, maybeNull);
                    BoundExpression result = operatorKind == BinaryOperatorKind.Equal ?
                        MakeUnaryOperator(UnaryOperatorKind.BoolLogicalNegation, syntax, null, callHasValue, boolType) :
                        callHasValue;
                    return result;
                }
                else
                {
                    BoundExpression falseExpr = MakeBooleanConstant(syntax, operatorKind == BinaryOperatorKind.NotEqual);
                    return _factory.Sequence(maybeNull, falseExpr);
                }
            }

            return null;
        }
Ejemplo n.º 58
0
        /// <summary>
        /// Build BinaryOperatorNode to uri
        /// </summary>
        /// <param name="operatorKind">the kind of the BinaryOperatorNode</param>
        /// <returns>String format of the operator</returns>
        private String BinaryOperatorNodeToString(BinaryOperatorKind operatorKind)
        {
            switch (operatorKind)
            {
            case BinaryOperatorKind.Has:
                return(ExpressionConstants.KeywordHas);

            case BinaryOperatorKind.Equal:
                return(ExpressionConstants.KeywordEqual);

            case BinaryOperatorKind.NotEqual:
                return(ExpressionConstants.KeywordNotEqual);

            case BinaryOperatorKind.GreaterThan:
                return(ExpressionConstants.KeywordGreaterThan);

            case BinaryOperatorKind.GreaterThanOrEqual:
                return(ExpressionConstants.KeywordGreaterThanOrEqual);

            case BinaryOperatorKind.LessThan:
                return(ExpressionConstants.KeywordLessThan);

            case BinaryOperatorKind.LessThanOrEqual:
                return(ExpressionConstants.KeywordLessThanOrEqual);

            // if current translated node is SearchNode, the BinaryOperator should return AND, OR; or return and, or.
            case BinaryOperatorKind.And:
                if (searchFlag)
                {
                    return(ExpressionConstants.SearchKeywordAnd);
                }

                return(ExpressionConstants.KeywordAnd);

            case BinaryOperatorKind.Or:
                if (searchFlag)
                {
                    return(ExpressionConstants.SearchKeywordOr);
                }

                return(ExpressionConstants.KeywordOr);

            case BinaryOperatorKind.Add:
                return(ExpressionConstants.KeywordAdd);

            case BinaryOperatorKind.Subtract:
                return(ExpressionConstants.KeywordSub);

            case BinaryOperatorKind.Multiply:
                return(ExpressionConstants.KeywordMultiply);

            case BinaryOperatorKind.Divide:
                return(ExpressionConstants.KeywordDivide);

            case BinaryOperatorKind.Modulo:
                return(ExpressionConstants.KeywordModulo);

            default:
                return(null);
            }
        }
Ejemplo n.º 59
0
        private BoundExpression LowerLiftedUserDefinedComparisonOperator(
            CSharpSyntaxNode syntax,
            BinaryOperatorKind kind,
            BoundExpression loweredLeft,
            BoundExpression loweredRight,
            MethodSymbol method)
        {
            // If both sides are null, or neither side is null, then we can do some simple optimizations.

            BoundExpression optimized = TrivialLiftedComparisonOperatorOptimizations(syntax, kind, loweredLeft, loweredRight, method);
            if (optimized != null)
            {
                return optimized;
            }

            // Otherwise, the expression
            //
            // x == y 
            //
            // becomes
            //
            // tempX = x;
            // tempY = y;
            // result = tempX.HasValue == tempY.HasValue ? 
            //            (tempX.HasValue ? 
            //              tempX.GetValueOrDefault() == tempY.GetValueOrDefault() : 
            //              true) : 
            //          false;
            //
            //
            // the expression
            //
            // x != y 
            //
            // becomes
            //
            // tempX = x;
            // tempY = y;
            // result = tempX.HasValue == tempY.HasValue ? 
            //            (tempX.HasValue ? 
            //              tempX.GetValueOrDefault() != tempY.GetValueOrDefault() : 
            //              false) : 
            //            true;
            //
            //
            // For the other comparison operators <, <=, >, >=,
            //
            // x OP y 
            //
            // becomes
            //
            // tempX = x;
            // tempY = y;
            // result = tempX.HasValue & tempY.HasValue ? 
            //              tempX.GetValueOrDefault() OP tempY.GetValueOrDefault() : 
            //              false;
            //
            // We have not yet optimized the case where we have a known-not-null value on one side, 
            // and an unknown value on the other. In those cases we will still generate a temp, but
            // we will not generate the call to the unnecessary nullable ctor or to GetValueOrDefault.
            // Rather, we will generate the value's temp instead of a call to GetValueOrDefault, and generate
            // literal true for HasValue. The tree construction methods we call will use those constants
            // to eliminate unnecessary branches.

            BoundExpression xNonNull = NullableAlwaysHasValue(loweredLeft);
            BoundExpression yNonNull = NullableAlwaysHasValue(loweredRight);

            // TODO: (This TODO applies throughout this file, not just to this method.)
            // TODO: We might be storing a constant to this temporary that we could simply inline.
            // TODO: (There are other expressions that can be safely moved around other than constants
            // TODO: as well -- for example a boxing conversion of a constant int to object.)
            // TODO: Build a better temporary-storage management system that decides whether or not
            // TODO: to store a temporary.

            BoundAssignmentOperator tempAssignmentX;
            BoundLocal boundTempX = _factory.StoreToTemp(xNonNull ?? loweredLeft, out tempAssignmentX);
            BoundAssignmentOperator tempAssignmentY;
            BoundLocal boundTempY = _factory.StoreToTemp(yNonNull ?? loweredRight, out tempAssignmentY);

            BoundExpression callX_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempX);
            BoundExpression callY_GetValueOrDefault = MakeOptimizedGetValueOrDefault(syntax, boundTempY);
            BoundExpression callX_HasValue = MakeOptimizedHasValue(syntax, boundTempX);
            BoundExpression callY_HasValue = MakeOptimizedHasValue(syntax, boundTempY);

            // tempx.HasValue == tempy.HasValue
            BinaryOperatorKind conditionOperator;
            BinaryOperatorKind operatorKind = kind.Operator();
            switch (operatorKind)
            {
                case BinaryOperatorKind.Equal:
                case BinaryOperatorKind.NotEqual:
                    conditionOperator = BinaryOperatorKind.BoolEqual;
                    break;
                default:
                    conditionOperator = BinaryOperatorKind.BoolAnd;
                    break;
            }

            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression condition = MakeBinaryOperator(
                syntax: syntax,
                operatorKind: conditionOperator,
                loweredLeft: callX_HasValue,
                loweredRight: callY_HasValue,
                type: boolType,
                method: null);

            // tempX.GetValueOrDefault() OP tempY.GetValueOrDefault()
            BoundExpression unliftedOp = MakeBinaryOperator(
                syntax: syntax,
                operatorKind: kind.Unlifted(),
                loweredLeft: callX_GetValueOrDefault,
                loweredRight: callY_GetValueOrDefault,
                type: boolType,
                method: method);

            BoundExpression consequence;
            if (operatorKind == BinaryOperatorKind.Equal || operatorKind == BinaryOperatorKind.NotEqual)
            {
                // tempx.HasValue ? tempX.GetValueOrDefault() == tempY.GetValueOrDefault() : true
                consequence = RewriteConditionalOperator(
                    syntax: syntax,
                    rewrittenCondition: callX_HasValue,
                    rewrittenConsequence: unliftedOp,
                    rewrittenAlternative: MakeLiteral(syntax, ConstantValue.Create(operatorKind == BinaryOperatorKind.Equal), boolType),
                    constantValueOpt: null,
                    rewrittenType: boolType);
            }
            else
            {
                // tempX.GetValueOrDefault() OP tempY.GetValueOrDefault()
                consequence = unliftedOp;
            }

            // false
            BoundExpression alternative = MakeBooleanConstant(syntax, operatorKind == BinaryOperatorKind.NotEqual);

            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: boolType);

            return new BoundSequence(
                syntax: syntax,
                locals: ImmutableArray.Create<LocalSymbol>(boundTempX.LocalSymbol, boundTempY.LocalSymbol),
                sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignmentX, tempAssignmentY),
                value: conditionalExpression,
                type: boolType);
        }
Ejemplo n.º 60
0
 public static int OperatorIndex(this BinaryOperatorKind kind)
 {
     return(((int)kind.Operator() >> 8) - 16);
 }