private Expression EvaluateProperty(ParameterExpression leftEnumerator, ParameterExpression leftSomeLeft, ParameterExpression rightEnumerator, ParameterExpression rightSomeLeft, Expression conflicts, Expression ret, Property property)
        {
            Expression leftCurrent  = Expression.Property(leftEnumerator, EnumerableMembers.Current(typeof(IDiffItem)));
            Expression rightCurrent = Expression.Property(rightEnumerator, EnumerableMembers.Current(typeof(IDiffItem)));

            /* PSEUDO CODE FOR THIS:
             * if (leftSomeLeft && leftCurrent.UniqueID == ID)
             * {
             *     if (rightSomeLeft && rightCurrent.UniqueID == ID)
             *     {
             *         CheckConflicts(leftCurrent, rightCurrent)
             *         rightSomeLeft = next(rightCurrent)
             *     }
             *     else
             *         add(leftCurrent)
             *     leftSomeLeft = next(leftCurrent)
             * }
             * else if (rightSomeLeft && rightCurrent.UniqueID == ID)
             * {
             *     add(rightCurrent)
             *     rightSomeLeft = next(rightCurrent)
             * }
             */

            Expression leftShouldBeProcessed = Expression.AndAlso(
                leftSomeLeft,
                Expression.Equal(
                    Expression.Property(
                        Expression.Property(
                            Expression.Convert(
                                leftCurrent,
                                typeof(IDiffClassItem)
                                ),
                            DiffItemsMembers.ClassProperty()
                            ),
                        FastPropertyMembers.UniqueID()
                        ),
                    Expression.Constant(property.UniqueID)
                    )
                );

            Expression rightShouldBeProcessed = Expression.AndAlso(
                rightSomeLeft,
                Expression.Equal(
                    Expression.Property(
                        Expression.Property(
                            Expression.Convert(
                                rightCurrent,
                                typeof(IDiffClassItem)
                                ),
                            DiffItemsMembers.ClassProperty()
                            ),
                        FastPropertyMembers.UniqueID()
                        ),
                    Expression.Constant(property.UniqueID)
                    )
                );

            return(Expression.IfThenElse(
                       leftShouldBeProcessed,
                       Expression.Block(
                           Expression.IfThenElse(
                               rightShouldBeProcessed,
                               Expression.Block(
                                   this.CompileCheckConflicts(property, leftCurrent, rightCurrent, conflicts, ret),
                                   this.MoveEnumerator(rightEnumerator, rightSomeLeft)
                                   ),
                               Expression.Call(
                                   ret,
                                   ListMembers.Add(typeof(IDiffItem)),
                                   leftCurrent
                                   )
                               ),
                           this.MoveEnumerator(leftEnumerator, leftSomeLeft)
                           ),
                       Expression.IfThen(
                           rightShouldBeProcessed,
                           Expression.Block(
                               Expression.Call(
                                   ret,
                                   ListMembers.Add(typeof(IDiffItem)),
                                   rightCurrent
                                   ),
                               this.MoveEnumerator(rightEnumerator, rightSomeLeft)
                               )
                           )
                       ));
        }
        public static Expression ForEach(ParameterExpression item, Expression source, Expression body)
        {
            if (!typeof(IEnumerable).IsAssignableFrom(source.Type))
            {
                throw new InvalidOperationException($"{source.Type} does not implement IEnumerable and cannot be iterated using foreach");
            }

            ParameterExpression enumerator = Expression.Parameter(typeof(IEnumerator), "enumerator");
            LabelTarget         forEachEnd = Expression.Label();

            return(Expression.Block(
                       new[] { item, enumerator },

                       Expression.Assign(
                           enumerator,
                           Expression.Call(source, EnumerableMembers.GetEnumerator())
                           ),

                       Expression.Loop(
                           Expression.IfThenElse(
                               Expression.Call(enumerator, EnumerableMembers.MoveNext()),

                               Expression.Block(
                                   Expression.Assign(item, Expression.Convert(Expression.Property(enumerator, EnumerableMembers.Current()), item.Type)),
                                   body
                                   ),

                               Expression.Break(forEachEnd)
                               ),
                           forEachEnd
                           )
                       ));
        }