/// <summary>
        /// If the condition has a constant value, then just use the selected branch.
        /// e.g. "true ? x : y" becomes "x".
        /// </summary>
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            // just a fact, not a requirement (VisitExpression would have rewritten otherwise)
            Debug.Assert(node.ConstantValue == null);

            var rewrittenCondition   = VisitExpression(node.Condition);
            var rewrittenConsequence = VisitExpression(node.Consequence);
            var rewrittenAlternative = VisitExpression(node.Alternative);

            if (rewrittenCondition.ConstantValue == null)
            {
                return(node.Update(
                           node.IsRef,
                           rewrittenCondition,
                           rewrittenConsequence,
                           rewrittenAlternative,
                           node.ConstantValueOpt,
                           node.NaturalTypeOpt,
                           node.WasTargetTyped,
                           node.Type
                           ));
            }

            return(RewriteConditionalOperator(
                       node.Syntax,
                       rewrittenCondition,
                       rewrittenConsequence,
                       rewrittenAlternative,
                       node.ConstantValueOpt,
                       node.Type,
                       node.IsRef
                       ));
        }
示例#2
0
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundSpillSequenceBuilder conditionBuilder = null;
            var condition = VisitExpression(ref conditionBuilder, node.Condition);

            BoundSpillSequenceBuilder consequenceBuilder = null;
            var consequence = VisitExpression(ref consequenceBuilder, node.Consequence);

            BoundSpillSequenceBuilder alternativeBuilder = null;
            var alternative = VisitExpression(ref alternativeBuilder, node.Alternative);

            if (consequenceBuilder == null && alternativeBuilder == null)
            {
                return(UpdateExpression(conditionBuilder, node.Update(condition, consequence, alternative, node.ConstantValueOpt, node.Type)));
            }

            if (conditionBuilder == null)
            {
                conditionBuilder = new BoundSpillSequenceBuilder();
            }
            if (consequenceBuilder == null)
            {
                consequenceBuilder = new BoundSpillSequenceBuilder();
            }
            if (alternativeBuilder == null)
            {
                alternativeBuilder = new BoundSpillSequenceBuilder();
            }

            if (node.Type.SpecialType == SpecialType.System_Void)
            {
                conditionBuilder.AddStatement(
                    _F.If(condition,
                          UpdateStatement(consequenceBuilder, _F.ExpressionStatement(consequence), substituteTemps: false),
                          UpdateStatement(alternativeBuilder, _F.ExpressionStatement(alternative), substituteTemps: false)));

                return(conditionBuilder.Update(_F.Default(node.Type)));
            }
            else
            {
                Debug.Assert(_F.Syntax.IsKind(SyntaxKind.AwaitExpression));
                var tmp = _F.SynthesizedLocal(node.Type, kind: SynthesizedLocalKind.AwaitSpill, syntax: _F.Syntax);

                conditionBuilder.AddLocal(tmp, _F.Diagnostics);
                conditionBuilder.AddStatement(
                    _F.If(condition,
                          UpdateStatement(consequenceBuilder, _F.Assignment(_F.Local(tmp), consequence), substituteTemps: false),
                          UpdateStatement(alternativeBuilder, _F.Assignment(_F.Local(tmp), alternative), substituteTemps: false)));

                return(conditionBuilder.Update(_F.Local(tmp)));
            }
        }
示例#3
0
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundSpillSequenceBuilder conditionBuilder = null;
            var condition = VisitExpression(ref conditionBuilder, node.Condition);

            BoundSpillSequenceBuilder consequenceBuilder = null;
            var consequence = VisitExpression(ref consequenceBuilder, node.Consequence);

            BoundSpillSequenceBuilder alternativeBuilder = null;
            var alternative = VisitExpression(ref alternativeBuilder, node.Alternative);

            if (consequenceBuilder == null && alternativeBuilder == null)
            {
                return(UpdateExpression(conditionBuilder, node.Update(node.IsRef, condition, consequence, alternative, node.ConstantValueOpt, node.Type)));
            }

            if (conditionBuilder == null)
            {
                conditionBuilder = new BoundSpillSequenceBuilder();
            }
            if (consequenceBuilder == null)
            {
                consequenceBuilder = new BoundSpillSequenceBuilder();
            }
            if (alternativeBuilder == null)
            {
                alternativeBuilder = new BoundSpillSequenceBuilder();
            }

            if (node.Type.IsVoidType())
            {
                conditionBuilder.AddStatement(
                    _F.If(condition,
                          UpdateStatement(consequenceBuilder, _F.ExpressionStatement(consequence)),
                          UpdateStatement(alternativeBuilder, _F.ExpressionStatement(alternative))));

                return(conditionBuilder.Update(_F.Default(node.Type)));
            }
            else
            {
                var tmp = _F.SynthesizedLocal(node.Type, kind: SynthesizedLocalKind.Spill, syntax: _F.Syntax);

                conditionBuilder.AddLocal(tmp);
                conditionBuilder.AddStatement(
                    _F.If(condition,
                          UpdateStatement(consequenceBuilder, _F.Assignment(_F.Local(tmp), consequence)),
                          UpdateStatement(alternativeBuilder, _F.Assignment(_F.Local(tmp), alternative))));

                return(conditionBuilder.Update(_F.Local(tmp)));
            }
        }
        /// <summary>
        /// If the condition has a constant value, then just use the selected branch.
        /// e.g. "true ? x : y" becomes "x".
        /// </summary>
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            // just a fact, not a requirement (VisitExpression would have rewritten otherwise)
            Debug.Assert(node.ConstantValue == null);

            var rewrittenCondition = VisitExpression(node.Condition);
            var rewrittenConsequence = VisitExpression(node.Consequence);
            var rewrittenAlternative = VisitExpression(node.Alternative);

            if (rewrittenCondition.ConstantValue == null)
            {
                return node.Update(rewrittenCondition, rewrittenConsequence, rewrittenAlternative, node.ConstantValueOpt, node.Type);
            }

            return RewriteConditionalOperator(
                node.Syntax,
                rewrittenCondition,
                rewrittenConsequence,
                rewrittenAlternative,
                node.ConstantValueOpt,
                node.Type);
        }
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundExpression condition   = (BoundExpression)this.Visit(node.Condition);
            BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence);
            BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative);
            TypeSymbol      type        = this.VisitType(node.Type);

            if (!RequiresSpill(condition, consequence, alternative))
            {
                return(node.Update(condition, consequence, alternative, node.ConstantValueOpt, type));
            }

            var spillBuilder = new SpillBuilder();

            LocalSymbol resultLocal = F.SynthesizedLocal(type, null);

            spillBuilder.Locals.Add(resultLocal);

            BoundExpression newCondition;

            if (condition.Kind == BoundKind.SpillSequence)
            {
                var spill = (BoundSpillSequence)condition;
                spillBuilder.AddSpill(spill);
                newCondition = spill.Value;
            }
            else
            {
                newCondition = condition;
            }

            spillBuilder.Statements.Add(
                F.If(
                    condition: newCondition,
                    thenClause: CrushExpression(consequence, resultLocal),
                    elseClause: CrushExpression(alternative, resultLocal)));

            return(spillBuilder.BuildSequenceAndFree(F, F.Local(resultLocal)));
        }
