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 = BoundSynthesizedVariableRef.CreateAndAssignSynthesizedVariable(switchValue, BoundAccess.Read, $"<switchValueCacher>{x.Span}"); switchValue = result.Item1; _current.Add(new BoundExpressionStatement(result.Item2)); } // 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); }
public override void VisitSynthesizedVariableRef(BoundSynthesizedVariableRef x) { // do not make diagnostics on syntesized variables }
public virtual void VisitSynthesizedVariableRef(BoundSynthesizedVariableRef x) { // BoundSynthesizedVariableRef is based solely on BoundVariableRef so far VisitVariableRef(x); }