Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
 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));
     }
 }
Пример #4
0
        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;
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
 public virtual void VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x)
 {
     Accept(x.Enumeree);
     x.NextBlock.Accept(this);
 }
Пример #8
0
        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);
        }
Пример #9
0
 public override void VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x)
 {
     Accept(x.Enumeree);
     VisitCFGSimpleEdge(x);
 }
Пример #10
0
 public virtual void VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x)
 {
     Accept(x.Enumeree);
     x.NextBlock.Accept(this);
 }
Пример #11
0
 public virtual TResult VisitCFGForeachEnumereeEdge(ForeachEnumereeEdge x) => DefaultVisitEdge(x);