Beispiel #1
0
 internal override Expression Visit(Expression expr)
 {
     if (expr == null)
     {
         return(expr);
     }
     if (HpcLinqExpression.IsConstant(expr))
     {
         object val = ExpressionSimplifier.Evaluate(expr);
         if (val is IQueryable)
         {
             QueryNodeInfo nodeInfo;
             if (this.m_referencedQueryMap.TryGetValue(((IQueryable)val).Expression, out nodeInfo))
             {
                 string name = "side__" + this.m_idx;
                 this.m_idx++;
                 this.m_referencedQueries.Add(new Pair <string, DryadQueryNode>(name, nodeInfo.queryNode));
                 return(Expression.Parameter(expr.Type, name));
             }
             throw new DryadLinqException(HpcLinqErrorCode.UnhandledQuery,
                                          String.Format(SR.UnhandledQuery, HpcLinqExpression.Summarize(expr)));
         }
         return(expr);
     }
     return(base.Visit(expr));
 }
Beispiel #2
0
        internal static Exception Create(int errorCode, string msg, Expression expr)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(msg);
            sb.Append(" Expression : ");
            sb.AppendLine(HpcLinqExpression.Summarize(expr, 1));

            return(new DryadLinqException(errorCode, sb.ToString()));
        }
Beispiel #3
0
        internal override PartitionInfo Rewrite(LambdaExpression resultSel, ParameterExpression param)
        {
            ParameterExpression a         = this.m_keySelector.Parameters[0];
            Substitution        pSubst    = Substitution.Empty.Cons(a, param);
            LambdaExpression    newKeySel = HpcLinqExpression.Rewrite(this.m_keySelector, resultSel, pSubst);

            if (newKeySel == null)
            {
                return(new RandomPartition(this.m_count));
            }
            return(this.Create(newKeySel));
        }
Beispiel #4
0
 internal override Expression Visit(Expression expr)
 {
     if (expr == null)
     {
         return(expr);
     }
     if (HpcLinqExpression.IsConstant(expr))
     {
         object val = ExpressionSimplifier.Evaluate(expr);
         if (val is IQueryable)
         {
             this.m_querySet.Add(((IQueryable)val).Expression);
         }
         return(expr);
     }
     return(base.Visit(expr));
 }
