public override object VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x) { IsConditional = true; var updated = x.Update( (BoundBlock)Accept(x.Target), (BoundExpression)Accept(x.Enumeree), x.AreValuesAliased); if (updated != x) { // Fix reference from the following ForEachMoveNextEdge var moveNext = (ForeachMoveNextEdge)updated.NextBlock.NextEdge; Debug.Assert(moveNext.EnumereeEdge == x); updated.NextBlock.NextEdge = moveNext.Update( moveNext.BodyBlock, moveNext.NextBlock, updated, moveNext.KeyVariable, moveNext.ValueVariable, moveNext.MoveSpan); } return(updated); }
public override void VisitForeachStmt(ForeachStmt x) { // binds enumeree expression & connect pre-enumeree-expr blocks var boundEnumereeBag = _binder.BindWholeExpression(x.Enumeree, BoundAccess.Read); ConnectBoundItemsBagBlocksToCurrentBlock(boundEnumereeBag); var end = NewBlock(); var move = NewBlock(); var body = NewBlock(); // _current -> move -> body -> move -> ... // ForeachEnumereeEdge : SimpleEdge // x.Enumeree.GetEnumerator(); var enumereeEdge = new ForeachEnumereeEdge(_current, move, boundEnumereeBag.BoundElement, x.ValueVariable.Alias); // ContinueTarget: OpenBreakScope(end, move); // bind reference expression for foreach key variable BoundReferenceExpression keyVar = (x.KeyVariable != null) ? (BoundReferenceExpression)_binder.BindWholeExpression(x.KeyVariable.Variable, BoundAccess.Write).GetOnlyBoundElement() : null; // bind reference expression for foreach value variable var valueVar = (BoundReferenceExpression)(_binder.BindWholeExpression( (Expression)x.ValueVariable.Variable ?? x.ValueVariable.List, x.ValueVariable.Alias ? BoundAccess.Write.WithWriteRef(FlowAnalysis.TypeRefMask.AnyType) : BoundAccess.Write ).GetOnlyBoundElement()); // ForeachMoveNextEdge : ConditionalEdge var moveEdge = new ForeachMoveNextEdge(move, body, end, enumereeEdge, keyVar, valueVar, Span.FromBounds(x.Enumeree.Span.End + 1, (x.KeyVariable ?? x.ValueVariable).Span.Start - 1).ToTextSpan() /*"as" between enumeree and variables*/); // while (enumerator.MoveNext()) { // var value = enumerator.Current.Value // var key = enumerator.Current.Key // Block // { x.Body } _current = WithOpenScope(WithNewOrdinal(body)); VisitElement(x.Body); CloseScope(); // goto ContinueTarget; Connect(_current, move); // BreakTarget: CloseBreakScope(); // _current = WithNewOrdinal(end); }
public ForeachMoveNextEdge Update(BoundBlock body, BoundBlock end, ForeachEnumereeEdge enumereeEdge, BoundReferenceExpression keyVar, BoundReferenceExpression /*!*/ valueVar, TextSpan moveSpan) { if (body == BodyBlock && end == _end && enumereeEdge == EnumereeEdge && keyVar == KeyVariable && valueVar == ValueVariable && moveSpan == MoveNextSpan) { return(this); } else { return(new ForeachMoveNextEdge(body, end, enumereeEdge, keyVar, valueVar, moveSpan)); } }
internal ForeachMoveNextEdge(BoundBlock /*!*/ body, BoundBlock /*!*/ end, ForeachEnumereeEdge /*!*/ enumereeEdge, BoundReferenceExpression keyVar, BoundReferenceExpression /*!*/ valueVar, TextSpan moveSpan) { Contract.ThrowIfNull(body); Contract.ThrowIfNull(end); Contract.ThrowIfNull(enumereeEdge); this.BodyBlock = body; _end = end; this.EnumereeEdge = enumereeEdge; this.KeyVariable = keyVar; this.ValueVariable = valueVar; this.MoveNextSpan = moveSpan; }
internal ForeachMoveNextEdge(BoundBlock /*!*/ source, BoundBlock /*!*/ body, BoundBlock /*!*/ end, ForeachEnumereeEdge /*!*/ enumereeEdge, BoundReferenceExpression keyVar, BoundReferenceExpression /*!*/ valueVar) : base(source) { Contract.ThrowIfNull(body); Contract.ThrowIfNull(end); Contract.ThrowIfNull(enumereeEdge); _body = body; _end = end; _enumereeEdge = enumereeEdge; _keyVariable = keyVar; _valueVariable = valueVar; Connect(source); }
public override void VisitForeachStmt(ForeachStmt x) { var end = NewBlock(); var move = NewBlock(); var body = NewBlock(); // _current -> move -> body -> move -> ... // ForeachEnumereeEdge : SimpleEdge // x.Enumeree.GetEnumerator(); var enumereeEdge = new ForeachEnumereeEdge(_current, move, _binder.BindExpression(x.Enumeree, BoundAccess.Read), x.ValueVariable.Alias); // ContinueTarget: OpenBreakScope(end, move); // ForeachMoveNextEdge : ConditionalEdge var moveEdge = new ForeachMoveNextEdge(move, body, end, enumereeEdge, (x.KeyVariable != null) ? (BoundReferenceExpression)_binder.BindExpression(x.KeyVariable.Variable, BoundAccess.Write) : null, (BoundReferenceExpression)_binder.BindExpression( (Expression)x.ValueVariable.Variable ?? x.ValueVariable.List, x.ValueVariable.Alias ? BoundAccess.Write.WithWriteRef(FlowAnalysis.TypeRefMask.AnyType) : BoundAccess.Write)); // while (enumerator.MoveNext()) { // var key = enumerator.Current.Key // var value = enumerator.Current.Value // Block // { x.Body } _current = WithOpenScope(WithNewOrdinal(body)); VisitElement(x.Body); CloseScope(); // goto ContinueTarget; Connect(_current, move); // BreakTarget: CloseBreakScope(); // _current = WithNewOrdinal(end); }
public virtual void VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x) { Accept(x.Enumeree); x.NextBlock.Accept(this); }
internal ForeachMoveNextEdge(BoundBlock/*!*/source, BoundBlock/*!*/body, BoundBlock/*!*/end, ForeachEnumereeEdge/*!*/enumereeEdge, BoundReferenceExpression keyVar, BoundReferenceExpression/*!*/valueVar) : base(source) { Contract.ThrowIfNull(body); Contract.ThrowIfNull(end); Contract.ThrowIfNull(enumereeEdge); _body = body; _end = end; _enumereeEdge = enumereeEdge; _keyVariable = keyVar; _valueVariable = valueVar; Connect(source); }
public override void VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x) { Accept(x.Enumeree); VisitCFGSimpleEdge(x); }
public virtual TResult VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x) => DefaultVisitEdge(x);