Esempio n. 1
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            var state               = SaveState();
            var remaps              = ReflectionHelper.GetCustomAttributes <ParameterDataflowAttribute>(node.Method, true);
            var method              = node.Method;
            var methodParameters    = method.GetParameters();
            var changed             = false;
            var arguments           = new Expression[node.Arguments.Count];
            var propertyAccessArray = new LooselyLinkedListNode <PropertyChainNode> [node.Arguments.Count];
            var ghostAccessArray    = new LooselyLinkedListNode <PropertyChainNode> [node.Arguments.Count];

            for (int i = 0; i < node.Arguments.Count; i++)
            {
                var arg      = node.Arguments[i];
                var argument = Visit(arg);
                arguments[i]           = argument;
                changed               |= argument != arg;
                propertyAccessArray[i] = propertyAccesses.First.Next;
                propertyAccesses.Clear();
            }
            Expression obj = node.Object;

            if (obj != null)
            {
                obj      = Visit(node.Object);
                changed |= obj != node.Object;
            }
            var objectPropertyAccesses = propertyAccesses.First.Next;

            propertyAccesses.Clear();
            var defaultList = Enumerable.Range(0, node.Arguments.Count).ToList();

            for (int i = 0; i < node.Arguments.Count; i++)
            {
                if (propertyAccessArray[i] == null)
                {
                    continue;
                }
                defaultList[i] = -2;
                var lambda = FindLambdaExpression(node.Arguments[i]);
                if (lambda != null)
                {
                    var remapsforLambda = remaps.Where(a => a.FunctionIndex == i);
                    var argumentMaps    = new List <int> [lambda.Parameters.Count];
                    foreach (var remap in remapsforLambda)
                    {
                        List <int> remapForArgument = argumentMaps[remap.SourceIndex];
                        if (remapForArgument == null)
                        {
                            remapForArgument = new List <int>();
                            argumentMaps[remap.SourceIndex] = remapForArgument;
                        }
                        remapForArgument.Add(remap.FunctionParameterIndex);
                    }
                    for (int j = 0; j < lambda.Parameters.Count; j++)
                    {
                        var parameter    = lambda.Parameters[j];
                        var dependencies = argumentMaps[j] ?? defaultList;
                        var dummy        = LooselyLinkedListNode <PropertyChainNode> .CreateDummyFor(propertyAccessArray[i]);

                        var ghostDummy = LooselyLinkedListNode <PropertyChainNode> .CreateDummyFor(ghostAccessArray[i]);

                        var current      = dummy;
                        var currentGhost = ghostDummy;
                        while (current.Next != null)
                        {
                            if (current.Next.Value.Parameter == parameter)
                            {
                                var access = current.Next.Value;
                                current.CutNext();
                                foreach (var dependency in dependencies)
                                {
                                    if (dependency == -2)
                                    {
                                        continue;
                                    }
                                    PropagatePropertyAccesses(propertyAccessArray, objectPropertyAccesses, ref current, ref currentGhost, access, dependency);
                                    PropagatePropertyAccesses(ghostAccessArray, null, ref current, ref currentGhost, access, dependency);
                                }
                            }
                            else
                            {
                                current = current.Next;
                            }
                        }
                        propertyAccessArray[i] = dummy.Next;
                    }
                    Expression returnValue;
                    if (ResetForLambdaExpression(state, node, lambda, out returnValue))
                    {
                        return(returnValue);
                    }
                }
                defaultList[i] = i;
            }
            if (objectPropertyAccesses != null)
            {
                propertyAccesses.AddFirst(objectPropertyAccesses);
            }
            for (int i = node.Arguments.Count - 1; i >= 0; i--)
            {
                if (propertyAccessArray[i] != null)
                {
                    propertyAccesses.AddFirst(propertyAccessArray[i]);
                }
            }
            if (changed)
            {
                return(node.Update(obj, arguments));
            }
            return(node);
        }