internal HasIncrement(IncrementStatement incrementStatement)
 {
     this.incrementStatement = incrementStatement;
 }
 protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie)
 {
     // Insert an Increment statement to support Sequential loops
     // if we find the pattern:
     // forwardExpr = ReplicateOp_Divide.UsesAverageConditional(backwardExpr[index], marginalExpr, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index]);
     if (Recognizer.IsStaticMethod(imie, typeof(ReplicateOp_Divide), "UsesAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[1];
         IExpression          indexExpr    = imie.Arguments[2];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[3];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = Replicate2BufferOp.UsesAverageConditional(backwardExpr, *, marginalExpr, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // marginalExpr = MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index]);
     if (Recognizer.IsStaticMethod(imie, typeof(Replicate2BufferOp), "UsesAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indexExpr    = imie.Arguments[3];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[4];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, Builder.ArrayIndex(backwardExpr, indexExpr));
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = JaggedSubarrayOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(JaggedSubarrayOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indexExpr    = imie.Arguments[4];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[5];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             IExpression[] args2             = new IExpression[] { marginalExpr, forwardExpr, backwardExpr, indicesExpr, indexExpr };
             Type[]        argTypes          = Array.ConvertAll(args2, e => e.GetExpressionType());
             Exception     exception;
             MethodInfo    method = (MethodInfo)Reflection.Invoker.GetBestMethod(itr.DotNetType, "MarginalIncrement",
                                                                                 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, argTypes, out exception);
             if (method == null)
             {
                 Error("Cannot find a compatible MarginalIncrement method for JaggedSubarrayOp", exception);
             }
             else
             {
                 IExpression rhs       = Builder.StaticGenericMethod(method, args2);
                 IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
                 var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
                 var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
                 context.OutputAttributes.Set(increment, attr);
                 onUpdate[backwardDecl] = increment;
             }
         }
     }
     // if we find the pattern:
     // forwardExpr = JaggedSubarrayWithMarginalOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrementItems(backwardExpr[index], forwardExpr,  indices, index, marginalExpr)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(JaggedSubarrayWithMarginalOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indexExpr    = imie.Arguments[4];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[5];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             IExpression[] args2             = new IExpression[] { backwardExpr, forwardExpr, indicesExpr, indexExpr, marginalExpr };
             Type[]        argTypes          = Array.ConvertAll(args2, e => e.GetExpressionType());
             Exception     exception;
             MethodInfo    method = (MethodInfo)Reflection.Invoker.GetBestMethod(itr.DotNetType, "MarginalIncrementItems",
                                                                                 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, argTypes, out exception);
             if (method == null)
             {
                 Error("Cannot find a compatible MarginalIncrementItems method for JaggedSubarrayWithMarginalOp", exception);
             }
             else
             {
                 IExpression rhs       = Builder.StaticGenericMethod(method, args2);
                 IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
                 var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
                 var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
                 context.OutputAttributes.Set(increment, attr);
                 object backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
                 onUpdate[backwardDecl] = increment;
                 IVariableDeclaration marginalVar = Recognizer.GetVariableDeclaration(marginalExpr);
                 suppressUpdate[marginalVar] = attr;
             }
             var indicesVar = Recognizer.GetDeclaration(indicesExpr);
             if (indicesVar != null)
             {
                 DistributedCommunicationExpression dce = context.GetAttribute <DistributedCommunicationExpression>(indicesVar);
                 if (dce != null)
                 {
                     context.OutputAttributes.Set(imie, dce);
                 }
             }
         }
     }
     // if we find the pattern:
     // backwardExpr = JaggedSubarrayWithMarginalOp<>.ArrayAverageConditional(forwardExpr, marginalExpr, backwardExpr)
     // then when forwardExpr is updated, we insert the following statement:
     // MarginalIncrementArray
     if (Recognizer.IsStaticGenericMethod(imie, typeof(JaggedSubarrayWithMarginalOp <>), "ArrayAverageConditional"))
     {
         IExpression forwardExpr  = imie.Arguments[0];
         IExpression marginalExpr = imie.Arguments[1];
         IExpression backwardExpr = imie.Arguments[2];
         if (true)
         {
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             IExpression[] args2             = new IExpression[] { forwardExpr, backwardExpr, marginalExpr };
             Type[]        argTypes          = Array.ConvertAll(args2, e => e.GetExpressionType());
             Exception     exception;
             MethodInfo    method = (MethodInfo)Reflection.Invoker.GetBestMethod(itr.DotNetType, "MarginalIncrementArray",
                                                                                 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, argTypes, out exception);
             if (method == null)
             {
                 Error("Cannot find a compatible MarginalIncrementArray method for JaggedSubarrayWithMarginalOp", exception);
             }
             else
             {
                 IExpression rhs       = Builder.StaticGenericMethod(method, args2);
                 IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
                 var         attr      = new IncrementStatement(null, false);
                 context.OutputAttributes.Set(increment, attr);
                 object forwardDecl = Recognizer.GetArrayDeclaration(forwardExpr);
                 onUpdate[forwardDecl] = increment;
             }
             IVariableDeclaration marginalVar = Recognizer.GetVariableDeclaration(marginalExpr);
             // only suppress when we also have MarginalIncrementItems
             //suppressUpdate.Add(marginalVar);
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsOp <>), "ItemsAverageConditional") ||
         Recognizer.IsStaticGenericMethod(imie, typeof(GetJaggedItemsOp <>), "ItemsAverageConditional") ||
         Recognizer.IsStaticGenericMethod(imie, typeof(GetDeepJaggedItemsOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indexExpr    = imie.Arguments[4];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[5];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, indexExpr);
             //IStatement increment = Builder.ExprStatement(rhs);
             IStatement increment = Builder.AssignStmt(marginalExpr, rhs);
             var        seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var        attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsWithDictionaryOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          dictExpr     = imie.Arguments[4];
         IExpression          indexExpr    = imie.Arguments[5];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[6];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, dictExpr, indexExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // partialExpr = GetItemsOp2<>.Partial(backwardExpr[index], to_array, indices, index, partialExpr);
     // then when backwardExpr is updated, we insert the following statement:
     // to_array[indices[index]] = ArrayIncrement(partialExpr, backwardExpr[index])
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsOp2 <>), "Partial"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          to_array     = imie.Arguments[1];
         IExpression          indicesExpr  = imie.Arguments[2];
         IExpression          indexExpr    = imie.Arguments[3];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[4];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("ArrayIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression resultExpr = Builder.ArrayIndex(to_array, Builder.ArrayIndex(indicesExpr, indexExpr));
             IExpression rhs        = Builder.StaticGenericMethod(method, forwardExpr, backwardExpr, resultExpr);
             IStatement  increment  = Builder.AssignStmt(resultExpr, rhs);
             var         seq        = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr       = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsJaggedOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, indices2, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, indices2, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromJaggedOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indices2Expr = imie.Arguments[4];
         IExpression          indexExpr    = imie.Arguments[5];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[6];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, indices2Expr, indexExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsDeepJaggedOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, indices2, indices3, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, indices2, indices3, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromDeepJaggedOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indices2Expr = imie.Arguments[4];
         IExpression          indices3Expr = imie.Arguments[5];
         IExpression          indexExpr    = imie.Arguments[6];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[7];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, indices2Expr, indices3Expr, indexExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     return(base.ConvertMethodInvoke(imie));
 }