Exemplo n.º 1
0
        /// <summary>
        /// Returns true iff the equality and hashcode functions defined in
        /// <paramref name="payloadEqualityComparer"/> can be used in columnar codegen.
        /// </summary>
        /// <typeparam name="T">The type of the payload</typeparam>
        /// <param name="payloadEqualityComparer">The equality and hashcode functions
        /// represented as lambda expressions.</param>
        /// <returns>True iff both the equality and hashcode functions can be used in columnar
        /// codegen operators.</returns>
        public static bool CanUsePayloadEquality <T>(this IEqualityComparerExpression <T> payloadEqualityComparer)
        {
            var typeofT = typeof(T);

            // If T is a struct, then even if the user defined equality function calls a method on the struct,
            // it can still be used because the active events will have a field of type T.
            if (typeofT.GetTypeInfo().IsValueType)
            {
                return(true);
            }

            // If T is a type for which the columnar representation is just a pseudo-field, e.g., string,
            // then the payload is not really represented as a set of its fields, but is an instance of T
            if (new ColumnarRepresentation(typeofT).noFields)
            {
                return(true);
            }

            // If T is a reference type, then codegen is going to define a structurally-equivalent type T'
            // and the active events will have a field of type T'. So if the equality or hash functions ever
            // use a value of type T (other than to dereference it for a field/property) then it cannot be used.
            var equalsIsBad = ParameterInstanceFinder.FoundInstance(payloadEqualityComparer.GetEqualsExpr());
            var hashIsBad   = ParameterInstanceFinder.FoundInstance(payloadEqualityComparer.GetGetHashCodeExpr());

            return(!equalsIsBad && !hashIsBad);
        }
Exemplo n.º 2
0
        public static IEqualityComparerExpression <T> GetCompoundEqualityComparerExpression <T, T1, T2, T3>(Expression <Func <T, T1> > lambda1, IEqualityComparerExpression <T1> iece1, Expression <Func <T, T2> > lambda2, IEqualityComparerExpression <T2> iece2, Expression <Func <T, T3> > lambda3, IEqualityComparerExpression <T3> iece3)
        {
            var iece1EqualsExpr = iece1.GetEqualsExpr();
            var iece2EqualsExpr = iece2.GetEqualsExpr();
            var iece3EqualsExpr = iece3.GetEqualsExpr();

            Expression <Func <T, T, bool> > equalsTemplate =
                (left, right) =>
                CallInliner.Call(iece1EqualsExpr, CallInliner.Call(lambda1, left), CallInliner.Call(lambda1, right)) &&
                CallInliner.Call(iece2EqualsExpr, CallInliner.Call(lambda2, left), CallInliner.Call(lambda2, right)) &&
                CallInliner.Call(iece3EqualsExpr, CallInliner.Call(lambda3, left), CallInliner.Call(lambda3, right))
            ;

            var iece1HashExpr = iece1.GetGetHashCodeExpr();
            var iece2HashExpr = iece2.GetGetHashCodeExpr();
            var iece3HashExpr = iece3.GetGetHashCodeExpr();

            Expression <Func <T, int> > hashTemplate =
                value =>
                CallInliner.Call(iece1HashExpr, CallInliner.Call(lambda1, value)) ^
                CallInliner.Call(iece2HashExpr, CallInliner.Call(lambda2, value)) ^
                CallInliner.Call(iece3HashExpr, CallInliner.Call(lambda3, value))
            ;

            return(new EqualityComparerExpression <T>(equalsTemplate.InlineCalls(), hashTemplate.InlineCalls()));
        }
