예제 #1
0
 public override object VisitCFGSwitchEdge(SwitchEdge x)
 {
     return(x.Update(
                (BoundExpression)Accept(x.SwitchValue),
                VisitBlockImmutableArray(x.CaseBlocks),
                (BoundBlock)Accept(x.NextBlock)));
 }
예제 #2
0
        public virtual void VisitCFGSwitchEdge(SwitchEdge x)
        {
            Accept(x.SwitchValue);

            //
            var arr = x.CaseBlocks;

            for (int i = 0; i < arr.Length; i++)
            {
                arr[i].Accept(this);
            }
        }
예제 #3
0
        public override void VisitSwitchStmt(SwitchStmt x)
        {
            var items = x.SwitchItems;

            if (items == null || items.Length == 0)
            {
                return;
            }

            var end = NewBlock();

            bool hasDefault = false;
            var  cases      = new List <CaseBlock>(items.Length);

            for (int i = 0; i < items.Length; i++)
            {
                cases.Add(NewBlock(items[i]));
                hasDefault |= (items[i] is DefaultItem);
            }
            if (!hasDefault)
            {
                // create implicit default:
                cases.Add(NewBlock(new DefaultItem(x.Span, EmptyArray <Statement> .Instance)));
            }

            // SwitchEdge // Connects _current to cases
            var edge = new SwitchEdge(_current, _binder.BindExpression(x.SwitchValue, BoundAccess.Read), cases.ToArray(), end);

            _current = WithNewOrdinal(cases[0]);

            OpenBreakScope(end, end); // NOTE: inside switch, Continue ~ Break

            for (int i = 0; i < cases.Count; i++)
            {
                OpenScope(_current);

                if (i < items.Length)
                {
                    items[i].Statements.ForEach(VisitElement);  // any break will connect block to end
                }
                CloseScope();

                _current = WithNewOrdinal(Connect(_current, (i == cases.Count - 1) ? end : cases[i + 1]));
            }

            CloseBreakScope();

            Debug.Assert(_current == end);
        }
예제 #4
0
        public override void VisitSwitchStmt(SwitchStmt x)
        {
            var items = x.SwitchItems;

            if (items == null || items.Length == 0)
            {
                return;
            }

            // get bound item for switch value & connect potential pre-switch-value blocks
            var boundBagForSwitchValue = _binder.BindWholeExpression(x.SwitchValue, BoundAccess.Read);

            ConnectBoundItemsBagBlocksToCurrentBlock(boundBagForSwitchValue);
            var switchValue = boundBagForSwitchValue.BoundElement;

            var end = NewBlock();

            bool hasDefault = false;
            var  cases      = new List <CaseBlock>(items.Length);

            for (int i = 0; i < items.Length; i++)
            {
                cases.Add(NewBlock(items[i]));
                hasDefault |= (items[i] is DefaultItem);
            }
            if (!hasDefault)
            {
                // create implicit default:
                cases.Add(NewBlock(new DefaultItem(x.Span, EmptyArray <Statement> .Instance)));
            }

            // if switch value isn't a constant & there're case values with preBoundStatements
            // -> the switch value might get evaluated multiple times (see SwitchEdge.Generate) -> preemptively evaluate and cache it
            if (!switchValue.IsConstant() && !cases.All(c => c.CaseValue.IsOnlyBoundElement))
            {
                var result = GeneratorSemanticsBinder.CreateAndAssignSynthesizedVariable(switchValue, BoundAccess.Read, $"<switchValueCacher>{x.Span}");
                switchValue = result.BoundExpr;
                _current.Add(new BoundExpressionStatement(result.Assignment));
            }

            // SwitchEdge // Connects _current to cases
            var edge = new SwitchEdge(_current, switchValue, cases.ToArray(), end);

            _current = WithNewOrdinal(cases[0]);

            OpenBreakScope(end, end); // NOTE: inside switch, Continue ~ Break

            for (int i = 0; i < cases.Count; i++)
            {
                OpenScope(_current);

                if (i < items.Length)
                {
                    items[i].Statements.ForEach(VisitElement);  // any break will connect block to end
                }
                CloseScope();

                _current = WithNewOrdinal(Connect(_current, (i == cases.Count - 1) ? end : cases[i + 1]));
            }

            CloseBreakScope();

            Debug.Assert(_current == end);
        }
예제 #5
0
        public override void VisitCFGSwitchEdge(SwitchEdge x)
        {
            Accept(x.SwitchValue);

            var state = _state;

            foreach (var c in x.CaseBlocks)
            {
                TraverseToBlock(state, c);
            }
        }
예제 #6
0
        public virtual void VisitCFGSwitchEdge(SwitchEdge x)
        {
            Accept(x.SwitchValue);

            //
            var arr = x.CaseBlocks;
            for (int i = 0; i < arr.Length; i++)
                arr[i].Accept(this);
        }
예제 #7
0
 public virtual TResult VisitCFGSwitchEdge(SwitchEdge x) => DefaultVisitEdge(x);