Пример #1
0
        protected internal override CSharpSwitchCase VisitSwitchCase(CSharpSwitchCase node)
        {
            var args = new List <object>();

            args.Add(new XAttribute(nameof(node.TestValues), string.Join(", ", node.TestValues.Select(EscapeToString))));

            args.Add(Visit(nameof(node.Statements), node.Statements));

            _nodes.Push(new XElement(nameof(CSharpSwitchCase), args));
            return(node);
        }
            public void Analyze(CSharpSwitchCase @case)
            {
                Debug.Assert(_info.HasGotoDefault == false);
                Debug.Assert(_info.GotoCases == null);

                foreach (var stmt in @case.Statements)
                {
                    Visit(stmt);
                }

                if (_info.GotoCases == null)
                {
                    _info.GotoCases = (s_empty ??= new HashSet <object>());
                }

                SwitchCaseInfos.Add(@case, _info);

                _info = default;
            }
            public void EnsureLonelyDefault()
            {
                if (DefaultCase != null && !IsDefaultLonely)
                {
                    // We have a default case but it's mingled up with other cases, e.g.
                    //
                    //   switch (x)
                    //   {
                    //     case 1:
                    //     case 2:
                    //     default:
                    //       ...
                    //       break;
                    //   }
                    //
                    // We can simply drop the other test values for compilation purposes, e.g.
                    //
                    //  switch (x)
                    //  {
                    //    default:
                    //       ...
                    //       break;
                    //  }

                    var roDefaultTestValues = new TrueReadOnlyCollection <object>(new[] { SwitchCaseDefaultValue });
                    var newDefaultCase      = new CSharpSwitchCase(roDefaultTestValues, DefaultCase.Statements);

                    if (DefaultCase == NullCase)
                    {
                        NullCase     = null;
                        IsNullLonely = false;
                    }

                    DefaultCase     = newDefaultCase;
                    IsDefaultLonely = true;
                }
            }
        private static IList <CSharpSwitchCase> ReduceGotos(IList <CSharpSwitchCase> cases)
        {
            var testValueToCaseMap = new Dictionary <object, CSharpSwitchCase>();

            var analyzer = new SwitchCaseGotoAnalyzer();

            var defaultCase = default(CSharpSwitchCase);

            foreach (var @case in cases)
            {
                foreach (var testValue in @case.TestValues)
                {
                    if (testValue == SwitchCaseDefaultValue)
                    {
                        defaultCase = @case;
                    }

                    testValueToCaseMap.Add(testValue.OrNullSentinel(), @case);
                }

                analyzer.Analyze(@case);
            }

            var caseHasJumpInto = new HashSet <CSharpSwitchCase>();

            foreach (var info in analyzer.SwitchCaseInfos.Values)
            {
                if (info.HasGotoDefault)
                {
                    if (defaultCase == null)
                    {
                        throw Error.InvalidGotoDefault();
                    }

                    caseHasJumpInto.Add(defaultCase);
                }

                foreach (var gotoCase in info.GotoCases)
                {
                    if (!testValueToCaseMap.TryGetValue(gotoCase.OrNullSentinel(), out CSharpSwitchCase @case))
                    {
                        throw Error.InvalidGotoCase(gotoCase.ToDebugString());
                    }

                    caseHasJumpInto.Add(@case);
                }
            }

            if (caseHasJumpInto.Count > 0)
            {
                var caseJumpTargets   = new Dictionary <CSharpSwitchCase, LabelTarget>();
                var defaultJumpTarget = default(LabelTarget);

                foreach (var @case in caseHasJumpInto)
                {
                    var label = default(LabelTarget);

                    if (@case == defaultCase)
                    {
                        label = defaultJumpTarget = Expression.Label("__default");
                    }
                    else
                    {
                        label = Expression.Label(FormattableString.Invariant($"__case<{@case.TestValues[0].ToDebugString()}>"));
                    }

                    caseJumpTargets.Add(@case, label);
                }

                var rewriter = new SwitchCaseRewriter(testValue => caseJumpTargets[testValueToCaseMap[testValue.OrNullSentinel()]], defaultJumpTarget);

                var newCases = new CSharpSwitchCase[cases.Count];

                var i = 0;
                foreach (var @case in cases)
                {
                    var newBody = rewriter.Visit(@case.Statements);

                    if (caseJumpTargets.TryGetValue(@case, out LabelTarget jumpTarget))
                    {
                        newBody = newBody.AddFirst(Expression.Label(jumpTarget)).ToReadOnly();
                    }

                    newCases[i++] = @case.Update(newBody);
                }

                return(newCases);
            }
            else
            {
                return(cases);
            }
        }
 private static SwitchCase ConvertSwitchCase(CSharpSwitchCase @case, Type type) =>
 Expression.SwitchCase(
     MakeBlock(@case.Statements),
     @case.TestValues.Select(testValue => Expression.Constant(testValue, type))
     );
Пример #6
0
 public XNode GetDebugView(CSharpSwitchCase switchCase)
 {
     return(Visit(switchCase));
 }
Пример #7
0
 private XNode Visit(CSharpSwitchCase node)
 {
     VisitSwitchCase(node);
     return(_nodes.Pop());
 }
Пример #8
0
 protected internal virtual CSharpSwitchCase VisitSwitchCase(CSharpSwitchCase node) =>
 node.Update(
     Visit(node.Statements)
     );
 public CSharpSwitchCaseProxy(CSharpSwitchCase node)
 {
     _node = node;
 }