示例#6
0
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundSpillSequence2 ss1 = null;
            var condition           = VisitExpression(ref ss1, node.Condition);

            BoundSpillSequence2 ss2 = null;
            var consequence         = VisitExpression(ref ss2, node.Consequence);

            BoundSpillSequence2 ss3 = null;
            var alternative         = VisitExpression(ref ss3, node.Alternative);

            if (ss2 == null && ss3 == null)
            {
                return(UpdateExpression(ss1, node.Update(condition, consequence, alternative, node.ConstantValueOpt, node.Type)));
            }

            var tmp = F.SynthesizedLocal(node.Type);

            if (ss1 == null)
            {
                ss1 = new BoundSpillSequence2();
            }
            if (ss2 == null)
            {
                ss2 = new BoundSpillSequence2();
            }
            if (ss3 == null)
            {
                ss3 = new BoundSpillSequence2();
            }

            ss1.Add(tmp);
            ss1.Add(
                F.If(condition,
                     UpdateStatement(ss2, F.Assignment(F.Local(tmp), consequence)),
                     UpdateStatement(ss3, F.Assignment(F.Local(tmp), alternative))));
            return(ss1.Update(F.Local(tmp)));
        }
示例#7
0
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundSpillSequence2 ss1 = null;
            var condition = VisitExpression(ref ss1, node.Condition);

            BoundSpillSequence2 ss2 = null;
            var consequence = VisitExpression(ref ss2, node.Consequence);

            BoundSpillSequence2 ss3 = null;
            var alternative = VisitExpression(ref ss3, node.Alternative);

            if (ss2 == null && ss3 == null)
            {
                return UpdateExpression(ss1, node.Update(condition, consequence, alternative, node.ConstantValueOpt, node.Type));
            }

            var tmp = F.SynthesizedLocal(node.Type);
            if (ss1 == null) ss1 = new BoundSpillSequence2();
            if (ss2 == null) ss2 = new BoundSpillSequence2();
            if (ss3 == null) ss3 = new BoundSpillSequence2();

            ss1.Add(tmp);
            ss1.Add(
                F.If(condition,
                    UpdateStatement(ss2, F.Assignment(F.Local(tmp), consequence)),
                    UpdateStatement(ss3, F.Assignment(F.Local(tmp), alternative))));
            return ss1.Update(F.Local(tmp));
        }
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundExpression condition = (BoundExpression)this.Visit(node.Condition);
            BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence);
            BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(condition, consequence, alternative))
            {
                return node.Update(condition, consequence, alternative, node.ConstantValueOpt, type);
            }

            var spillBuilder = new SpillBuilder();

            LocalSymbol resultLocal = F.SynthesizedLocal(type, null);
            spillBuilder.Locals.Add(resultLocal);

            BoundExpression newCondition;
            if (condition.Kind == BoundKind.SpillSequence)
            {
                var spill = (BoundSpillSequence)condition;
                spillBuilder.AddSpill(spill);
                newCondition = spill.Value;
            }
            else
            {
                newCondition = condition;
            }

            spillBuilder.Statements.Add(
                F.If(
                    condition: newCondition,
                    thenClause: CrushExpression(consequence, resultLocal),
                    elseClause: CrushExpression(alternative, resultLocal)));

            return spillBuilder.BuildSequenceAndFree(F, F.Local(resultLocal));

        }