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); } }
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); } }
public Assignment(IMethodBlock left, IMethodBlock right) { Left = left; Right = right; }
public bool Equals(IMethodBlock other) => other is Parameter paramOther && Equals(paramOther);
public bool Equals(IMethodBlock other) => other is Expression exprOther && Equals(exprOther);
public bool Equals(IMethodBlock other) => other is BlockCollection collectionOther && Equals(collectionOther);
public Convert(IMethodBlock instance, Type type) { Instance = instance; Type = type; }
public Property(IMethodBlock instance, PropertyInfo propertyInfo, params IMethodBlock[] arguments) { Instance = instance; PropertyInfo = propertyInfo; Arguments = arguments; }
public bool Equals(IMethodBlock other) => other is ArrayAccess arrayAccessOther && Equals(arrayAccessOther);
public bool Equals(IMethodBlock other) => other is Loop loopOther && Equals(loopOther);
public Loop(IMethodBlock iterator, IMethodBlock upperBound, IMethodBlock body) { Iterator = iterator; UpperBound = upperBound; Body = body; }
public bool Equals(IMethodBlock other) => other is MemberAccess memberAccessOther && Equals(memberAccessOther);
public MemberAccess(IMethodBlock declaringInstance, MemberToken memberToken) { DeclaringInstance = declaringInstance; Member = memberToken; }
public DelegatedArrayAccess(IMethodBlock array) { Array = array; Index = default !;
public bool Equals(IMethodBlock other) => other is Property propertyOther && Equals(propertyOther);
public bool Equals(IMethodBlock other) => other is Assignment assignmentOther && Equals(assignmentOther);
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);
public bool Equals(IMethodBlock other) => other is Convert convertOther && Equals(convertOther);
protected abstract IMethodBlock CreateArrayInitializer(MemberToken memberToken, IMethodBlock assignmentTarget);
public bool Equals(IMethodBlock other) => other is MethodCall methodCallOther && Equals(methodCallOther);
public bool Equals(IMethodBlock other) => other is Empty emptyOther && Equals(emptyOther);
public ArrayIndex(IMethodBlock array, IMethodBlock index) { Array = array; Index = index; }