Ejemplo n.º 1
0
        private BoundExpression MakeAsOperator(
            BoundAsOperator oldNode,
            SyntaxNode syntax,
            BoundExpression rewrittenOperand,
            BoundTypeExpression rewrittenTargetType,
            Conversion conversion,
            TypeSymbol rewrittenType)
        {
            // TODO: Handle dynamic operand type and target type
            Debug.Assert(rewrittenTargetType.Type.Equals(rewrittenType));

            // target type cannot be a non-nullable value type
            Debug.Assert(!rewrittenType.IsValueType || rewrittenType.IsNullableType());

            if (!_inExpressionLambda)
            {
                ConstantValue constantValue = Binder.GetAsOperatorConstantResult(rewrittenOperand.Type, rewrittenType, conversion.Kind, rewrittenOperand.ConstantValue);

                if (constantValue != null)
                {
                    Debug.Assert(constantValue.IsNull);
                    BoundExpression result = rewrittenType.IsNullableType() ? new BoundDefaultExpression(syntax, rewrittenType) : MakeLiteral(syntax, constantValue, rewrittenType);

                    if (rewrittenOperand.ConstantValue != null)
                    {
                        // No need to preserve any side-effects from the operand.
                        // We also can keep the "constant" notion of the result, which
                        // enables some optimizations down the road.
                        return(result);
                    }

                    return(new BoundSequence(
                               syntax: syntax,
                               locals: ImmutableArray <LocalSymbol> .Empty,
                               sideEffects: ImmutableArray.Create <BoundExpression>(rewrittenOperand),
                               value: result,
                               type: rewrittenType));
                }

                if (conversion.IsImplicit)
                {
                    // Operand with bound implicit conversion to target type.
                    // We don't need a runtime check, generate a conversion for the operand instead.
                    return(MakeConversionNode(syntax, rewrittenOperand, conversion, rewrittenType, @checked: false));
                }
            }

            return(oldNode.Update(rewrittenOperand, rewrittenTargetType, conversion, rewrittenType));
        }
Ejemplo n.º 2
0
        private BoundExpression MakeIsOperator(
            BoundIsOperator oldNode,
            SyntaxNode syntax,
            BoundExpression rewrittenOperand,
            BoundTypeExpression rewrittenTargetType,
            Conversion conversion,
            TypeSymbol rewrittenType)
        {
            if (rewrittenOperand.Kind == BoundKind.MethodGroup)
            {
                var             methodGroup = (BoundMethodGroup)rewrittenOperand;
                BoundExpression receiver    = methodGroup.ReceiverOpt;
                if (receiver != null && receiver.Kind != BoundKind.ThisReference)
                {
                    // possible side-effect
                    return(RewriteConstantIsOperator(receiver.Syntax, receiver, ConstantValue.False, rewrittenType));
                }
                else
                {
                    return(MakeLiteral(syntax, ConstantValue.False, rewrittenType));
                }
            }

            var operandType = rewrittenOperand.Type;
            var targetType  = rewrittenTargetType.Type;

            Debug.Assert((object)operandType != null || rewrittenOperand.ConstantValue.IsNull);
            Debug.Assert((object)targetType != null);

            // TODO: Handle dynamic operand type and target type

            if (!_inExpressionLambda)
            {
                ConstantValue constantValue = Binder.GetIsOperatorConstantResult(operandType, targetType, conversion.Kind, rewrittenOperand.ConstantValue);

                if (constantValue != null)
                {
                    return(RewriteConstantIsOperator(syntax, rewrittenOperand, constantValue, rewrittenType));
                }
                else if (conversion.IsImplicit)
                {
                    // operand is a reference type with bound identity or implicit conversion
                    // We can replace the "is" instruction with a null check
                    return(MakeNullCheck(syntax, rewrittenOperand, BinaryOperatorKind.NotEqual));
                }
            }

            return(oldNode.Update(rewrittenOperand, rewrittenTargetType, conversion, rewrittenType));
        }