Beispiel #5
0
        //This is the IQueryProvider.Execute() method used for execution when a single value is produced (rather than an enumerable)
        public override TResult Execute <TResult>(Expression expression)
        {
            MethodCallExpression callExpr = expression as MethodCallExpression;

            if (callExpr == null)
            {
                throw new ArgumentException(String.Format(SR.ExpressionMustBeMethodCall,
                                                          HpcLinqExpression.Summarize(expression)), "expression");
            }
            string methodName = callExpr.Method.Name;

            if (methodName == "FirstOrDefault" ||
                methodName == "SingleOrDefault" ||
                methodName == "LastOrDefault")
            {
                Type qType = typeof(DryadLinqQuery <>).MakeGenericType(typeof(AggregateValue <>).MakeGenericType(expression.Type));
                AggregateValue <TResult> res = ((IEnumerable <AggregateValue <TResult> >)
                                                Activator.CreateInstance(
                                                    qType,
                                                    BindingFlags.NonPublic | BindingFlags.Instance,
                                                    null,
                                                    new object[] { this, expression },
                                                    CultureInfo.CurrentCulture
                                                    )).Single();
                if (res.Count == 0)
                {
                    return(default(TResult));
                }
                return(res.Value);
            }
            else
            {
                Type qType = typeof(DryadLinqQuery <>).MakeGenericType(expression.Type);
                return(((IEnumerable <TResult>)Activator.CreateInstance(
                            qType,
                            BindingFlags.NonPublic | BindingFlags.Instance,
                            null,
                            new object[] { this, expression },
                            CultureInfo.CurrentCulture
                            )).Single());
            }
        }
        private static DecompositionInfo GetDecompositionInfo(ParameterExpression groupParam,
                                                              MethodCallExpression mcExpr,
                                                              HpcLinqCodeGen codeGen)
        {
            if (mcExpr.Arguments.Count == 0 || mcExpr.Arguments[0] != groupParam)
            {
                return(null);
            }
            for (int i = 1; i < mcExpr.Arguments.Count; i++)
            {
                if (HpcLinqExpression.Contains(groupParam, mcExpr.Arguments[i]))
                {
                    return(null);
                }
            }

            ExpressionSimplifier <object> evaluator = new ExpressionSimplifier <object>();

            Type[] paramTypeArgs  = groupParam.Type.GetGenericArguments();
            Type   sourceElemType = paramTypeArgs[paramTypeArgs.Length - 1];
            Type   resultType     = mcExpr.Type;
            Type   decomposerType = null;

            DecomposableAttribute decomposableAttrib = AttributeSystem.GetDecomposableAttrib(mcExpr);

            if (decomposableAttrib != null)
            {
                decomposerType = decomposableAttrib.DecompositionType;
            }
            else
            {
                MethodInfo mInfo = mcExpr.Method;
                if (mInfo.DeclaringType == typeof(System.Linq.Enumerable) ||
                    mInfo.DeclaringType == typeof(System.Linq.Queryable))
                {
                    // For built-in decomposable operators.
                    switch (mInfo.Name)
                    {
                    case "Count":
                    case "LongCount":
                    {
                        Type       outputType;
                        Expression body;
                        if (mInfo.Name == "Count")
                        {
                            outputType = typeof(Int32);
                            body       = Expression.Constant(1, outputType);
                        }
                        else
                        {
                            outputType = typeof(Int64);
                            body       = Expression.Constant((long)1, outputType);
                        }
                        ParameterExpression param1   = Expression.Parameter(outputType, "a");
                        ParameterExpression param2   = Expression.Parameter(sourceElemType, "e");
                        LambdaExpression    seedExpr = Expression.Lambda(body, param2);
                        body = Expression.AddChecked(param1, body);
                        LambdaExpression accumulateExpr = Expression.Lambda(body, param1, param2);
                        param2 = Expression.Parameter(outputType, "b");
                        body   = Expression.AddChecked(param1, param2);
                        LambdaExpression recursiveAccumulateExpr = Expression.Lambda(body, param1, param2);

                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "Any":
                    {
                        ParameterExpression param1 = Expression.Parameter(typeof(bool), "a");
                        ParameterExpression param2;
                        Expression          body;
                        if (mcExpr.Arguments.Count == 1)
                        {
                            param2 = Expression.Parameter(sourceElemType, "e");
                            body   = Expression.Constant(true, typeof(bool));
                        }
                        else
                        {
                            LambdaExpression predExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[1]);
                            param2 = predExpr.Parameters[0];
                            body   = predExpr.Body;
                        }

                        LambdaExpression seedExpr       = Expression.Lambda(body, param2);
                        LambdaExpression accumulateExpr = Expression.Lambda(Expression.Or(param1, body), param1, param2);
                        param2 = Expression.Parameter(typeof(bool), "b");
                        body   = Expression.Or(param1, param2);
                        LambdaExpression recursiveAccumulateExpr = Expression.Lambda(body, param1, param2);

                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "All":
                    {
                        ParameterExpression param1   = Expression.Parameter(typeof(bool), "a");
                        LambdaExpression    predExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[1]);
                        ParameterExpression param2   = predExpr.Parameters[0];

                        Expression       body           = predExpr.Body;
                        LambdaExpression seedExpr       = Expression.Lambda(body, param2);
                        LambdaExpression accumulateExpr = Expression.Lambda(Expression.And(param1, body), param1, param2);
                        param2 = Expression.Parameter(typeof(bool), "b");
                        body   = Expression.And(param1, param2);
                        LambdaExpression recursiveAccumulateExpr = Expression.Lambda(body, param1, param2);

                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "First":
                    {
                        ParameterExpression param1 = Expression.Parameter(sourceElemType, "a");
                        ParameterExpression param2 = Expression.Parameter(sourceElemType, "e");

                        LambdaExpression seedExpr                = Expression.Lambda(param2, param2);
                        LambdaExpression accumulateExpr          = Expression.Lambda(param1, param1, param2);
                        LambdaExpression recursiveAccumulateExpr = accumulateExpr;

                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "Last":
                    {
                        ParameterExpression param1 = Expression.Parameter(sourceElemType, "a");
                        ParameterExpression param2 = Expression.Parameter(sourceElemType, "e");

                        LambdaExpression seedExpr                = Expression.Lambda(param2, param2);
                        LambdaExpression accumulateExpr          = Expression.Lambda(param2, param1, param2);
                        LambdaExpression recursiveAccumulateExpr = accumulateExpr;

                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "Sum":
                    {
                        ParameterExpression param1;
                        ParameterExpression param2;
                        Expression          arg2;
                        if (mInfo.GetParameters().Length == 1)
                        {
                            param2 = Expression.Parameter(sourceElemType, "e");
                            arg2   = param2;
                        }
                        else
                        {
                            LambdaExpression selectExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[1]);
                            param2 = selectExpr.Parameters[0];
                            arg2   = selectExpr.Body;
                        }

                        Expression abody, sbody;
                        if (arg2.Type.IsGenericType)
                        {
                            param1 = Expression.Parameter(arg2.Type.GetGenericArguments()[0], "a");
                            MethodInfo accumulateInfo = typeof(HpcLinqVertex).GetMethod(
                                "SumAccumulate",
                                new Type[] { param1.Type, arg2.Type });
                            sbody = Expression.Constant(0, param1.Type);
                            sbody = Expression.Call(accumulateInfo, sbody, arg2);
                            abody = Expression.Call(accumulateInfo, param1, arg2);
                        }
                        else
                        {
                            param1 = Expression.Parameter(arg2.Type, "a");
                            sbody  = arg2;
                            abody  = Expression.AddChecked(param1, arg2);
                        }

                        LambdaExpression seedExpr       = Expression.Lambda(sbody, param2);
                        LambdaExpression accumulateExpr = Expression.Lambda(abody, param1, param2);
                        param2 = Expression.Parameter(param1.Type, "b");
                        Expression       rbody = Expression.AddChecked(param1, param2);
                        LambdaExpression recursiveAccumulateExpr = Expression.Lambda(rbody, param1, param2);
                        Expression       fbody           = Expression.Convert(param1, arg2.Type);
                        LambdaExpression finalReduceExpr = Expression.Lambda(fbody, param1);
                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr,
                                                     recursiveAccumulateExpr, finalReduceExpr));
                    }

                    case "Max":
                    case "Min":
                    {
                        ParameterExpression param2;
                        Expression          abody;
                        if (mInfo.GetParameters().Length == 1)
                        {
                            param2 = Expression.Parameter(sourceElemType, "e");
                            abody  = param2;
                        }
                        else
                        {
                            LambdaExpression selectExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[1]);
                            param2 = selectExpr.Parameters[0];
                            abody  = selectExpr.Body;
                        }

                        ParameterExpression param1 = Expression.Parameter(abody.Type, "a");
                        Expression          sbody  = abody;
                        MethodInfo          accumulateInfo;
                        string methodName = (mInfo.Name == "Max") ? "MaxAccumulate" : "MinAccumulate";
                        if (mInfo.IsGenericMethod && (mInfo.GetParameters().Length == 1))
                        {
                            accumulateInfo = typeof(HpcLinqVertex).GetMethod(methodName + "Generic");
                            accumulateInfo = accumulateInfo.MakeGenericMethod(sourceElemType);
                        }
                        else
                        {
                            accumulateInfo = typeof(HpcLinqVertex).GetMethod(
                                methodName,
                                new Type[] { param1.Type, abody.Type });
                        }
                        abody = Expression.Call(accumulateInfo, param1, abody);

                        LambdaExpression seedExpr       = Expression.Lambda(sbody, param2);
                        LambdaExpression accumulateExpr = Expression.Lambda(abody, param1, param2);
                        param2 = Expression.Parameter(param1.Type, "b");
                        Expression       rbody = Expression.Call(accumulateInfo, param1, param2);
                        LambdaExpression recursiveAccumulateExpr = Expression.Lambda(rbody, param1, param2);
                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "Aggregate":
                    {
                        ParameterExpression elemParam = Expression.Parameter(sourceElemType, "e");
                        LambdaExpression    accumulateExpr;
                        LambdaExpression    seedExpr;
                        if (mcExpr.Arguments.Count == 2)
                        {
                            accumulateExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[1]);
                            seedExpr       = Expression.Lambda(elemParam, elemParam);
                        }
                        else
                        {
                            accumulateExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[2]);
                            object         seedVal = evaluator.Eval(mcExpr.Arguments[1]);
                            Expression     body    = Expression.Constant(seedVal, seedVal.GetType());
                            ParameterSubst subst   = new ParameterSubst(accumulateExpr.Parameters[0], body);
                            body     = subst.Visit(accumulateExpr.Body);
                            seedExpr = Expression.Lambda(body, accumulateExpr.Parameters[1]);
                        }
                        if (!HpcLinqExpression.IsAssociative(accumulateExpr))
                        {
                            return(null);
                        }
                        LambdaExpression recursiveAccumulateExpr = HpcLinqExpression.GetAssociativeCombiner(accumulateExpr);
                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, null));
                    }

                    case "Average":
                    {
                        ParameterExpression param2;
                        Expression          abody;
                        if (mInfo.GetParameters().Length == 1)
                        {
                            param2 = Expression.Parameter(sourceElemType, "e");
                            abody  = param2;
                        }
                        else
                        {
                            LambdaExpression selectExpr = HpcLinqExpression.GetLambda(mcExpr.Arguments[1]);
                            param2 = selectExpr.Parameters[0];
                            abody  = selectExpr.Body;
                        }
                        Type aggValueType = abody.Type;
                        if (aggValueType == typeof(int) ||
                            aggValueType == typeof(int?))
                        {
                            aggValueType = typeof(long);
                        }
                        else if (aggValueType == typeof(long?))
                        {
                            aggValueType = typeof(long);
                        }
                        else if (aggValueType == typeof(float) ||
                                 aggValueType == typeof(float?))
                        {
                            aggValueType = typeof(double);
                        }
                        else if (aggValueType == typeof(double?))
                        {
                            aggValueType = typeof(double);
                        }
                        else if (aggValueType == typeof(decimal?))
                        {
                            aggValueType = typeof(decimal);
                        }

                        Type sumAndCountType               = typeof(AggregateValue <>).MakeGenericType(aggValueType);
                        ParameterExpression param1         = Expression.Parameter(sumAndCountType, "a");
                        MethodInfo          accumulateInfo = typeof(HpcLinqVertex).GetMethod(
                            "AverageAccumulate",
                            new Type[] { sumAndCountType, abody.Type });

                        // Seed:
                        Expression sbody = Expression.New(sumAndCountType);
                        sbody = Expression.Call(accumulateInfo, sbody, abody);
                        LambdaExpression seedExpr = Expression.Lambda(sbody, param2);

                        // Accumulate:
                        abody = Expression.Call(accumulateInfo, param1, abody);
                        LambdaExpression accumulateExpr = Expression.Lambda(abody, param1, param2);

                        // RecursiveAccumulate:
                        param2 = Expression.Parameter(param1.Type, "b");
                        PropertyInfo     valueInfo  = sumAndCountType.GetProperty("Value");
                        PropertyInfo     countInfo  = sumAndCountType.GetProperty("Count");
                        Expression       sumExpr1   = Expression.Property(param1, valueInfo);
                        Expression       countExpr1 = Expression.Property(param1, countInfo);
                        Expression       sumExpr2   = Expression.Property(param2, valueInfo);
                        Expression       countExpr2 = Expression.Property(param2, countInfo);
                        Expression       sumExpr    = Expression.AddChecked(sumExpr1, sumExpr2);
                        Expression       countExpr  = Expression.AddChecked(countExpr1, countExpr2);
                        ConstructorInfo  cinfo      = sumAndCountType.GetConstructor(new Type[] { sumExpr.Type, countExpr.Type });
                        Expression       rbody      = Expression.New(cinfo, sumExpr, countExpr);
                        LambdaExpression recursiveAccumulateExpr = Expression.Lambda(rbody, param1, param2);

                        // FinalReduce:
                        if (sumExpr1.Type == typeof(long))
                        {
                            sumExpr1 = Expression.Convert(sumExpr1, typeof(double));
                        }
                        Expression fbody = Expression.Divide(sumExpr1, countExpr1);
                        fbody = Expression.Convert(fbody, resultType);
                        if (resultType.IsGenericType)
                        {
                            Expression zeroExpr = Expression.Constant(0, typeof(long));
                            Expression condExpr = Expression.GreaterThan(countExpr1, zeroExpr);
                            Expression nullExpr = Expression.Constant(null, resultType);
                            fbody = Expression.Condition(condExpr, fbody, nullExpr);
                        }
                        LambdaExpression finalReduceExpr = Expression.Lambda(fbody, param1);
                        return(new DecompositionInfo(mcExpr, seedExpr, accumulateExpr, recursiveAccumulateExpr, finalReduceExpr));
                    }

                    case "Contains":
                    {
                        decomposerType = typeof(ContainsDecomposition <>).MakeGenericType(sourceElemType);
                        break;
                    }

                    case "Distinct":
                    {
                        decomposerType = typeof(DistinctDecomposition <>).MakeGenericType(sourceElemType);
                        break;
                    }

                    default:
                    {
                        return(null);
                    }
                    }
                }
            }

            if (decomposerType == null)
            {
                return(null);
            }

            Type implementedInterface = null;

            Type[] interfaces = decomposerType.GetInterfaces();
            foreach (Type intf in interfaces)
            {
                if (intf.GetGenericTypeDefinition() == typeof(IDecomposable <, ,>))
                {
                    if (implementedInterface != null)
                    {
                        throw new DryadLinqException("Decomposition class can implement only one decomposable interface.");
                    }
                    implementedInterface = intf;
                }
            }

            if (implementedInterface == null ||
                implementedInterface.GetGenericArguments().Length != 3)
            {
                throw new DryadLinqException("Decomposition class " + decomposerType.FullName +
                                             "must implement IDecomposable<,,>");
            }

            // The second type of the implemented interface definition is the accumulatorType.
            Type accumulatorType = implementedInterface.GetGenericArguments()[1];

            // Now check that all the types match up.
            Type decomposerInterface = typeof(IDecomposable <, ,>).MakeGenericType(
                sourceElemType, accumulatorType, resultType);

            if (!decomposerInterface.IsAssignableFrom(decomposerType))
            {
                throw new DryadLinqException("Decomposition class must match the function that it decorates.");
            }
            if (decomposerType.ContainsGenericParameters)
            {
                if (decomposerType.GetGenericArguments().Length != 1 ||
                    !decomposerType.GetGenericArguments()[0].IsGenericParameter)
                {
                    throw new DryadLinqException(decomposerType.Name + " must match the function it annotates.");
                }
                decomposerType = decomposerType.MakeGenericType(sourceElemType);
            }
            if (decomposerType.GetConstructor(Type.EmptyTypes) == null)
            {
                throw new DryadLinqException("Decomposition class must have a default constructor.");
            }

            // Add to the codegen a call of the static Initializer of decomposerType
            Expression[] args = new Expression[mcExpr.Arguments.Count - 1];
            for (int i = 0; i < args.Length; i++)
            {
                args[i] = Expression.Convert(mcExpr.Arguments[i + 1], typeof(object));
            }
            Expression          stateExpr      = Expression.NewArrayInit(typeof(object), args);
            string              decomposerName = codeGen.AddDecompositionInitializer(decomposerType, stateExpr);
            ParameterExpression decomposer     = Expression.Parameter(decomposerType, decomposerName);

            // Seed: TSource => TAccumulate
            MethodInfo          seedInfo1 = decomposerType.GetMethod("Seed");
            ParameterExpression p2        = Expression.Parameter(sourceElemType, "e");
            Expression          sbody1    = Expression.Call(decomposer, seedInfo1, p2);
            LambdaExpression    seedExpr1 = Expression.Lambda(sbody1, p2);

            // Accumulate: (TAccumulate, TSource) => TAccumulate
            MethodInfo          accumulateInfo1 = decomposerType.GetMethod("Accumulate");
            ParameterExpression p1              = Expression.Parameter(accumulatorType, "a");
            Expression          abody1          = Expression.Call(decomposer, accumulateInfo1, p1, p2);
            LambdaExpression    accumulateExpr1 = Expression.Lambda(abody1, p1, p2);

            // RecursiveAccumulate: (TAccumulate, TAccumulate) => TAccumulate
            MethodInfo recursiveAccumulateInfo1 = decomposerType.GetMethod("RecursiveAccumulate");

            p2 = Expression.Parameter(accumulatorType, "e");
            Expression       rbody1 = Expression.Call(decomposer, recursiveAccumulateInfo1, p1, p2);
            LambdaExpression recursiveAccumulateExpr1 = Expression.Lambda(rbody1, p1, p2);

            // FinalReduce: TAccumulate => TResult
            MethodInfo       finalReduceInfo1 = decomposerType.GetMethod("FinalReduce");
            Expression       fbody1           = Expression.Call(decomposer, finalReduceInfo1, p1);
            LambdaExpression finalReduceExpr1 = Expression.Lambda(fbody1, p1);

            return(new DecompositionInfo(mcExpr, seedExpr1, accumulateExpr1, recursiveAccumulateExpr1, finalReduceExpr1));
        }
        private static bool GetDecompositionInfoList(ParameterExpression keyParam,
                                                     ParameterExpression groupParam,
                                                     Expression expr,
                                                     List <DecompositionInfo> infoList,
                                                     HpcLinqCodeGen codeGen)
        {
            IEnumerable <Expression> argList = null;

            if (HpcLinqExpression.IsConstant(expr))
            {
                return(true);
            }
            else if (expr is BinaryExpression)
            {
                BinaryExpression be = (BinaryExpression)expr;
                argList = new Expression[] { be.Left, be.Right };
            }
            else if (expr is UnaryExpression)
            {
                UnaryExpression ue = (UnaryExpression)expr;
                return(GetDecompositionInfoList(keyParam, groupParam, ue.Operand, infoList, codeGen));
            }
            else if (expr is ConditionalExpression)
            {
                ConditionalExpression ce = (ConditionalExpression)expr;
                argList = new Expression[] { ce.Test, ce.IfTrue, ce.IfFalse };
            }
            else if (expr is MethodCallExpression)
            {
                MethodCallExpression mcExpr = (MethodCallExpression)expr;
                DecompositionInfo    dinfo  = GetDecompositionInfo(groupParam, mcExpr, codeGen);
                if (dinfo != null)
                {
                    infoList.Add(dinfo);
                    return(true);
                }
                if (mcExpr.Object != null)
                {
                    bool isDecomposed = GetDecompositionInfoList(keyParam, groupParam,
                                                                 mcExpr.Object,
                                                                 infoList, codeGen);
                    if (!isDecomposed)
                    {
                        return(false);
                    }
                }
                argList = mcExpr.Arguments;
            }
            else if (expr is NewExpression)
            {
                argList = ((NewExpression)expr).Arguments;
            }
            else if (expr is NewArrayExpression)
            {
                argList = ((NewArrayExpression)expr).Expressions;
            }
            else if (expr is ListInitExpression)
            {
                ListInitExpression li = (ListInitExpression)expr;
                bool isDecomposed     = GetDecompositionInfoList(keyParam, groupParam,
                                                                 li.NewExpression,
                                                                 infoList, codeGen);
                for (int i = 0, n = li.Initializers.Count; i < n; i++)
                {
                    ElementInit ei = li.Initializers[i];
                    foreach (Expression arg in ei.Arguments)
                    {
                        isDecomposed = GetDecompositionInfoList(keyParam, groupParam, arg, infoList, codeGen);
                        if (!isDecomposed)
                        {
                            return(false);
                        }
                    }
                }
                return(true);
            }
            else if (expr is MemberInitExpression)
            {
                MemberInitExpression mi = (MemberInitExpression)expr;
                bool isDecomposed       = GetDecompositionInfoList(keyParam, groupParam,
                                                                   mi.NewExpression,
                                                                   infoList, codeGen);
                if (!isDecomposed)
                {
                    return(false);
                }
                foreach (MemberBinding mb in mi.Bindings)
                {
                    isDecomposed = GetDecompositionInfoList(keyParam, groupParam, mb, infoList, codeGen);
                    if (!isDecomposed)
                    {
                        return(false);
                    }
                }
                return(true);
            }
            else if (keyParam == null)
            {
                while (expr is MemberExpression)
                {
                    MemberExpression me = (MemberExpression)expr;
                    if (me.Expression == groupParam &&
                        me.Member.Name == "Key")
                    {
                        return(true);
                    }
                    expr = me.Expression;
                }
                return(false);
            }
            else
            {
                while (expr is MemberExpression)
                {
                    expr = ((MemberExpression)expr).Expression;
                }
                return(expr == keyParam);
            }

            foreach (var argExpr in argList)
            {
                bool isDecomposed = GetDecompositionInfoList(keyParam, groupParam, argExpr, infoList, codeGen);
                if (!isDecomposed)
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Explain one query node.
        /// </summary>
        /// <param name="plan">Return plan here.</param>
        /// <param name="n">Node to explain.</param>
        internal static void ExplainNode(StringBuilder plan, DryadQueryNode n)
        {
            if (n is DryadTeeNode || n is DryadOutputNode)
            {
                return;
            }
            else if (n is DryadInputNode)
            {
                plan.AppendLine("Input:");
                plan.Append("\t");
                n.BuildString(plan);
                plan.AppendLine();
                return;
            }

            plan.Append(n.m_vertexEntryMethod);
            plan.AppendLine(":");

            HashSet <DryadQueryNode> allchildren = new HashSet <DryadQueryNode>();

            if (n is DryadSuperNode)
            {
                DryadSuperNode        sn      = n as DryadSuperNode;
                List <DryadQueryNode> tovisit = new List <DryadQueryNode>();

                tovisit.Add(sn.RootNode);

                while (tovisit.Count > 0)
                {
                    DryadQueryNode t = tovisit[0];
                    tovisit.RemoveAt(0);
                    if (!(t is DryadSuperNode))
                    {
                        allchildren.Add(t);
                    }
                    foreach (DryadQueryNode tc in t.Children)
                    {
                        if (!allchildren.Contains(tc) && sn.Contains(tc))
                        {
                            tovisit.Add(tc);
                        }
                    }
                }
            }
            else
            {
                allchildren.Add(n);
            }

            foreach (DryadQueryNode nc in allchildren.Reverse())
            {
                Expression    expression = null;                // expression to print
                List <string> additional = new List <string>(); // additional arguments to print
                int           argsToSkip = 0;
                string        methodname = nc.OpName;

                plan.Append("\t");

                if (nc is DryadMergeNode)
                {
                    expression = ((DryadMergeNode)nc).ComparerExpression;
                }
                else if (nc is DryadHashPartitionNode)
                {
                    DryadHashPartitionNode hp = (DryadHashPartitionNode)nc;
                    expression = hp.KeySelectExpression;
                    additional.Add(hp.NumberOfPartitions.ToString());
                }
                else if (nc is DryadGroupByNode)
                {
                    DryadGroupByNode gb = (DryadGroupByNode)nc;
                    expression = gb.KeySelectExpression;
                    if (gb.ElemSelectExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(gb.ElemSelectExpression));
                    }
                    if (gb.ResSelectExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(gb.ResSelectExpression));
                    }
                    if (gb.ComparerExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(gb.ComparerExpression));
                    }
                    if (gb.SeedExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(gb.SeedExpression));
                    }
                    if (gb.AccumulatorExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(gb.AccumulatorExpression));
                    }
                }
                else if (nc is DryadOrderByNode)
                {
                    DryadOrderByNode ob = (DryadOrderByNode)nc;
                    expression = ob.KeySelectExpression;
                    if (ob.ComparerExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(ob.ComparerExpression));
                    }
                }
                else if (nc is DryadWhereNode)
                {
                    expression = ((DryadWhereNode)nc).WhereExpression;
                }
                else if (nc is DryadSelectNode)
                {
                    DryadSelectNode s = (DryadSelectNode)nc;
                    expression = s.SelectExpression;
                    if (s.ResultSelectExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(s.ResultSelectExpression));
                    }
                }
                else if (nc is DryadAggregateNode)
                {
                    DryadAggregateNode a = (DryadAggregateNode)nc;
                    expression = a.FuncLambda;
                    if (a.SeedExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(a.SeedExpression));
                    }
                    if (a.ResultLambda != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(a.ResultLambda));
                    }
                }
                else if (nc is DryadPartitionOpNode)
                {
                    expression = ((DryadPartitionOpNode)nc).ControlExpression;
                }
                else if (nc is DryadJoinNode)
                {
                    DryadJoinNode j = (DryadJoinNode)nc;
                    expression = j.OuterKeySelectorExpression;
                    additional.Add(HpcLinqExpression.Summarize(j.InnerKeySelectorExpression));
                    additional.Add(HpcLinqExpression.Summarize(j.ResultSelectorExpression));
                    if (j.ComparerExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(j.ComparerExpression));
                    }
                }
                else if (nc is DryadDistinctNode)
                {
                    expression = ((DryadDistinctNode)nc).ComparerExpression;
                }
                else if (nc is DryadContainsNode)
                {
                    DryadContainsNode c = (DryadContainsNode)nc;
                    expression = c.ValueExpression;
                    if (c.ComparerExpression != null)
                    {
                        additional.Add(HpcLinqExpression.Summarize(c.ComparerExpression));
                    }
                }
                else if (nc is DryadBasicAggregateNode)
                {
                    expression = ((DryadBasicAggregateNode)nc).SelectExpression;
                }
                else if (nc is DryadConcatNode)
                // nothing to do
                {
                }
                else if (nc is DryadSetOperationNode)
                {
                    expression = ((DryadSetOperationNode)nc).ComparerExpression;
                }
                else if (nc is DryadRangePartitionNode)
                {
                    DryadRangePartitionNode r = (DryadRangePartitionNode)nc;
                    expression = r.CountExpression;
                    // TODO: there's some other possible interesting info
                }
                else if (nc is DryadApplyNode)
                {
                    expression = ((DryadApplyNode)nc).LambdaExpression;
                }

                else if (nc is DryadForkNode)
                {
                    expression = ((DryadForkNode)nc).ForkLambda;
                }

                else if (nc is DryadTeeNode)
                {
                    // nothing
                }
                else if (nc is DryadDynamicNode)
                {
                    // nothing
                }
                else
                {
                    expression = nc.QueryExpression;
                }

                if (expression is MethodCallExpression)
                {
                    MethodCallExpression mc = (MethodCallExpression)expression;
                    methodname = mc.Method.Name;  // overwrite methodname

                    // determine which arguments to skip
                    #region LINQMETHODS
                    switch (mc.Method.Name)
                    {
                    case "Aggregate":
                    case "AggregateAsQuery":
                    case "Select":
                    case "LongSelect":
                    case "SelectMany":
                    case "LongSelectMany":
                    case "OfType":
                    case "Where":
                    case "LongWhere":
                    case "First":
                    case "FirstOrDefault":
                    case "FirstAsQuery":
                    case "Single":
                    case "SingleOrDefault":
                    case "SingleAsQuery":
                    case "Last":
                    case "LastOrDefault":
                    case "LastAsQuery":
                    case "Distinct":
                    case "Any":
                    case "AnyAsQuery":
                    case "All":
                    case "AllAsQuery":
                    case "Count":
                    case "CountAsQuery":
                    case "LongCount":
                    case "LongCountAsQuery":
                    case "Sum":
                    case "SumAsQuery":
                    case "Min":
                    case "MinAsQuery":
                    case "Max":
                    case "MaxAsQuery":
                    case "Average":
                    case "AverageAsQuery":
                    case "GroupBy":
                    case "OrderBy":
                    case "OrderByDescending":
                    case "ThenBy":
                    case "ThenByDescending":
                    case "Take":
                    case "TakeWhile":
                    case "LongTakeWhile":
                    case "Skip":
                    case "SkipWhile":
                    case "LongSkipWhile":
                    case "Contains":
                    case "ContainsAsQuery":
                    case "Reverse":
                    case "Merge":
                    case "HashPartition":
                    case "RangePartition":
                    case "Fork":
                    case "ForkChoose":
                    case "AssumeHashPartition":
                    case "AssumeRangePartition":
                    case "AssumeOrderBy":
                    case "ToPartitionedTableLazy":
                    case "AddCacheEntry":
                    case "SlidingWindow":
                    case "SelectWithPartitionIndex":
                    case "ApplyWithPartitionIndex":
                        argsToSkip = 1;
                        break;

                    case "Join":
                    case "GroupJoin":
                    case "Concat":
                    case "MultiConcat":
                    case "Union":
                    case "Intersect":
                    case "Except":
                    case "SequenceEqual":
                    case "SequenceEqualAsQuery":
                    case "Zip":
                        argsToSkip = 2;
                        break;

                    case "Apply":
                    case "ApplyPerPartition":
                        if (mc.Arguments.Count < 3)
                        {
                            argsToSkip = 1;
                        }
                        else
                        {
                            argsToSkip = 2;
                        }
                        break;

                    default:
                        throw DryadLinqException.Create(HpcLinqErrorCode.OperatorNotSupported,
                                                        String.Format(SR.OperatorNotSupported, mc.Method.Name),
                                                        expression);
                    }
                    #endregion

                    plan.Append(methodname);
                    plan.Append("(");

                    int argno = 0;
                    foreach (var arg in mc.Arguments)
                    {
                        argno++;
                        if (argno <= argsToSkip)
                        {
                            continue;
                        }
                        if (argno > argsToSkip + 1)
                        {
                            plan.Append(",");
                        }
                        plan.Append(HpcLinqExpression.Summarize(arg));
                    }
                    plan.AppendLine(")");
                }
                else
                {
                    // expression is not methodcall
                    plan.Append(methodname);
                    plan.Append("(");
                    if (expression != null)
                    {
                        plan.Append(HpcLinqExpression.Summarize(expression));
                    }
                    foreach (string e in additional)
                    {
                        plan.Append(",");
                        plan.Append(e);
                    }
                    plan.AppendLine(")");
                }
            }
        }
