protected internal override CSharpSwitchCase VisitSwitchCase(CSharpSwitchCase node) { var statements = VisitSequence(node.Statements); return(node.Update(statements)); }
public CSharpSwitchCaseProxy(CSharpSwitchCase node) { _node = node; }
protected internal override CSharpSwitchCase VisitSwitchCase(CSharpSwitchCase node) { var statements = VisitSequence(node.Statements); return node.Update(statements); }
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: // case default: // ... // break; // } // // We can simply drop the other test values for compilation purposes, e.g. // // switch (x) // { // case 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; } }
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 ?? (s_empty = new HashSet<object>())); } SwitchCaseInfos.Add(@case, _info); _info = default(SwitchCaseInfo); }
private static SwitchCase ConvertSwitchCase(CSharpSwitchCase @case, Type type) { return Expression.SwitchCase(MakeBlock(@case.Statements), @case.TestValues.Select(testValue => Expression.Constant(testValue, type))); }
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) { var @case = default(CSharpSwitchCase); if (!testValueToCaseMap.TryGetValue(gotoCase.OrNullSentinel(), out @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); var jumpTarget = default(LabelTarget); if (caseJumpTargets.TryGetValue(@case, out jumpTarget)) { newBody = newBody.AddFirst(Expression.Label(jumpTarget)).ToReadOnly(); } newCases[i++] = @case.Update(newBody); } return newCases; } else { return cases; } }