コード例 #1
0
        public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperator node)
        {
            // TestExpression ?? ElseExpression
            if (node.ConstantValue == null && !node.HasErrors)
            {
                var           testExpression = node.TestExpression;
                ConstantValue testExpressionConstantValue = testExpression.ConstantValue;
                if (testExpressionConstantValue != null)
                {
                    // testExpression is a known compile time constant
                    if (testExpressionConstantValue == ConstantValue.Null)
                    {
                        // testExpression is always null
                        return(Visit(node.ElseExpression));
                    }
                    // testExpression is always non null constant
                    return(Visit(node.LeftConversion ?? node.TestExpression));
                }
                else
                {
                    TypeSymbol      exprType       = node.Type;
                    BoundExpression elseExpression = node.ElseExpression;
                    BoundExpression leftConversion = node.LeftConversion; //it's a BoundConversion, but we're passing by ref

                    // There are two ways that a conversion of the test expression can be represented:
                    //   1) If it was cast in source, then node.TestExpression could be a BoundConversion, or
                    //   2) If the compiler generated a conversion to reconcile the types, then node.LeftConversion could be non-null.
                    if (leftConversion == null)
                    {
                        if (IsUpdateRequiredForExplicitConversion(exprType, ref testExpression, ref elseExpression))
                        {
                            return(node.Update(
                                       testExpression,
                                       elseExpression,
                                       leftConversion: null,
                                       constantValueOpt: null,
                                       type: exprType));
                        }
                    }
                    else if (IsUpdateRequiredForExplicitConversion(exprType, ref leftConversion, ref elseExpression))
                    {
                        return(node.Update(
                                   (BoundExpression)Visit(testExpression),
                                   elseExpression,
                                   (BoundConversion)leftConversion,
                                   constantValueOpt: null,
                                   type: exprType));
                    }
                }
            }
            return(base.VisitNullCoalescingOperator(node));
        }
コード例 #2
0
        public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperator node)
        {
            BoundSpillSequenceBuilder builder = null;
            var             right             = VisitExpression(ref builder, node.RightOperand);
            BoundExpression left;

            if (builder == null)
            {
                left = VisitExpression(ref builder, node.LeftOperand);
            }
            else
            {
                var leftBuilder = new BoundSpillSequenceBuilder();
                left = VisitExpression(ref leftBuilder, node.LeftOperand);
                left = Spill(leftBuilder, left);

                var tmp = _F.SynthesizedLocal(node.Type, kind: SynthesizedLocalKind.Spill, syntax: _F.Syntax);
                leftBuilder.AddLocal(tmp);
                leftBuilder.AddStatement(_F.Assignment(_F.Local(tmp), left));
                leftBuilder.AddStatement(_F.If(
                                             _F.ObjectEqual(_F.Local(tmp), _F.Null(left.Type)),
                                             UpdateStatement(builder, _F.Assignment(_F.Local(tmp), right))));

                return(UpdateExpression(leftBuilder, _F.Local(tmp)));
            }

            return(UpdateExpression(builder, node.Update(left, right, node.LeftConversion, node.OperatorResultKind, node.Type)));
        }
コード例 #3
0
        public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperator node)
        {
            BoundSpillSequenceBuilder builder = null;
            var             right             = VisitExpression(ref builder, node.RightOperand);
            BoundExpression left;

            if (builder == null)
            {
                left = VisitExpression(ref builder, node.LeftOperand);
            }
            else
            {
                var leftBuilder = new BoundSpillSequenceBuilder();
                left = VisitExpression(ref leftBuilder, node.LeftOperand);
                left = Spill(leftBuilder, left);

                leftBuilder.AddStatement(_F.If(
                                             _F.ObjectEqual(left, _F.Null(left.Type)),
                                             UpdateStatement(builder, _F.Assignment(left, right), substituteTemps: false)));

                return(UpdateExpression(leftBuilder, left));
            }

            return(UpdateExpression(builder, node.Update(left, right, node.LeftConversion, node.Type)));
        }
コード例 #4
0
        public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperator node)
        {
            BoundSpillSequence2 ss = null;
            var             right  = VisitExpression(ref ss, node.RightOperand);
            BoundExpression left;

            if (ss == null)
            {
                left = VisitExpression(ref ss, node.LeftOperand);
            }
            else
            {
                var ssLeft = new BoundSpillSequence2();
                left = VisitExpression(ref ssLeft, node.LeftOperand);
                left = Spill(ssLeft, left);

                ssLeft.Add(F.If(
                               F.ObjectEqual(left, F.Null(left.Type)),
                               UpdateStatement(ss, F.Assignment(left, right))
                               ));
                return(UpdateExpression(ssLeft, left));
            }

            return(UpdateExpression(ss, node.Update(left, right, node.LeftConversion, node.Type)));
        }
コード例 #5
0
ファイル: Optimizer.cs プロジェクト: rosslyn-cuongle/roslyn
        public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperator node)
        {
            var origStack = StackDepth();
            BoundExpression left = (BoundExpression)this.Visit(node.LeftOperand);

            var cookie = GetStackStateCookie();     // implicit branch here

            // right is evaluated with original stack 
            // (this is not entirely true, codegen may keep left on the stack as an ephemeral temp, but that is irrelevant here)
            SetStackDepth(origStack);
            BoundExpression right = (BoundExpression)this.Visit(node.RightOperand);

            EnsureStackState(cookie);   // implicit label here

            return node.Update(left, right, node.LeftConversion, node.Type);
        }
コード例 #6
0
        public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperator node)
        {
            // TestExpression ?? ElseExpression
            if (node.ConstantValue == null && !node.HasErrors)
            {
                var testExpression = node.TestExpression;
                ConstantValue testExpressionConstantValue = testExpression.ConstantValue;
                if (testExpressionConstantValue != null)
                {
                    // testExpression is a known compile time constant
                    if (testExpressionConstantValue == ConstantValue.Null)
                    {
                        // testExpression is always null
                        return Visit(node.ElseExpression);
                    }
                    // testExpression is always non null constant
                    return Visit(node.LeftConversion ?? node.TestExpression);
                }
                else
                {
                    TypeSymbol exprType = node.Type;
                    BoundExpression elseExpression = node.ElseExpression;
                    BoundExpression leftConversion = node.LeftConversion; //it's a BoundConversion, but we're passing by ref

                    // There are two ways that a conversion of the test expression can be represented:
                    //   1) If it was cast in source, then node.TestExpression could be a BoundConversion, or
                    //   2) If the compiler generated a conversion to reconcile the types, then node.LeftConversion could be non-null.
                    if (leftConversion == null)
                    {
                        if (IsUpdateRequiredForExplicitConversion(exprType, ref testExpression, ref elseExpression))
                        {
                            return node.Update(
                                testExpression,
                                elseExpression,
                                leftConversion: null,
                                constantValueOpt: null,
                                type: exprType);
                        }
                    }
                    else if (IsUpdateRequiredForExplicitConversion(exprType, ref leftConversion, ref elseExpression))
                    {
                        return node.Update(
                            (BoundExpression)Visit(testExpression),
                            elseExpression,
                            (BoundConversion)leftConversion,
                            constantValueOpt: null,
                            type: exprType);
                    }
                }
            }
            return base.VisitNullCoalescingOperator(node);
        }