private void GenerateValueMemberBlock(TypeToken typeToken, IMethodBlock memberAccess, Method.BlockCollection block)
        {
            var instanceInitializer        = CreateInstanceInitializer(typeToken, memberAccess);
            var defaultInstanceInitializer = instanceInitializer == default(IMethodBlock);

            if (defaultInstanceInitializer && typeToken.IsClass)
            {
                instanceInitializer = new Method.Assignment(memberAccess, typeToken.NewExpression().ToMethodBlock());
            }

            if (instanceInitializer != default)
            {
                block.Children.Add(instanceInitializer);
            }

            if (!defaultInstanceInitializer)
            {
                return;
            }

            foreach (var subMemberToken in MemberProvider(typeToken))
            {
                GenerateMemberBlock(subMemberToken, memberAccess, block);
            }
        }
Пример #2
0
            public MethodCall(IMethodBlock invocationTarget, MethodInfo method, params IMethodBlock[] parameters)
            {
                Debug.Assert((invocationTarget == null) == method.IsStatic);

                InvocationTarget = invocationTarget;
                Method           = method;
                Parameters       = parameters;
            }
        private void GenerateMemberBlock(MemberToken memberToken, IMethodBlock declaringInstanceAccess, Method.BlockCollection block)
        {
            var memberAccess = new Method.MemberAccess(declaringInstanceAccess, memberToken);

            if (memberToken.IsArray)
            {
                GenerateArrayMemberBlock(memberToken, memberAccess, block);
            }
            else
            {
                GenerateValueMemberBlock(memberToken.TypeToken, memberAccess, block);
            }
        }
Пример #4
0
 public Assignment(IMethodBlock left, IMethodBlock right)
 {
     Left  = left;
     Right = right;
 }
Пример #5
0
 public bool Equals(IMethodBlock other)
 => other is Parameter paramOther && Equals(paramOther);
Пример #6
0
 public bool Equals(IMethodBlock other)
 => other is Expression exprOther && Equals(exprOther);
Пример #7
0
 public bool Equals(IMethodBlock other)
 => other is BlockCollection collectionOther && Equals(collectionOther);
Пример #8
0
 public Convert(IMethodBlock instance, Type type)
 {
     Instance = instance;
     Type     = type;
 }
Пример #9
0
 public Property(IMethodBlock instance, PropertyInfo propertyInfo, params IMethodBlock[] arguments)
 {
     Instance     = instance;
     PropertyInfo = propertyInfo;
     Arguments    = arguments;
 }
Пример #10
0
 public bool Equals(IMethodBlock other)
 => other is ArrayAccess arrayAccessOther && Equals(arrayAccessOther);
Пример #11
0
 public bool Equals(IMethodBlock other)
 => other is Loop loopOther && Equals(loopOther);
Пример #12
0
 public Loop(IMethodBlock iterator, IMethodBlock upperBound, IMethodBlock body)
 {
     Iterator   = iterator;
     UpperBound = upperBound;
     Body       = body;
 }
Пример #13
0
 public bool Equals(IMethodBlock other)
 => other is MemberAccess memberAccessOther && Equals(memberAccessOther);
Пример #14
0
 public MemberAccess(IMethodBlock declaringInstance, MemberToken memberToken)
 {
     DeclaringInstance = declaringInstance;
     Member            = memberToken;
 }