Exemplo n.º 3
0
        public static Func <FastDictionary2 <TKey, TValue> > CreateFastDictionary2Generator <TKey, TValue>(
            this IEqualityComparerExpression <TKey> comparerExp, int capacity, Func <TKey, TKey, bool> equalsFunc, Func <TKey, int> getHashCodeFunc, QueryContainer container)
        {
            if (EqualityComparerExpression <TKey> .IsSimpleDefault(comparerExp))
            {
                return(() => new FastDictionary2 <TKey, TValue>());
            }
            if (container == null)
            {
                return(() => new FastDictionary2 <TKey, TValue>(capacity, equalsFunc, getHashCodeFunc));
            }

            var equalsExp      = comparerExp.GetEqualsExpr();
            var getHashCodeExp = comparerExp.GetGetHashCodeExpr();
            var vars           = VariableFinder.Find(equalsExp).Select(o => o.GetHashCode()).ToList();

            if (!vars.Any())
            {
                vars.Add(string.Empty.StableHash());
            }
            var hashvars = VariableFinder.Find(getHashCodeExp).Select(o => o.GetHashCode()).ToList();

            if (!hashvars.Any())
            {
                hashvars.Add(string.Empty.StableHash());
            }
            var key =
                Tuple.Create(
                    equalsExp.ToString() + getHashCodeExp.ToString() + string.Concat(vars.Aggregate((a, i) => a ^ i)) + string.Concat(hashvars.Aggregate((a, i) => a ^ i)),
                    typeof(TKey), typeof(TValue));

            Type temp;

            lock (sentinel)
            {
                if (!generatorCache.TryGetValue(key, out temp))
                {
                    string typeName    = Prefix + classCounter++;
                    var    builderCode = new GeneratedFastDictionary(typeName, "2").TransformText();
                    var    a           = Transformer.CompileSourceCode(builderCode, Array.Empty <Assembly>(), out string errorMessages);

                    temp = a.GetType(typeName + "`2");
                    temp = temp.MakeGenericType(typeof(TKey), typeof(TValue));
                    MethodInfo init = temp.GetTypeInfo().GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public);
                    init.Invoke(null, new object[] { equalsFunc, getHashCodeFunc, capacity });
                    generatorCache.Add(key, temp);
                }
                if (!container.TryGetFastDictionary2Type(key, out Type other))
                {
                    container.RegisterFastDictionary2Type(key, temp);
                }
            }

            return(() => (FastDictionary2 <TKey, TValue>)Activator.CreateInstance(temp));
        }
Exemplo n.º 4
0
        public static IEqualityComparerExpression <T> GetEqualityComparerExpression <T, T1>(
            Expression <Func <T, T1> > lambda1, IEqualityComparerExpression <T1> iece1)
        {
            var iece1EqualsExpr = iece1.GetEqualsExpr();
            Expression <Func <T, T, bool> > equalsTemplate =
                (left, right) =>
                CallInliner.Call(iece1EqualsExpr, CallInliner.Call(lambda1, left),
                                 CallInliner.Call(lambda1, right));

            var iece1HashExpr = iece1.GetGetHashCodeExpr();
            Expression <Func <T, int> > hashTemplate =
                value =>
                CallInliner.Call(iece1HashExpr, CallInliner.Call(lambda1, value));

            return(new EqualityComparerExpression <T>(equalsTemplate.InlineCalls(), hashTemplate.InlineCalls()));
        }
Exemplo n.º 5
0
 public static bool ExpressionEquals <T>(this IEqualityComparerExpression <T> source, IEqualityComparerExpression <T> other)
 {
     return(EqualityComparer.IsEqual(source.GetEqualsExpr(), other.GetEqualsExpr()) &&
            EqualityComparer.IsEqual(source.GetGetHashCodeExpr(), other.GetGetHashCodeExpr()));
 }
Exemplo n.º 6
0
 private static bool IsEqualIECE <T>(IEqualityComparerExpression <T> o1, IEqualityComparerExpression <T> o2)
 {
     return(EqualityComparer.IsEqual(o1.GetEqualsExpr(), o2.GetEqualsExpr()) &&
            EqualityComparer.IsEqual(o1.GetGetHashCodeExpr(), o2.GetGetHashCodeExpr()));
 }