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)) );
public XNode GetDebugView(CSharpSwitchCase switchCase) { return(Visit(switchCase)); }
private XNode Visit(CSharpSwitchCase node) { VisitSwitchCase(node); return(_nodes.Pop()); }
protected internal virtual CSharpSwitchCase VisitSwitchCase(CSharpSwitchCase node) => node.Update( Visit(node.Statements) );
public CSharpSwitchCaseProxy(CSharpSwitchCase node) { _node = node; }