Beispiel #1
0
        bool AdjustInitializerStack(List <ILExpression> initializerStack, List <ILExpression> getters, ILExpression argument, ILVariable v, bool isCollection, bool isValueType)
        {
            // Argument is of the form 'getter(getter(...(v)))'
            // Unpack it into a list of getters:
            getters.Clear();
            while (argument.Code == ILCode.CallvirtGetter || argument.Code == ILCode.CallGetter || argument.Code == ILCode.Ldfld)
            {
                getters.Add(argument);
                if (argument.Arguments.Count != 1)
                {
                    return(false);
                }
                argument = argument.Arguments[0];
            }
            // Ensure that the final argument is 'v'
            if (isValueType)
            {
                ILVariable loadedVar;
                if (!(argument.Match(ILCode.Ldloca, out loadedVar) && loadedVar == v))
                {
                    return(false);
                }
            }
            else
            {
                if (!argument.MatchLdloc(v))
                {
                    return(false);
                }
            }
            // Now compare the getters with those that are currently active on the initializer stack:
            int i;

            for (i = 1; i <= Math.Min(getters.Count, initializerStack.Count - 1); i++)
            {
                ILExpression g1 = initializerStack[i].Arguments[0];           // getter stored in initializer
                ILExpression g2 = getters[getters.Count - i];                 // matching getter from argument
                if (g1.Operand != g2.Operand)
                {
                    // operands differ, so we abort the comparison
                    break;
                }
            }
            // Remove all initializers from the stack that were not matched with one from the argument:
            initializerStack.RemoveRange(i, initializerStack.Count - i);
            // Now create new initializers for the remaining arguments:
            for (; i <= getters.Count; i++)
            {
                ILExpression g  = getters[getters.Count - i];
                IMemberRef   mr = g.Operand as IMemberRef;
                TypeSig      returnType;
                if (mr == null || mr.IsField)
                {
                    returnType = TypeAnalysis.GetFieldType((IField)mr);
                }
                else
                {
                    returnType = TypeAnalysis.SubstituteTypeArgs(((IMethod)mr).MethodSig.GetRetType(), method: (IMethod)mr);
                }

                ILExpression nestedInitializer = new ILExpression(
                    IsCollectionType(returnType) ? ILCode.InitCollection : ILCode.InitObject,
                    null, g);
                // add new initializer to its parent:
                ILExpression parentInitializer = initializerStack[initializerStack.Count - 1];
                if (parentInitializer.Code == ILCode.InitCollection)
                {
                    // can't add children to collection initializer
                    if (parentInitializer.Arguments.Count == 1)
                    {
                        // convert empty collection initializer to object initializer
                        parentInitializer.Code = ILCode.InitObject;
                    }
                    else
                    {
                        return(false);
                    }
                }
                parentInitializer.Arguments.Add(nestedInitializer);
                initializerStack.Add(nestedInitializer);
            }
            ILExpression lastInitializer = initializerStack[initializerStack.Count - 1];

            if (isCollection)
            {
                return(lastInitializer.Code == ILCode.InitCollection);
            }
            else
            {
                if (lastInitializer.Code == ILCode.InitCollection)
                {
                    if (lastInitializer.Arguments.Count == 1)
                    {
                        // convert empty collection initializer to object initializer
                        lastInitializer.Code = ILCode.InitObject;
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(true);
                }
            }
        }