예제 #1
0
            private void PopAndSetResult(InvocationAndState result)
            {
                _invocationStack.Pop();
                var prevFrame = _invocationStack.Peek();

                prevFrame.Invocations.AddLast(result);
            }
예제 #2
0
            protected override Expression VisitInvocation(InvocationExpression node)
            {
                if (_state == RecursionState.Check)
                {
                    Push();

                    var rewritten = (InvocationExpression)base.VisitInvocation(node);

                    var frame = _invocationStack.Peek();

                    var freeCount      = 0;
                    var dqCount        = 0;
                    var candidateCount = 0;

                    foreach (var invocation in frame.Invocations)
                    {
                        if (invocation.State == InvocationSubtreeState.Disqualified)
                        {
                            dqCount++;
                        }
                        else if (invocation.State == InvocationSubtreeState.Free)
                        {
                            freeCount++;
                        }
                        else
                        {
                            candidateCount++;
                        }
                    }

                    if (frame.DelegationTargets.Count == 0)
                    {
                        if (frame.Invocations.Count == freeCount)
                        {
                            PopAndSetResult(InvocationAndState.CreateFree());
                            return(rewritten);
                        }
                        else if (candidateCount == 1 && dqCount == 0)
                        {
                            var candidate = frame.Invocations.Single(i => i.State == InvocationSubtreeState.Candidate).DelegationTarget;
                            var target    = _delegatableTargets[candidate];
                            if (target.CanDelegate(candidate, rewritten))
                            {
                                PopAndSetResult(InvocationAndState.CreateCandidate(candidate));
                                return(rewritten);
                            }
                            else
                            {
                                var delegated = RewriteInvocations(rewritten);
                                PopAndSetResult(InvocationAndState.CreateDisqualified());
                                return(delegated);
                            }
                        }
                        else
                        {
                            var delegated = RewriteInvocations(rewritten);
                            PopAndSetResult(InvocationAndState.CreateDisqualified());
                            return(delegated);
                        }
                    }
                    else if (frame.DelegationTargets.Count > 1)
                    {
                        var delegated = RewriteInvocations(rewritten);
                        PopAndSetResult(InvocationAndState.CreateDisqualified());
                        return(delegated);
                    }
                    else
                    {
                        if (frame.Invocations.Count == freeCount)
                        {
                            var candidate = frame.DelegationTargets.Single();

                            var target = _delegatableTargets[candidate];
                            if (target.CanDelegate(candidate, rewritten))
                            {
                                PopAndSetResult(InvocationAndState.CreateCandidate(candidate));
                                return(rewritten);
                            }
                            else
                            {
                                var delegated = RewriteInvocations(rewritten);
                                PopAndSetResult(InvocationAndState.CreateDisqualified());
                                return(delegated);
                            }
                        }
                        else
                        {
                            var delegated = RewriteInvocations(rewritten);
                            PopAndSetResult(InvocationAndState.CreateDisqualified());
                            return(delegated);
                        }
                    }
                }
                else
                {
                    var currFrame      = _invocationStack.Peek();
                    var currInvocation = currFrame.Invocations.First();
                    currFrame.Invocations.RemoveFirst();

                    if (currInvocation.State == InvocationSubtreeState.Candidate)
                    {
                        var candidate = currInvocation.DelegationTarget;
                        var target    = _delegatableTargets[candidate];
                        return(target.Delegate(candidate, node));
                    }
                    else
                    {
                        return(node);
                    }
                }
            }