Beispiel #9
0
        // Return true iff EPG is modified by this method.
        public bool RewriteOne(int idx)
        {
            QueryNodeInfo curNode = this.m_nodeInfos[idx];

            if (curNode.OperatorName == "Where" && !curNode.children[0].child.IsForked)
            {
                LambdaExpression lambda = HpcLinqExpression.GetLambda(((MethodCallExpression)curNode.queryExpression).Arguments[1]);
                if (lambda.Type.GetGenericArguments().Length == 2)
                {
                    QueryNodeInfo child = curNode.children[0].child;
                    string[]      names = new string[] { "OrderBy", "Distinct", "RangePartition", "HashPartition" };
                    if (names.Contains(child.OperatorName))
                    {
                        curNode.Swap(child);
                        return(true);
                    }
                    if (child.OperatorName == "Concat")
                    {
                        curNode.Delete();
                        for (int i = 0; i < child.children.Count; i++)
                        {
                            NodeInfoEdge  edge = child.children[i];
                            QueryNodeInfo node = curNode.Clone();
                            this.m_nodeInfos.Add(node);
                            edge.Insert(node);
                        }
                        return(true);
                    }
                }
            }
            else if ((curNode.OperatorName == "Select" || curNode.OperatorName == "SelectMany") &&
                     !curNode.children[0].child.IsForked)
            {
                LambdaExpression lambda = HpcLinqExpression.GetLambda(((MethodCallExpression)curNode.queryExpression).Arguments[1]);
                if (lambda.Type.GetGenericArguments().Length == 2)
                {
                    QueryNodeInfo child = curNode.children[0].child;
                    if (child.OperatorName == "Concat")
                    {
                        curNode.Delete();
                        for (int i = 0; i < child.children.Count; i++)
                        {
                            NodeInfoEdge  edge = child.children[i];
                            QueryNodeInfo node = curNode.Clone();
                            this.m_nodeInfos.Add(node);
                            edge.Insert(node);
                        }
                        return(true);
                    }
                }
            }
            else if (curNode.OperatorName == "Take" && !curNode.children[0].child.IsForked)
            {
                QueryNodeInfo child = curNode.children[0].child;
                if (child.OperatorName == "Select")
                {
                    QueryNodeInfo cchild = child.children[0].child;
                    if (cchild.OperatorName != "GroupBy")
                    {
                        curNode.Swap(child);
                        return(true);
                    }
                }
            }
            else if ((curNode.OperatorName == "Contains" ||
                      curNode.OperatorName == "ContainsAsQuery" ||
                      curNode.OperatorName == "All" ||
                      curNode.OperatorName == "AllAsQuery" ||
                      curNode.OperatorName == "Any" ||
                      curNode.OperatorName == "AnyAsQuery") &&
                     !curNode.children[0].child.IsForked)
            {
                QueryNodeInfo child = curNode.children[0].child;
                string[]      names = new string[] { "OrderBy", "Distinct", "RangePartition", "HashPartition" };
                if (names.Contains(child.OperatorName))
                {
                    child.Delete();
                    return(true);
                }
            }
            return(false);
        }