コード例 #1
0
        public override BoundNode VisitRangeExpression(BoundRangeExpression node)
        {
            if (_inExpressionLambda)
            {
                Error(ErrorCode.ERR_ExpressionTreeContainsRangeExpression, node);
            }

            return(base.VisitRangeExpression(node));
        }
コード例 #2
0
        public override BoundNode VisitRangeExpression(BoundRangeExpression node)
        {
            Debug.Assert(node != null && node.MethodOpt != null);

            bool needLifting = false;
            var  F           = _factory;

            var left = node.LeftOperandOpt;

            if (left != null)
            {
                left = tryOptimizeOperand(left);
            }

            var right = node.RightOperandOpt;

            if (right != null)
            {
                right = tryOptimizeOperand(right);
            }

            if (needLifting)
            {
                return(LiftRangeExpression(node, left, right));
            }
            else
            {
                BoundExpression rangeCreation = MakeRangeExpression(node.MethodOpt, left, right);

                if (node.Type.IsNullableType())
                {
                    if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
                    {
                        return(BadExpression(node.Syntax, node.Type, node));
                    }

                    return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation));
                }

                return(rangeCreation);
            }

            BoundExpression tryOptimizeOperand(BoundExpression operand)
            {
                Debug.Assert(operand != null);
                operand = VisitExpression(operand);
                Debug.Assert(operand.Type is { });

                if (NullableNeverHasValue(operand))
                {
                    operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
                }
                else
                {
                    operand = NullableAlwaysHasValue(operand) ?? operand;
                    Debug.Assert(operand.Type is { });
コード例 #3
0
        public override BoundNode VisitRangeExpression(BoundRangeExpression node)
        {
            Debug.Assert(node != null && node.MethodOpt != null);

            bool needLifting = false;
            var  F           = _factory;

            var left = node.LeftOperandOpt;

            if (left != null)
            {
                left = tryOptimizeOperand(left);
            }

            var right = node.RightOperandOpt;

            if (right != null)
            {
                right = tryOptimizeOperand(right);
            }

            if (needLifting)
            {
                return(LiftRangeExpression(node, left, right));
            }
            else
            {
                BoundExpression rangeCreation = MakeRangeExpression(node.MethodOpt, left, right);

                if (node.Type.IsNullableType())
                {
                    return(ConvertToNullable(node.Syntax, node.Type, rangeCreation));
                }

                return(rangeCreation);
            }

            BoundExpression tryOptimizeOperand(BoundExpression operand)
            {
                Debug.Assert(operand != null);
                operand = VisitExpression(operand);
                Debug.Assert(operand.Type is { });

                if (NullableNeverHasValue(operand))
                {
                    operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
                }
                else
                {
                    operand = NullableAlwaysHasValue(operand) ?? operand;
                    Debug.Assert(operand.Type is { });
コード例 #4
0
        private BoundExpression LiftRangeExpression(BoundRangeExpression node, BoundExpression left, BoundExpression right)
        {
            Debug.Assert(node.Type.IsNullableType());
            Debug.Assert(left?.Type.IsNullableType() == true || right?.Type.IsNullableType() == true);
            Debug.Assert(!(left is null && right is null));

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

            var locals = ArrayBuilder <LocalSymbol> .GetInstance();

            // makeRange(left.GetValueOrDefault(), right.GetValueOrDefault())
            BoundExpression condition = null;

            left  = getIndexFromPossibleNullable(left);
            right = getIndexFromPossibleNullable(right);
            var rangeExpr = MakeRangeExpression(node.MethodOpt, left, right);

            Debug.Assert(condition != null);

            if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
            {
                return(BadExpression(node.Syntax, node.Type, node));
            }

            // new Nullable(makeRange(left.GetValueOrDefault(), right.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeExpr);

            // default
            BoundExpression alternative = new BoundDefaultExpression(node.Syntax, node.Type);

            // left.HasValue && right.HasValue
            //     ? new Nullable(makeRange(left.GetValueOrDefault(), right.GetValueOrDefault()))
            //     : default
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: node.Syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: node.Type,
                isRef: false);

            return(new BoundSequence(
                       syntax: node.Syntax,
                       locals: locals.ToImmutableAndFree(),
                       sideEffects: sideeffects.ToImmutableAndFree(),
                       value: conditionalExpression,
                       type: node.Type));

            BoundExpression getIndexFromPossibleNullable(BoundExpression arg)
            {
                if (arg is null)
                {
                    return(null);
                }

                BoundExpression tempOperand = CaptureExpressionInTempIfNeeded(arg, sideeffects, locals);

                if (tempOperand.Type.IsNullableType())
                {
                    BoundExpression operandHasValue = MakeOptimizedHasValue(tempOperand.Syntax, tempOperand);

                    if (condition is null)
                    {
                        condition = operandHasValue;
                    }
                    else
                    {
                        TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
                        condition = MakeBinaryOperator(node.Syntax, BinaryOperatorKind.BoolAnd, condition, operandHasValue, boolType, method: null);
                    }

                    return(MakeOptimizedGetValueOrDefault(tempOperand.Syntax, tempOperand));
                }
                else
                {
                    return(tempOperand);
                }
            }
        }
コード例 #5
0
ファイル: LocalRewriter_Range.cs プロジェクト: zyonet/roslyn
        private BoundExpression LiftRangeExpression(BoundRangeExpression node, ImmutableArray <BoundExpression> operands)
        {
            Debug.Assert(node.Type.IsNullableType());
            Debug.Assert(operands.Any(operand => operand.Type.IsNullableType()));
            Debug.Assert(operands.Length == 1 || operands.Length == 2);

            ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance();

            ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance();

            ArrayBuilder <BoundExpression> arguments = ArrayBuilder <BoundExpression> .GetInstance();

            // left.HasValue && right.HasValue
            BoundExpression condition = null;

            foreach (var operand in operands)
            {
                BoundExpression tempOperand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals);

                if (tempOperand.Type.IsNullableType())
                {
                    BoundExpression operandHasValue = MakeOptimizedHasValue(tempOperand.Syntax, tempOperand);

                    if (condition is null)
                    {
                        condition = operandHasValue;
                    }
                    else
                    {
                        TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
                        condition = MakeBinaryOperator(node.Syntax, BinaryOperatorKind.BoolAnd, condition, operandHasValue, boolType, method: null);
                    }

                    arguments.Add(MakeOptimizedGetValueOrDefault(tempOperand.Syntax, tempOperand));
                }
                else
                {
                    arguments.Add(tempOperand);
                }
            }

            Debug.Assert(condition != null);

            // method(left.GetValueOrDefault(), right.GetValueOrDefault())
            BoundExpression rangeCall = MakeCall(
                node.Syntax,
                rewrittenReceiver: null,
                node.MethodOpt,
                arguments.ToImmutableArray(),
                node.MethodOpt.ReturnType.TypeSymbol);

            if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
            {
                return(BadExpression(node.Syntax, node.Type, node));
            }

            // new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCall);

            // default
            BoundExpression alternative = new BoundDefaultExpression(node.Syntax, constantValueOpt: null, node.Type);

            // left.HasValue && right.HasValue ? new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault())) : default
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: node.Syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: node.Type,
                isRef: false);

            return(new BoundSequence(
                       syntax: node.Syntax,
                       locals: locals.ToImmutableAndFree(),
                       sideEffects: sideeffects.ToImmutableAndFree(),
                       value: conditionalExpression,
                       type: node.Type));
        }
コード例 #6
0
ファイル: LocalRewriter_Range.cs プロジェクト: zyonet/roslyn
        public override BoundNode VisitRangeExpression(BoundRangeExpression node)
        {
            Debug.Assert(node != null && node.MethodOpt != null);

            bool needLifting     = false;
            var  operandsBuilder = new ArrayBuilder <BoundExpression>();

            var left = node.LeftOperand;

            if (left != null)
            {
                operandsBuilder.Add(tryOptimizeOperand(left));
            }

            var right = node.RightOperand;

            if (right != null)
            {
                operandsBuilder.Add(tryOptimizeOperand(right));
            }

            ImmutableArray <BoundExpression> operands = operandsBuilder.ToImmutable();

            if (needLifting)
            {
                return(LiftRangeExpression(node, operands));
            }
            else
            {
                BoundExpression rangeCreation = MakeCall(
                    node.Syntax,
                    rewrittenReceiver: null,
                    node.MethodOpt,
                    operands,
                    node.MethodOpt.ReturnType.TypeSymbol);

                if (node.Type.IsNullableType())
                {
                    if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
                    {
                        return(BadExpression(node.Syntax, node.Type, node));
                    }

                    return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation));
                }

                return(rangeCreation);
            }

            BoundExpression tryOptimizeOperand(BoundExpression operand)
            {
                Debug.Assert(operand != null);
                operand = VisitExpression(operand);

                if (NullableNeverHasValue(operand))
                {
                    operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
                }
                else
                {
                    operand = NullableAlwaysHasValue(operand) ?? operand;

                    if (operand.Type.IsNullableType())
                    {
                        needLifting = true;
                    }
                }

                return(operand);
            }
        }
