public override void VisitIf(BoundIf node)
            {
                // Rules for if:
                // * When IsTrue(Test), Else is not taken and Then stays the
                //   default branch;
                // * When IsFalse(Test), Then is not taken and If stays the
                //   default branch;
                // * Otherwise, Then and Else become a fork (even when Else
                //   is null).

                bool? result = ToBoolean(node.Test);

                // If Test evaluates to a constant that allows us to skip
                // the Then, and we don't have an Else, we don't have any
                // work for this node.

                if (result == false && node.Else == null)
                    return;

                // Test is executed on the default branch.
                Visit(node.Test);

                var block = new Block(_branch, null, false, false, null);

                PushBlock(block);

                if (!result.HasValue)
                {
                    // Visit the Then.

                    _branch = block.Branch.Fork();

                    Visit(node.Then);

                    block.JoinBranch(_branch);

                    // Visit the Else. Note that we always fork the branch, even
                    // when we don't have an Else. The reason for this is that
                    // the join algorithm correctly marks variables that are
                    // only written to in the Then branch as not definitely
                    // assigned.

                    _branch = block.Branch.Fork();

                    if (node.Else != null)
                        Visit(node.Else);

                    block.JoinBranch(_branch);
                }
                else
                {
                    Visit(result.Value ? node.Then : node.Else);
                }

                PopBlock(block);
            }
Example #2
0
 public virtual void VisitIf(BoundIf node)
 {
     DefaultVisit(node);
 }
Example #3
0
        private void EmitIf(BoundIf node)
        {
            var afterTarget = IL.DefineLabel();

            if (node.Else != null)
            {
                var elseTarget = IL.DefineLabel();

                // Jump over the Then if the test fails.

                EmitTest(node.Test, elseTarget, true);

                // Emit the Then and jump over the Else.

                EmitStatement(node.Then);

                IL.Emit(OpCodes.Br, afterTarget);

                // Emit the Else.

                IL.MarkLabel(elseTarget);

                EmitStatement(node.Else);
            }
            else
            {
                // Jump over the Then if the test fails.

                EmitTest(node.Test, afterTarget, true);

                // Emit the Then.

                EmitStatement(node.Then);
            }

            // After the whole If.

            IL.MarkLabel(afterTarget);
        }