Пример #15
0
 public DelegatedArrayAccess(IMethodBlock array)
 {
     Array = array;
     Index = default !;
Пример #16
0
 public bool Equals(IMethodBlock other)
 => other is Property propertyOther && Equals(propertyOther);
Пример #17
0
 public bool Equals(IMethodBlock other)
 => other is Assignment assignmentOther && Equals(assignmentOther);
Пример #18
0
 public ArrayAccess(IMethodBlock array, IMethodBlock index)
 {
     Array = array;
     Index = index;
 }
        private void GenerateArrayMemberBlock(MemberToken memberToken, IMethodBlock memberAccess, Method.BlockCollection block)
        {
            var elementTypeToken = memberToken.TypeToken.GetElementTypeToken();

            var arraySize           = GetCardinality(memberToken);
            var arraySizeExpression = Expr.Constant(arraySize);

            // Give the generator a chance to create the array
            var arrayInitializer        = CreateArrayInitializer(memberToken, memberAccess);
            var defaultArrayInitializer = arrayInitializer == default(IMethodBlock);

            if (defaultArrayInitializer) // Otherwise just assign new T[N];
            {
                arrayInitializer = elementTypeToken.NewArrayBounds(arraySizeExpression).ToMethodBlock();
            }

            if (arrayInitializer != null)
            {
                block.Children.Add(new Method.Assignment(memberAccess, arrayInitializer));
                // If the generator provided a specialized initializer, exit now.
                if (!defaultArrayInitializer)
                {
                    return;
                }
            }

            var loopUnrollingNeeded = OnLoopGenerationStart(memberToken) != UnrollingMode.Never;

            if (!loopUnrollingNeeded) // Fast path to reduce allocations
            {
                arraySize = 1;
            }

            var elementAccesses = ArrayPool <Method.DelegatedArrayAccess> .Shared.Rent(arraySize);

            var loopBodyBlocks = ArrayPool <Method.BlockCollection> .Shared.Rent(arraySize);

            for (var i = 0; i < arraySize; ++i)
            {
                elementAccesses[i] = new Method.DelegatedArrayAccess(memberAccess);
                loopBodyBlocks[i]  = new Method.BlockCollection();

                // Classes need a public default ctor
                if (elementTypeToken.IsClass && elementTypeToken != typeof(string))
                {
                    var newElementBlock = elementTypeToken.NewExpression().ToMethodBlock();
                    loopBodyBlocks[i].Children.Add(new Method.Assignment(elementAccesses[i], newElementBlock));
                }

                GenerateValueMemberBlock(elementTypeToken, elementAccesses[i], loopBodyBlocks[i]);

                // If the implementation decides we never need to unroll this loop, save ourselves the trouble
                var unrollingMode = OnLoopGenerationIteration(i, memberToken);
                if (unrollingMode == UnrollingMode.Never)
                {
                    break;
                }

                // If unrolling state was decided to be unknown, we determine if we needed to unroll
                // This is technically legacy code
                if (unrollingMode == UnrollingMode.Unknown)
                {
                    if (i > 0 && !loopUnrollingNeeded)
                    {
                        loopUnrollingNeeded = !loopBodyBlocks[i].Equals(loopBodyBlocks[0]);
                    }
                }
            }

            OnLoopGenerationEnd(memberToken);

            // If all the invocation bodies are equal, we can just loop. Otherwise, we need to unroll it.
            if (loopUnrollingNeeded)
            {
                for (var i = 0; i < arraySize; ++i)
                {
                    elementAccesses[i].Index = Expr.Constant(i).ToMethodBlock();
                    foreach (var variable in loopBodyBlocks[i].Variables)
                    {
                        block.Variables.Add(variable);
                    }

                    block.Children.AddRange(loopBodyBlocks[i].Children);
                }
            }
            else
            {
                var iterationCounter = _iteratorProvider.Rent();

                elementAccesses[0].Index = iterationCounter;
                block.Variables.Add(iterationCounter);

                var arraySizeBlock = arraySizeExpression.ToMethodBlock();
                block.Children.Add(new Method.Assignment(iterationCounter, Expr.Constant(0).ToMethodBlock()));
                block.Children.Add(new Method.Loop(iterationCounter, arraySizeBlock, loopBodyBlocks[0]));

                _iteratorProvider.Return(iterationCounter);
            }

            ArrayPool <Method.DelegatedArrayAccess> .Shared.Return(elementAccesses);

            ArrayPool <Method.BlockCollection> .Shared.Return(loopBodyBlocks);
        }
 protected abstract IMethodBlock CreateInstanceInitializer(TypeToken typeToken, IMethodBlock assignmentTarget);
Пример #21
0
 public bool Equals(IMethodBlock other)
 => other is Convert convertOther && Equals(convertOther);
 protected abstract IMethodBlock CreateArrayInitializer(MemberToken memberToken, IMethodBlock assignmentTarget);
Пример #23
0
 public bool Equals(IMethodBlock other)
 => other is MethodCall methodCallOther && Equals(methodCallOther);
Пример #24
0
 public bool Equals(IMethodBlock other)
 => other is Empty emptyOther && Equals(emptyOther);
Пример #25
0
 public ArrayIndex(IMethodBlock array, IMethodBlock index)
 {
     Array = array;
     Index = index;
 }