コード例 #7
0
ファイル: LocalRewriter_Range.cs プロジェクト: qxqasdf/roslyn
        public override BoundNode VisitRangeExpression(BoundRangeExpression node)
        {
            Debug.Assert(node != null && node.MethodOpt != null);

            bool needLifting = false;
            var  F           = _factory;

            var left = node.LeftOperand;

            if (left != null)
            {
                left = tryOptimizeOperand(left);
            }
            else
            {
                left = newIndexZero(fromEnd: false);
            }

            var right = node.RightOperand;

            if (right != null)
            {
                right = tryOptimizeOperand(right);
            }
            else
            {
                right = newIndexZero(fromEnd: true);
            }

            var operands = ImmutableArray.Create(left, right);

            if (needLifting)
            {
                return(LiftRangeExpression(node, operands));
            }
            else
            {
                BoundExpression rangeCreation = new BoundObjectCreationExpression(
                    node.Syntax,
                    node.MethodOpt,
                    binderOpt: null,
                    operands);

                if (node.Type.IsNullableType())
                {
                    if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
                    {
                        return(BadExpression(node.Syntax, node.Type, node));
                    }

                    return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation));
                }

                return(rangeCreation);
            }

            BoundExpression newIndexZero(bool fromEnd) =>
            // new Index(0, fromEnd: fromEnd)
            F.New(
                WellKnownMember.System_Index__ctor,
                ImmutableArray.Create <BoundExpression>(F.Literal(0), F.Literal(fromEnd)));

            BoundExpression tryOptimizeOperand(BoundExpression operand)
            {
                Debug.Assert(operand != null);
                operand = VisitExpression(operand);

                if (NullableNeverHasValue(operand))
                {
                    operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
                }
                else
                {
                    operand = NullableAlwaysHasValue(operand) ?? operand;

                    if (operand.Type.IsNullableType())
                    {
                        needLifting = true;
                    }
                }

                return(operand);
            }
        }