public override object VisitCFGSwitchEdge(SwitchEdge x) { return(x.Update( (BoundExpression)Accept(x.SwitchValue), VisitBlockImmutableArray(x.CaseBlocks), (BoundBlock)Accept(x.NextBlock))); }
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); } }
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); }
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); }
public override void VisitCFGSwitchEdge(SwitchEdge x) { Accept(x.SwitchValue); var state = _state; foreach (var c in x.CaseBlocks) { TraverseToBlock(state, c); } }
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); }
public virtual TResult VisitCFGSwitchEdge(SwitchEdge x) => DefaultVisitEdge(x);